Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
112 andreas 1
/*
264 andreas 2
 * Copyright (C) 2022 to 2023 by Andreas Theofilu <andreas@theosys.at>
112 andreas 3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software Foundation,
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
17
 */
18
 
19
#include <fstream>
117 andreas 20
#include <functional>
21
#include <iostream>
22
#include <cstdint>
23
#include <filesystem>
112 andreas 24
 
25
#include <sys/socket.h>
26
#include <netinet/in.h>
27
#include <string.h>
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <sys/stat.h>
235 andreas 31
#ifndef __MACH__
112 andreas 32
#include <sys/sendfile.h>
235 andreas 33
#endif
112 andreas 34
#include <fcntl.h>
35
#include <unistd.h>
117 andreas 36
#include <sys/socket.h>
37
#include <netinet/in.h>
38
#include <netdb.h>
39
#include <arpa/inet.h>
112 andreas 40
 
41
#include "tfsfreader.h"
42
#include "tconfig.h"
43
#include "terror.h"
113 andreas 44
#include "readtp4.h"
112 andreas 45
 
125 andreas 46
#if __cplusplus < 201402L
47
#   error "This module requires at least C++ 14 standard!"
48
#else
49
#   if __cplusplus < 201703L
50
#       include <experimental/filesystem>
51
        namespace fs = std::experimental::filesystem;
52
#       warning "Support for C++14 and experimental filesystem will be removed in a future version!"
53
#   else
54
#       include <filesystem>
55
#       ifdef __ANDROID__
56
            namespace fs = std::__fs::filesystem;
57
#       else
58
            namespace fs = std::filesystem;
59
#       endif
60
#   endif
61
#endif
62
 
112 andreas 63
#define FTP_PORT    21
64
 
65
#define FTP_CMD_USER    0
66
#define FTP_CMD_PASS    1
67
#define FTP_CMD_PASV    2
68
#define FTP_CMD_TYPE    3
69
#define FTP_CMD_RETR    4
70
#define FTP_CMD_QUIT    5
71
 
72
using std::string;
73
using std::vector;
117 andreas 74
using std::bind;
125 andreas 75
/*
119 andreas 76
#if __GNUC__ < 9 && !defined(__ANDROID__)
77
   #if __cplusplus < 201703L
78
      #warning "Your C++ compiler seems to have no support for C++17 standard!"
79
   #endif
80
   #include <experimental/filesystem>
81
   namespace fs = std::experimental::filesystem;
82
#else
83
#  ifdef __ANDROID__
84
#   if _LIBCPP_STD_VER >= 17
85
#       include <filesystem>
86
        namespace fs = std::__fs::filesystem;
87
#   else
88
#       include <experimental/filesystem>
89
        namespace fs = std::__fs::filesystem;
90
#   endif
91
#  else
92
#   include <filesystem>
93
    namespace fs = std::filesystem;
94
#  endif
95
#endif
125 andreas 96
*/
117 andreas 97
 
120 andreas 98
std::function<int (off64_t xfered)> TFsfReader::_progress{nullptr};
99
 
112 andreas 100
TFsfReader::TFsfReader()
101
{
102
    DECL_TRACER("TFsfReader::TFsfReader()");
103
 
104
}
105
 
106
TFsfReader::~TFsfReader()
107
{
108
    DECL_TRACER("TFsfReader::~TFsfReader()");
109
 
117 andreas 110
    if (mFtpLib)
111
        delete mFtpLib;
112 andreas 112
}
113
 
117 andreas 114
bool TFsfReader::copyOverFTP(const string& fname, const string& target)
112 andreas 115
{
179 andreas 116
    DECL_TRACER("TFsfReader::copyOverFTP(const string& fname, const string& target)");
112 andreas 117
 
117 andreas 118
    if (mFtpLib)
119
        delete mFtpLib;
112 andreas 120
 
117 andreas 121
    mFtpLib = new ftplib();
137 andreas 122
    mFtpLib->regLogging(bind(&TFsfReader::logging, this, std::placeholders::_1, std::placeholders::_2));
112 andreas 123
 
117 andreas 124
    if (TConfig::getFtpPassive())
125
        mFtpLib->SetConnmode(ftplib::pasv);
112 andreas 126
    else
117 andreas 127
        mFtpLib->SetConnmode(ftplib::port);
112 andreas 128
 
120 andreas 129
    mFtpLib->SetCallbackLogFunction(&TFsfReader::callbackLog);      // Print some debugging messages
130
    mFtpLib->SetCallbackErrorFunction(&TFsfReader::callbackError);  // Print errors or info's
131
    mFtpLib->SetCallbackXferFunction(&TFsfReader::callbackXfer);    // This is the progress
264 andreas 132
    mFtpLib->SetCallbackBytes(10000L);                              // This tells the progress to be called every 10Kb
117 andreas 133
    string scon = TConfig::getController() + ":21";
134
    MSG_DEBUG("Trying to connect to " << scon);
115 andreas 135
 
117 andreas 136
    if (!mFtpLib->Connect(scon.c_str()))
115 andreas 137
    {
117 andreas 138
        delete mFtpLib;
139
        mFtpLib = nullptr;
112 andreas 140
        return false;
115 andreas 141
    }
112 andreas 142
 
117 andreas 143
    string sUser = TConfig::getFtpUser();
144
    string sPass = TConfig::getFtpPassword();
179 andreas 145
    MSG_DEBUG("Trying to login <" << sUser << ", ********>");
112 andreas 146
 
117 andreas 147
    if (!mFtpLib->Login(sUser.c_str(), sPass.c_str()))
115 andreas 148
    {
117 andreas 149
        delete mFtpLib;
150
        mFtpLib = nullptr;
112 andreas 151
        return false;
115 andreas 152
    }
112 andreas 153
 
117 andreas 154
    MSG_DEBUG("Trying to download file " << fname << " to " << target);
112 andreas 155
 
117 andreas 156
    if (!mFtpLib->Get(target.c_str(), fname.c_str(), ftplib::image))
112 andreas 157
    {
117 andreas 158
        MSG_ERROR("Error downloading file " << fname);
159
        delete mFtpLib;
160
        mFtpLib = nullptr;
112 andreas 161
        return false;
162
    }
163
 
117 andreas 164
    MSG_TRACE("File " << fname << " successfully downloaded to " << target << ".");
165
    mFtpLib->Quit();
112 andreas 166
    return true;
167
}
168
 
117 andreas 169
bool TFsfReader::unpack(const string& fname, const string& path)
112 andreas 170
{
117 andreas 171
    DECL_TRACER("TFsfReader::unpack(const string& fname, const string& path)");
112 andreas 172
 
117 andreas 173
    if (fname.empty() || path.empty())
112 andreas 174
    {
117 andreas 175
        MSG_ERROR("Invalid parameters!");
112 andreas 176
        return false;
177
    }
178
 
117 andreas 179
    reader::ReadTP4 readtp4(fname, path);
115 andreas 180
 
117 andreas 181
    if (!readtp4.isReady())
112 andreas 182
        return false;
183
 
117 andreas 184
    // We must delete the old files first
185
    std::uintmax_t n = fs::remove_all(path);
186
    MSG_TRACE("Deleted " << n << " files/directories from " << path);
187
    return readtp4.doRead();
188
}
112 andreas 189
 
120 andreas 190
void TFsfReader::callbackLog(char* str, void*, bool out)
117 andreas 191
{
192
    DECL_TRACER("TFsfReader::callbackLog(char* str, void* arg, bool out)");
112 andreas 193
 
117 andreas 194
    if (!str)
195
        return;
112 andreas 196
 
117 andreas 197
    string msg = str;
116 andreas 198
    size_t pos = 0;
112 andreas 199
 
117 andreas 200
    if ((pos = msg.find("\r")) != string::npos)
201
        msg = msg.substr(0, pos);
116 andreas 202
 
117 andreas 203
    if (!out)
112 andreas 204
    {
117 andreas 205
        MSG_DEBUG("Output: " << msg);
112 andreas 206
    }
207
    else
208
    {
117 andreas 209
        MSG_DEBUG("Input: " << msg);
112 andreas 210
    }
211
}
120 andreas 212
 
213
void TFsfReader::callbackError(char* msg, void*, int err)
214
{
215
    DECL_TRACER("TFsfReader::callbackError(char* msg, void* arg, int err)");
216
 
217
    if (!msg)
218
        return;
219
 
220
    if (err)
221
    {
222
        MSG_ERROR(msg);
223
    }
224
    else if (*msg >= '0' && *msg <= '9')
225
    {
226
        MSG_INFO(msg);
227
    }
228
    else
229
    {
230
        MSG_DEBUG(msg);
231
    }
232
}
233
 
234
int TFsfReader::callbackXfer(off64_t xfered, void*)
235
{
236
    DECL_TRACER("TFsfReader::callbackXfer(off64_t xfered, void*)");
237
 
238
    if (_progress)
239
        return _progress(xfered);
240
 
241
    return 1;
242
}
137 andreas 243
 
244
void TFsfReader::logging(int level, const std::string &msg)
245
{
246
    switch(level)
247
    {
248
        case LOG_INFO:      MSG_INFO(msg); break;
249
        case LOG_WARNING:   MSG_WARNING(msg); break;
250
        case LOG_ERROR:     MSG_ERROR(msg); break;
251
        case LOG_TRACE:     MSG_TRACE(msg); break;
252
        case LOG_DEBUG:     MSG_DEBUG(msg); break;
253
    }
254
}