The SWORD Project  1.9.0.svnversion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
remotetrans.cpp
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * remotetrans.cpp -
4  *
5  * $Id: remotetrans.cpp 3822 2020-11-03 18:54:47Z scribe $
6  *
7  * Copyright 2004-2013 CrossWire Bible Society (http://www.crosswire.org)
8  * CrossWire Bible Society
9  * P. O. Box 2528
10  * Tempe, AZ 85280-2528
11  *
12  * This program is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU General Public License as published by the
14  * Free Software Foundation version 2.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  */
22 
23 #include <remotetrans.h>
24 #include <filemgr.h>
25 
26 #include <fcntl.h>
27 #include <dirent.h>
28 #include <swlog.h>
29 
30 
31 extern "C" {
32 #include <ftpparse.h>
33 }
34 
35 
36 using std::vector;
37 
38 
40 
41 
42 namespace {
43 
44  void removeTrailingSlash(SWBuf &buf) {
45  int len = buf.size();
46  if ((buf[len-1] == '/')
47  || (buf[len-1] == '\\'))
48  buf.size(len-1);
49  }
50 
51 };
52 
53 
54 void StatusReporter::preStatus(long totalBytes, long completedBytes, const char *message) {
55 }
56 
57 
58 void StatusReporter::statusUpdate(double dtTotal, double dlNow) {
59 }
60 
61 
63  this->statusReporter = statusReporter;
64  this->host = host;
65  u = "ftp";
66  p = "installmgr@user.com";
67  term = false;
68  passive = true;
69  unverifiedPeerAllowed = true;
70 }
71 
72 
74 }
75 
76 
77 // override this method in your real transport class
78 char RemoteTransport::getURL(const char *destPath, const char *sourceURL, SWBuf *destBuf) {
79  SWLog::getSystemLog()->logWarning("RemoteTransport::getURL called but unsupported");
80  char retVal = -1;
81  return retVal;
82 }
83 
84 // override this method in your real transport class
85 char RemoteTransport::putURL(const char *destURL, const char *sourcePath, SWBuf *sourceBuf) {
86  SWLog::getSystemLog()->logWarning("RemoteTransport::putURL called but unsupported");
87  char retVal = -1;
88  return retVal;
89 }
90 
91 
92 vector<struct DirEntry> RemoteTransport::getDirList(const char *dirURL) {
93 
94 SWLOGD("RemoteTransport::getDirList(%s)", dirURL);
95  vector<struct DirEntry> dirList;
96 
97  SWBuf dirBuf;
98  if (!getURL("", dirURL, &dirBuf)) {
99  char *start = dirBuf.getRawData();
100  char *end = start;
101  while (start < (dirBuf.getRawData()+dirBuf.size())) {
102  struct ftpparse item;
103  bool looking = true;
104  for (end = start; *end; end++) {
105  if (looking) {
106  if ((*end == 10) || (*end == 13)) {
107  *end = 0;
108  looking = false;
109  }
110  }
111  else if ((*end != 10) && (*end != 13))
112  break;
113  }
114 SWLOGD("getDirList: parsing item %s(%d)\n", start, end-start);
115  int status = ftpparse(&item, start, (int)(end - start));
116  // in ftpparse.h, there is a warning that name is not necessarily null terminated
117  SWBuf name;
118  name.append(item.name, item.namelen);
119 SWLOGD("getDirList: got item %s\n", name.c_str());
120  if (status && name != "." && name != "..") {
121  struct DirEntry i;
122  i.name = name;
123  i.size = item.size;
124  i.isDirectory = (item.flagtrycwd == 1);
125  dirList.push_back(i);
126  }
127  start = end;
128  }
129  }
130  else {
131  SWLog::getSystemLog()->logWarning("getDirList: failed to get dir %s\n", dirURL);
132  }
133  return dirList;
134 }
135 
136 
140 int RemoteTransport::copyDirectory(const char *urlPrefix, const char *dir, const char *dest, const char *suffix) {
141 SWLOGD("RemoteTransport::copyDirectory");
142  int retVal = 0;
143 
144  SWBuf url = SWBuf(urlPrefix) + SWBuf(dir);
145  removeTrailingSlash(url);
146  url += '/';
147 
148 SWLOGD("NetTransport: getting dir %s\n", url.c_str());
149  vector<struct DirEntry> dirList = getDirList(url.c_str());
150 
151  if (!dirList.size()) {
152  SWLog::getSystemLog()->logWarning("NetTransport: failed to read dir %s\n", url.c_str());
153  return -1;
154  }
155 
156  // append files in sub directories and calculate total download size
157  unsigned int i = 0;
158  long totalBytes = 0;
159  for (;;) {
160  if (i == dirList.size())
161  break;
162 
163  struct DirEntry &e = dirList.at(i);
164 
165  if (e.isDirectory) {
166  SWBuf name(e.name); // &e will be invalidated after first insertion
167  vector<struct DirEntry> sd = getDirList((url + name + '/').c_str());
168  for (unsigned int ii = 0; ii < sd.size(); ii++) {
169  sd[ii].name = name + '/' + sd[ii].name;
170  dirList.push_back(sd[ii]);
171  }
172  dirList.erase(dirList.begin() + i);
173  }
174  else {
175  totalBytes += e.size;
176  i++;
177  }
178  }
179 
180  long completedBytes = 0;
181  for (i = 0; i < dirList.size(); i++) {
182  struct DirEntry &dirEntry = dirList[i];
183  SWBuf buffer = (SWBuf)dest;
184  removeTrailingSlash(buffer);
185  buffer += "/";
186  buffer += dirEntry.name;
187  if (!strcmp(&buffer.c_str()[buffer.length()-strlen(suffix)], suffix)) {
188  SWBuf buffer2 = "Downloading (";
189  buffer2.appendFormatted("%d", i+1);
190  buffer2 += " of ";
191  buffer2.appendFormatted("%d", dirList.size());
192  buffer2 += "): ";
193  buffer2 += dirEntry.name;
194  if (statusReporter)
195  statusReporter->preStatus(totalBytes, completedBytes, buffer2.c_str());
196  FileMgr::createParent(buffer.c_str()); // make sure parent directory exists
197  SWTRY {
198  SWBuf url = (SWBuf)urlPrefix + (SWBuf)dir;
199  removeTrailingSlash(url);
200  url += "/";
201  url += dirEntry.name;
202  retVal = getURL(buffer.c_str(), url.c_str());
203  if (retVal) {
204  SWLog::getSystemLog()->logWarning("copyDirectory: failed to get file %s\n", url.c_str());
205  return retVal;
206  }
207  completedBytes += dirEntry.size;
208  }
209  SWCATCH (...) {}
210  if (term) {
211  retVal = -3;
212  break;
213  }
214  }
215  }
216  return retVal;
217 }
218 
219 
220 #if defined(__GNUC__)
221 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
222 #endif
223 void StatusReporter::update(unsigned long totalBytes, unsigned long completedBytes) {
224  statusUpdate(totalBytes, completedBytes);
225 }
226 
227 
229 
bool isDirectory
Definition: filemgr.h:43
#define SWORD_NAMESPACE_START
Definition: defs.h:39
SWBuf & appendFormatted(const char *format,...)
Definition: swbuf.cpp:81
Definition: swbuf.h:47
unsigned long length() const
Definition: swbuf.h:197
unsigned long size
Definition: filemgr.h:42
int flagtrycwd
Definition: ftpparse.h:23
static SWLog * getSystemLog()
Definition: swlog.cpp:53
char * name
Definition: ftpparse.h:21
virtual char getURL(const char *destPath, const char *sourceURL, SWBuf *destBuf=0)
Definition: remotetrans.cpp:78
StatusReporter * statusReporter
Definition: installmgr.cpp:48
preg buffer
Definition: regex.c:8089
#define SWTRY
Definition: defs.h:57
#define SWCATCH(x)
Definition: defs.h:58
int namelen
Definition: ftpparse.h:22
char * getRawData()
Definition: swbuf.h:379
const char * c_str() const
Definition: swbuf.h:158
SWBuf & append(const char *str, long max=-1)
Definition: swbuf.h:274
SWBuf name
Definition: filemgr.h:41
virtual void preStatus(long totalBytes, long completedBytes, const char *message)
Definition: remotetrans.cpp:54
virtual char putURL(const char *destURL, const char *sourcePath, SWBuf *sourceBuf=0)
Definition: remotetrans.cpp:85
int copyDirectory(const char *urlPrefix, const char *dir, const char *dest, const char *suffix)
static void removeTrailingSlash(SWBuf &buf)
Definition: installmgr.cpp:57
RemoteTransport(const char *host, StatusReporter *statusReporter=0)
Definition: remotetrans.cpp:62
static int createParent(const char *pName)
Definition: filemgr.cpp:426
unsigned long size() const
Definition: swbuf.h:185
virtual void update(unsigned long totalBytes, unsigned long completedBytes)
void logWarning(const char *fmt,...) const
Definition: swlog.cpp:74
virtual std::vector< struct DirEntry > getDirList(const char *dirURL)
Definition: remotetrans.cpp:92
bool unverifiedPeerAllowed
Definition: remotetrans.h:63
virtual SWDEPRECATED void statusUpdate(double dtTotal, double dlNow)
Definition: remotetrans.cpp:58
int ftpparse(struct ftpparse *fp, char *buf, int len)
Definition: ftpparse.c:144
#define SWORD_NAMESPACE_END
Definition: defs.h:40
#define SWLOGD(...)
Definition: defs.h:187
long size
Definition: ftpparse.h:26
virtual ~RemoteTransport()
Definition: remotetrans.cpp:73
StatusReporter * statusReporter
Definition: remotetrans.h:59