Subversion Repositories tpanel

Rev

Rev 446 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
446 andreas 1
/*
475 andreas 2
 * Copyright (C) 2022 to 2024 by Andreas Theofilu <andreas@theosys.at>
446 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>
20
#include <functional>
21
#include <iostream>
22
#include <cstdint>
23
#include <filesystem>
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>
31
#ifndef __MACH__
32
#include <sys/sendfile.h>
33
#endif
34
#include <fcntl.h>
35
#include <unistd.h>
36
#include <sys/socket.h>
37
#include <netinet/in.h>
38
#include <netdb.h>
39
#include <arpa/inet.h>
40
 
41
#include "tfsfreader.h"
42
#include "tconfig.h"
43
#include "terror.h"
44
#include "readtp4.h"
45
 
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
 
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;
74
using std::bind;
75
/*
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
96
*/
97
 
98
std::function<int (off64_t xfered)> TFsfReader::_progress{nullptr};
99
 
100
TFsfReader::TFsfReader()
101
{
102
    DECL_TRACER("TFsfReader::TFsfReader()");
103
 
104
}
105
 
106
TFsfReader::~TFsfReader()
107
{
108
    DECL_TRACER("TFsfReader::~TFsfReader()");
109
 
110
    if (mFtpLib)
111
        delete mFtpLib;
112
}
113
 
114
bool TFsfReader::copyOverFTP(const string& fname, const string& target)
115
{
116
    DECL_TRACER("TFsfReader::copyOverFTP(const string& fname, const string& target)");
117
 
118
    if (mFtpLib)
119
        delete mFtpLib;
120
 
121
    mFtpLib = new ftplib();
122
    mFtpLib->regLogging(bind(&TFsfReader::logging, this, std::placeholders::_1, std::placeholders::_2));
123
 
124
    if (TConfig::getFtpPassive())
125
        mFtpLib->SetConnmode(ftplib::pasv);
126
    else
127
        mFtpLib->SetConnmode(ftplib::port);
128
 
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
132
    mFtpLib->SetCallbackBytes(10000L);                              // This tells the progress to be called every 10Kb
133
    string scon = TConfig::getController() + ":21";
134
    MSG_DEBUG("Trying to connect to " << scon);
135
 
136
    if (!mFtpLib->Connect(scon.c_str()))
137
    {
138
        delete mFtpLib;
139
        mFtpLib = nullptr;
140
        return false;
141
    }
142
 
143
    string sUser = TConfig::getFtpUser();
144
    string sPass = TConfig::getFtpPassword();
145
    MSG_DEBUG("Trying to login <" << sUser << ", ********>");
146
 
147
    if (!mFtpLib->Login(sUser.c_str(), sPass.c_str()))
148
    {
149
        delete mFtpLib;
150
        mFtpLib = nullptr;
151
        return false;
152
    }
153
 
154
    MSG_DEBUG("Trying to download file " << fname << " to " << target);
155
 
156
    if (!mFtpLib->Get(target.c_str(), fname.c_str(), ftplib::image))
157
    {
158
        MSG_ERROR("Error downloading file " << fname);
159
        delete mFtpLib;
160
        mFtpLib = nullptr;
161
        return false;
162
    }
163
 
164
    MSG_TRACE("File " << fname << " successfully downloaded to " << target << ".");
165
    mFtpLib->Quit();
166
    return true;
167
}
168
 
169
bool TFsfReader::unpack(const string& fname, const string& path)
170
{
171
    DECL_TRACER("TFsfReader::unpack(const string& fname, const string& path)");
172
 
173
    if (fname.empty() || path.empty())
174
    {
175
        MSG_ERROR("Invalid parameters!");
176
        return false;
177
    }
178
 
179
    reader::ReadTP4 readtp4(fname, path);
180
 
181
    if (!readtp4.isReady())
182
        return false;
183
 
475 andreas 184
    tp5Type = readtp4.isTP5();
446 andreas 185
    // We must delete the old files first
186
    std::uintmax_t n = fs::remove_all(path);
187
    MSG_TRACE("Deleted " << n << " files/directories from " << path);
188
    return readtp4.doRead();
189
}
190
 
191
void TFsfReader::callbackLog(char* str, void*, bool out)
192
{
193
    DECL_TRACER("TFsfReader::callbackLog(char* str, void* arg, bool out)");
194
 
195
    if (!str)
196
        return;
197
 
198
    string msg = str;
199
    size_t pos = 0;
200
 
201
    if ((pos = msg.find("\r")) != string::npos)
202
        msg = msg.substr(0, pos);
203
 
204
    if (!out)
205
    {
206
        MSG_DEBUG("Output: " << msg);
207
    }
208
    else
209
    {
210
        MSG_DEBUG("Input: " << msg);
211
    }
212
}
213
 
214
void TFsfReader::callbackError(char* msg, void*, int err)
215
{
216
    DECL_TRACER("TFsfReader::callbackError(char* msg, void* arg, int err)");
217
 
218
    if (!msg)
219
        return;
220
 
221
    if (err)
222
    {
223
        MSG_ERROR(msg);
224
    }
225
    else if (*msg >= '0' && *msg <= '9')
226
    {
227
        MSG_INFO(msg);
228
    }
229
    else
230
    {
231
        MSG_DEBUG(msg);
232
    }
233
}
234
 
235
int TFsfReader::callbackXfer(off64_t xfered, void*)
236
{
237
    DECL_TRACER("TFsfReader::callbackXfer(off64_t xfered, void*)");
238
 
239
    if (_progress)
240
        return _progress(xfered);
241
 
242
    return 1;
243
}
244
 
245
void TFsfReader::logging(int level, const std::string &msg)
246
{
247
    switch(level)
248
    {
249
        case LOG_INFO:      MSG_INFO(msg); break;
250
        case LOG_WARNING:   MSG_WARNING(msg); break;
251
        case LOG_ERROR:     MSG_ERROR(msg); break;
252
        case LOG_TRACE:     MSG_TRACE(msg); break;
253
        case LOG_DEBUG:     MSG_DEBUG(msg); break;
254
    }
255
}