Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
112 andreas 1
/*
2
 * Copyright (C) 2022 by Andreas Theofilu <andreas@theosys.at>
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 "tsocket.h"
43
#include "tconfig.h"
44
#include "terror.h"
45
#include "tresources.h"
113 andreas 46
#include "readtp4.h"
112 andreas 47
 
125 andreas 48
#if __cplusplus < 201402L
49
#   error "This module requires at least C++ 14 standard!"
50
#else
51
#   if __cplusplus < 201703L
52
#       include <experimental/filesystem>
53
        namespace fs = std::experimental::filesystem;
54
#       warning "Support for C++14 and experimental filesystem will be removed in a future version!"
55
#   else
56
#       include <filesystem>
57
#       ifdef __ANDROID__
58
            namespace fs = std::__fs::filesystem;
59
#       else
60
            namespace fs = std::filesystem;
61
#       endif
62
#   endif
63
#endif
64
 
112 andreas 65
#define FTP_PORT    21
66
 
67
#define FTP_CMD_USER    0
68
#define FTP_CMD_PASS    1
69
#define FTP_CMD_PASV    2
70
#define FTP_CMD_TYPE    3
71
#define FTP_CMD_RETR    4
72
#define FTP_CMD_QUIT    5
73
 
74
using std::string;
75
using std::vector;
117 andreas 76
using std::bind;
125 andreas 77
/*
119 andreas 78
#if __GNUC__ < 9 && !defined(__ANDROID__)
79
   #if __cplusplus < 201703L
80
      #warning "Your C++ compiler seems to have no support for C++17 standard!"
81
   #endif
82
   #include <experimental/filesystem>
83
   namespace fs = std::experimental::filesystem;
84
#else
85
#  ifdef __ANDROID__
86
#   if _LIBCPP_STD_VER >= 17
87
#       include <filesystem>
88
        namespace fs = std::__fs::filesystem;
89
#   else
90
#       include <experimental/filesystem>
91
        namespace fs = std::__fs::filesystem;
92
#   endif
93
#  else
94
#   include <filesystem>
95
    namespace fs = std::filesystem;
96
#  endif
97
#endif
125 andreas 98
*/
117 andreas 99
 
120 andreas 100
std::function<int (off64_t xfered)> TFsfReader::_progress{nullptr};
101
 
112 andreas 102
TFsfReader::TFsfReader()
103
{
104
    DECL_TRACER("TFsfReader::TFsfReader()");
105
 
106
}
107
 
108
TFsfReader::~TFsfReader()
109
{
110
    DECL_TRACER("TFsfReader::~TFsfReader()");
111
 
117 andreas 112
    if (mFtpLib)
113
        delete mFtpLib;
112 andreas 114
}
115
 
117 andreas 116
bool TFsfReader::copyOverFTP(const string& fname, const string& target)
112 andreas 117
{
179 andreas 118
    DECL_TRACER("TFsfReader::copyOverFTP(const string& fname, const string& target)");
112 andreas 119
 
117 andreas 120
    if (mFtpLib)
121
        delete mFtpLib;
112 andreas 122
 
117 andreas 123
    mFtpLib = new ftplib();
137 andreas 124
    mFtpLib->regLogging(bind(&TFsfReader::logging, this, std::placeholders::_1, std::placeholders::_2));
112 andreas 125
 
117 andreas 126
    if (TConfig::getFtpPassive())
127
        mFtpLib->SetConnmode(ftplib::pasv);
112 andreas 128
    else
117 andreas 129
        mFtpLib->SetConnmode(ftplib::port);
112 andreas 130
 
120 andreas 131
    mFtpLib->SetCallbackLogFunction(&TFsfReader::callbackLog);      // Print some debugging messages
132
    mFtpLib->SetCallbackErrorFunction(&TFsfReader::callbackError);  // Print errors or info's
133
    mFtpLib->SetCallbackXferFunction(&TFsfReader::callbackXfer);    // This is the progress
134
    mFtpLib->SetCallbackBytes(10000L);                              // This tells the progress to be called every 10KiB
117 andreas 135
    string scon = TConfig::getController() + ":21";
136
    MSG_DEBUG("Trying to connect to " << scon);
115 andreas 137
 
117 andreas 138
    if (!mFtpLib->Connect(scon.c_str()))
115 andreas 139
    {
117 andreas 140
        delete mFtpLib;
141
        mFtpLib = nullptr;
112 andreas 142
        return false;
115 andreas 143
    }
112 andreas 144
 
117 andreas 145
    string sUser = TConfig::getFtpUser();
146
    string sPass = TConfig::getFtpPassword();
179 andreas 147
    MSG_DEBUG("Trying to login <" << sUser << ", ********>");
112 andreas 148
 
117 andreas 149
    if (!mFtpLib->Login(sUser.c_str(), sPass.c_str()))
115 andreas 150
    {
117 andreas 151
        delete mFtpLib;
152
        mFtpLib = nullptr;
112 andreas 153
        return false;
115 andreas 154
    }
112 andreas 155
 
117 andreas 156
    MSG_DEBUG("Trying to download file " << fname << " to " << target);
112 andreas 157
 
117 andreas 158
    if (!mFtpLib->Get(target.c_str(), fname.c_str(), ftplib::image))
112 andreas 159
    {
117 andreas 160
        MSG_ERROR("Error downloading file " << fname);
161
        delete mFtpLib;
162
        mFtpLib = nullptr;
112 andreas 163
        return false;
164
    }
165
 
117 andreas 166
    MSG_TRACE("File " << fname << " successfully downloaded to " << target << ".");
167
    mFtpLib->Quit();
112 andreas 168
    return true;
169
}
170
 
117 andreas 171
bool TFsfReader::unpack(const string& fname, const string& path)
112 andreas 172
{
117 andreas 173
    DECL_TRACER("TFsfReader::unpack(const string& fname, const string& path)");
112 andreas 174
 
117 andreas 175
    if (fname.empty() || path.empty())
112 andreas 176
    {
117 andreas 177
        MSG_ERROR("Invalid parameters!");
112 andreas 178
        return false;
179
    }
180
 
117 andreas 181
    reader::ReadTP4 readtp4(fname, path);
115 andreas 182
 
117 andreas 183
    if (!readtp4.isReady())
112 andreas 184
        return false;
185
 
117 andreas 186
    // We must delete the old files first
187
    std::uintmax_t n = fs::remove_all(path);
188
    MSG_TRACE("Deleted " << n << " files/directories from " << path);
189
    return readtp4.doRead();
190
}
112 andreas 191
 
120 andreas 192
void TFsfReader::callbackLog(char* str, void*, bool out)
117 andreas 193
{
194
    DECL_TRACER("TFsfReader::callbackLog(char* str, void* arg, bool out)");
112 andreas 195
 
117 andreas 196
    if (!str)
197
        return;
112 andreas 198
 
117 andreas 199
    string msg = str;
116 andreas 200
    size_t pos = 0;
112 andreas 201
 
117 andreas 202
    if ((pos = msg.find("\r")) != string::npos)
203
        msg = msg.substr(0, pos);
116 andreas 204
 
117 andreas 205
    if (!out)
112 andreas 206
    {
117 andreas 207
        MSG_DEBUG("Output: " << msg);
112 andreas 208
    }
209
    else
210
    {
117 andreas 211
        MSG_DEBUG("Input: " << msg);
112 andreas 212
    }
213
}
120 andreas 214
 
215
void TFsfReader::callbackError(char* msg, void*, int err)
216
{
217
    DECL_TRACER("TFsfReader::callbackError(char* msg, void* arg, int err)");
218
 
219
    if (!msg)
220
        return;
221
 
222
    if (err)
223
    {
224
        MSG_ERROR(msg);
225
    }
226
    else if (*msg >= '0' && *msg <= '9')
227
    {
228
        MSG_INFO(msg);
229
    }
230
    else
231
    {
232
        MSG_DEBUG(msg);
233
    }
234
}
235
 
236
int TFsfReader::callbackXfer(off64_t xfered, void*)
237
{
238
    DECL_TRACER("TFsfReader::callbackXfer(off64_t xfered, void*)");
239
 
240
    if (_progress)
241
        return _progress(xfered);
242
 
243
    return 1;
244
}
137 andreas 245
 
246
void TFsfReader::logging(int level, const std::string &msg)
247
{
248
    switch(level)
249
    {
250
        case LOG_INFO:      MSG_INFO(msg); break;
251
        case LOG_WARNING:   MSG_WARNING(msg); break;
252
        case LOG_ERROR:     MSG_ERROR(msg); break;
253
        case LOG_TRACE:     MSG_TRACE(msg); break;
254
        case LOG_DEBUG:     MSG_DEBUG(msg); break;
255
    }
256
}