Wittyshare  0.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
WsModZip.cpp
Go to the documentation of this file.
1 /*
2  *
3  * Filename: WsModZip.cpp
4  *
5  * Description: Zip Wittyshare plugin
6  *
7  * Created: 03/07/12 11:07:15
8  *
9  * Author: Benoit Daccache, ben.daccache@gmail.com
10  *
11  */
12 
13 #include <Wt/WTheme>
14 #include <Wt/WFileResource>
15 
16 #include <gdwtcore/gdToolbar.h>
17 
18 #include "WsModZip.h"
19 #include <Main/WsFileResource.h>
20 #include <Logger/WsLogger.h>
21 
22 extern "C" {
23  void WsModZipInit(void)
24  {
25  void* hndl = dlopen("libarchive.so", RTLD_NOW | RTLD_GLOBAL);
26  if ( hndl == NULL ) {
27  fprintf(stderr, "cannot load libarchive.so shared library! %s\n", dlerror());
28  return;
29  }
30  }
31 }
32 WsZipEditorWidget::WsZipEditorWidget(WContainerWidget* parent)
33  : WsEditorWidget(parent)
34 { }
35 
37 { }
38 
40 {
43  string path = WApplication::instance()->internalPath();
45  std::string prop(user->getProperty(path, WSMODZIP, ALLOW_ZIP, "true"));
46  m_cb = new WCheckBox("Allow in zip ? ");
47  if ( prop == "true" ) {
48  m_bState = true;
49  m_cb->setCheckState(Wt::Checked);
50  } else
51  m_bState = false;
52  m_cb->setCheckState(Wt::Unchecked);
53  addWidget(m_cb);
54 }
55 
57 {
59  string path = WApplication::instance()->internalPath();
61  if ( m_cb->checkState() != m_bState )
62  if ( user->saveProperty(path, WSMODZIP, ALLOW_ZIP, m_cb->checkState() ? "true" : "false") == ErrorCode::Failure ) return false;
63  return true;
64 }
65 
67  : WsModule()
68 {
69  m_errmsg = "Could not create archive";
70 }
71 
73 {
74 }
75 
76 WWidget* WsModZip::createContentsMenuBar(WContainerWidget* parent) const
77 {
78  WsModZip* self = const_cast<WsModZip*>(this);
79  self->buildMenuBar();
80  return 0;
81 }
82 
84 {
86 }
87 
88 WWidget* WsModZip::createContents(WContainerWidget* parent) const
89 {
90  return 0;
91 }
92 
93 WsEditorWidget* WsModZip::createEditor(WContainerWidget* parent) const
94 {
95  WsZipEditorWidget* editor = new WsZipEditorWidget();
96  return editor;
97 }
98 
99 WWidget* WsModZip::createAdmin(WContainerWidget* parent) const
100 {
101  return 0;
102 }
103 
105 {
106  if ( !contentButtonsBar() ) return 0;
107  gdToolbarItem* pTbItem = contentButtonsBar()->addToolbarItem(wApp->theme()->resourcesUrl() + "wittyshare/Icons/compress.png", "", "Compress this directory");
108  pTbItem->clicked().connect(SLOT(this, WsModZip::handleZipClick));
109  return 0;
110 }
111 
113 {
114  m_dialog = new WDialog();
115  m_dialog->setTitleBarEnabled(false);
116  m_dialog->rejectWhenEscapePressed();
117  m_archiveType = new WButtonGroup(m_dialog->contents());
118  m_fileType = new WButtonGroup(m_dialog->contents());
119  m_container = new WGroupBox("Archive Type", m_dialog->contents());
120  m_zip = new WRadioButton("Zip", m_container);
121  m_tar = new WRadioButton("Tar", m_container);
122  m_archiveType->addButton(m_zip);
123  m_archiveType->addButton(m_tar);
124  m_archiveType->setCheckedButton(m_zip);
125  m_container2 = new WGroupBox("What ?", m_dialog->contents());
126  m_all = new WRadioButton("All contents", m_container2);
127  m_fonly = new WRadioButton("Files only", m_container2);
128  m_fileType->addButton(m_all);
129  m_fileType->addButton(m_fonly);
130  m_fileType->setCheckedButton(m_fonly);
131  new Wt::WBreak(m_dialog->contents());
132  m_ok = new WPushButton("Ok ", m_dialog->contents());
133  m_cancel = new WPushButton("Cancel ", m_dialog->contents());
134  m_ok->clicked().connect(SLOT(this, WsModZip::handleAccept));
135  m_cancel->clicked().connect(SLOT(this, WsModZip::handleReject));
136  m_dialog->show();
137 }
138 
139 void WsModZip::appendToZip(const string& path)
140 {
141  m_paths.push_back(path);
142 }
143 
145 {
146  m_paths.clear();
147  m_ok->hide();
148  m_cancel->hide();
149  m_container->hide();
150  m_container2->hide();
151  int t = -1;
152  /* Archive type is TAR */
153  if (m_archiveType->id(m_tar) == m_archiveType->checkedId())
154  t = TAR;
155  else
156  /* Archive type is ZIP */
157  t = ZIP;
158  m_label = new WLabel("Creating archive...\n Please Wait", m_dialog->contents());
159  m_loading = new WLabel(new WImage(WApplication::instance()->resourcesUrl() + "loading.gif"), m_dialog->contents());
160  int r;
161  /* Compress files and folder */
162  if (m_fileType->id(m_all) == m_fileType->checkedId())
163  r = handleAll(t);
164  else
165  /* Compress only files (1 level)*/
166  r = handleFiles(t);
167  if (r < 0) {
168  m_dialog->hide();
169  StandardButton result = WMessageBox::show("Error", m_errmsg, Ok );
170  }
171 }
172 
174 {
175  m_dialog->hide();
176  delete m_dialog;
177 }
178 
180 {
181  /* Get the WsUser class */
183  NodePtr accessTree = user->getAccessRoot();
184  if (!accessTree.get()) {
185  LOG(ERROR) << "WsModZip::handleFiles() AccessRoot is NULL";
186  return ErrorCode::Failure;
187  }
188  /* Get the internalPath */
189  string path = WApplication::instance()->internalPath();
191  /* Get the directory contents */
192  NodePtr tmp = accessTree.get()->eatPath(path);
193  if (!tmp)
194  return ErrorCode::Failure;
195  vector<NodePtr> contents = tmp.get()->getAll();
196  vector<NodePtr>::iterator it;
197  int size = contents.size();
198  int i = 0;
199  /* Iterate over all files and folders in directory */
200  for (it = contents.begin(); it != contents.end(); ++it) {
201  /* If it's a file */
202  if ((*it).get()->isRegularFile()) {
203  /* Check if we can include it in zip (read config) */
204  if ((*it).get()->getProperties().get()->get(WSMODZIP, ALLOW_ZIP, "true") == "true")
205  if ((*it).get()->getSize() > 0)
206  /* If yes and we file size is not 0 add it to zip */
207  appendToZip((*it).get()->getPath().string());
208  }
209  }
210  return writeAndCloseZip(t);
211 }
212 
214 {
215  /* Get WsUser class */
217  NodePtr accessTree = user->getAccessRoot();
218  if (!accessTree.get()) {
219  return ErrorCode::Failure;
220  }
221  /* Get the internalPath */
222  string path = WApplication::instance()->internalPath();
224  /* Get the directory contents */
225  NodePtr tmp = accessTree.get()->eatPath(path);
226  if (!tmp.get())
227  return ErrorCode::Failure;
228  vector<NodePtr> contents = tmp.get()->getAll();
229  vector<NodePtr>::iterator it;
230  int size = contents.size();
231  int i = 0;
232  /* Iterate over all files and folder */
233  for (it = contents.begin(); it != contents.end(); ++it) {
234  /* If it's a file */
235  if ((*it)->isRegularFile()) {
236  /* Check if we can add it to zip */
237  if ((*it).get()->getProperties().get()->get(WSMODZIP, ALLOW_ZIP, "true") == "true")
238  /* If we can add it to zip and file size > 0, add it */
239  if ((*it).get()->getSize() > 0)
240  appendToZip((*it)->getPath().string());
241  } else {
242  /* It's a directory */
243  /* Check if we can add it to zip */
244  if ((*it).get()->getProperties().get()->get(WSMODZIP, ALLOW_ZIP_ALL, "true") == "true" && (*it).get()->getProperties().get()->get(WSMODZIP, ALLOW_ZIP, "true") == "true")
245  /* Append the directory */
246  appendSubDir((*it).get()->getPath().string());
247  }
248  }
249  return writeAndCloseZip(t);
250 }
251 
252 void WsModZip::appendSubDir(const string& path)
253 {
254  /* Get the WsUser class */
256  NodePtr accessTree = user->getAccessRoot();
257  if (!accessTree.get()) {
258  LOG(ERROR) << "WsModZip::handleFiles() AccessRoot is NULL";
259  return;
260  }
261  /* Get the internalPath */
262  /* Get the directory contents */
263  NodePtr tmp = accessTree.get()->eatPath(path);
264  if (!tmp.get())
265  return;
266  vector<NodePtr> contents = tmp.get()->getAll();
267  /* Get contents of directory */
268  vector<NodePtr>::iterator it;
269  /* Iterate over files and folder */
270  for (it = contents.begin(); it != contents.end(); ++it) {
271  /* If it's a file */
272  if (typeid(*(*it)) == typeid(WsFileNode)) {
273  appendToZip((*it)->getPath().string());
274  } else {
275  /* it's a folder, recursively add sub files and folders */
276  appendSubDir((*it)->getPath().string());
277  }
278  }
279 }
280 
281 std::string WsModZip::description() const
282 {
283  return "WsModZip wittyShare module";
284 }
285 
286 
288 {
289  char buff[16384];
290  struct archive* a;
291  struct archive* disk;
292  struct archive_entry* entry;
293  ssize_t len;
294  int fd;
296  WsUser* user = wsApp->wsUser();
297  char* currentDir = get_current_dir_name();
298  string rootPath = user->getRootPath();
299  const char* temp = rootPath.c_str();
300  char* newDir = new char[rootPath.size() + 1]();
301  strncpy(newDir, temp, rootPath.size());
302  newDir[rootPath.size()] = '\0';
303  /* Do a chdir to zip files correctly */
304  if (chdir(newDir) != 0) {
305  LOG(ERROR) << "WsModZip :: Could not chdir to " << newDir;
306  return -1;
307  }
308  string ext;
309  /* Create a new archive */
310  a = archive_write_new();
311  /* Check format wanted */
312  if (format == TAR) {
313  /* Set flags TAR */
314  archive_write_set_compression_compress(a);
315  archive_write_set_compression_bzip2(a);
316  archive_write_set_format_ustar(a);
317  ext = ".tar.bz2";
318  } else if (format == ZIP) {
319  /* Set flags zIP */
320  archive_write_set_compression_compress(a);
321  archive_write_set_format_zip(a);
322  ext = ".zip";
323  } else {
324  LOG(ERROR) << "WsModZip :: Unknown file format ";
325  return -1;
326  }
327  /* Get TMP directory of user */
328  string filenameTmp = wsApp->getUserTmpPath() + string(basename(tmpnam(NULL))) + ext;
329  /* Open archive */
330  archive_write_open_file(a, filenameTmp.c_str());
331  disk = archive_read_disk_new();
332  archive_read_disk_set_standard_lookup(disk);
333  /* Nothing to archive */
334  if (m_paths.size() == 0) {
335  m_errmsg = "Nothing to archive";
336  return -1;
337  }
338  /* Iterate over paths we want to add to the archive */
339  for (int i = 0; i < m_paths.size(); ++i) {
340  struct archive* disk = archive_read_disk_new();
341  int r;
342  string str = m_paths[i];
343  /* remove the starting / */
344  if (m_paths[i][0] == '/') {
345  str = m_paths[i].substr(1);
346  }
347  r = archive_read_disk_open(disk, str.c_str());
348  if (r != ARCHIVE_OK) {
349  LOG(ERROR) << "WsModZip :: Cannot read file";
350  return -1;
351  }
352  /* Write */
353  for (;;) {
354  int needcr = 0;
355  entry = archive_entry_new();
356  r = archive_read_next_header2(disk, entry);
357  if (r == ARCHIVE_EOF)
358  break;
359  if (r != ARCHIVE_OK) {
360  LOG(ERROR) << "WsModZip :: Archive error";
361  return -1;
362  }
363  archive_read_disk_descend(disk);
364  LOG(DEBUG) << "WsModZip :: Writing archive header";
365  r = archive_write_header(a, entry);
366  if (r < ARCHIVE_OK) {
367  needcr = 1;
368  }
369  if (r == ARCHIVE_FATAL) {
370  LOG(ERROR) << "WsModZip :: Archive fatal";
371  return -1;
372  }
373  if (r > ARCHIVE_FAILED) {
374  fd = open(archive_entry_sourcepath(entry), O_RDONLY);
375  len = read(fd, buff, sizeof(buff));
376  while (len > 0) {
377  archive_write_data(a, buff, len);
378  len = read(fd, buff, sizeof(buff));
379  }
380  close(fd);
381  } else
382  LOG(ERROR) << "WsModZip :: Archive failed";
383  archive_entry_free(entry);
384  }
385  archive_read_close(disk);
386  archive_read_free(disk);
387  }
388  archive_write_close(a);
389  archive_write_free(a);
390  if (chdir(currentDir) != 0)
391  LOG(DEBUG) << "WsModZip :: Could not chdir to " << currentDir;
392  boost::replace_all(filenameTmp, wsApp->docRoot(), "");
393  WApplication::instance()->redirect(filenameTmp);
394  m_dialog->hide();
395  delete m_dialog;
396  return 0;
397 }
WsUser * wsUser()
WsModulesLoader & WsModules()
virtual bool saveEditor() const
Definition: WsModZip.cpp:56
boost::shared_ptr< WsAbstractNode > NodePtr
void WsModZipInit(void)
Definition: WsModZip.cpp:23
void handleReject()
Definition: WsModZip.cpp:173
std::string pathWithoutPrefix(const std::string &path)
#define DEBUG
Definition: WsLogger.h:27
int saveProperty(const std::string &path, const std::string &section, const std::string &attr, const std::string &val)
sets one property of the node and save it on disk.
Definition: WsUser.cpp:99
std::string getProperty(const std::string &path, const std::string &section, const string &attr, const std::string &def)
returns one property of a node If the property does not exist, a empty string is returned.
Definition: WsUser.cpp:91
#define ALLOW_ZIP_ALL
Definition: WsModZip.h:55
Wt::WRadioButton * m_tar
Definition: WsModZip.h:124
Wt::WButtonGroup * m_archiveType
Definition: WsModZip.h:128
Wt::WRadioButton * m_all
Definition: WsModZip.h:122
const int Failure
Wt::WCheckBox * m_cb
Definition: WsModZip.h:80
static WsApplication * wsInstance()
Facility function to access the application object.
Definition: WsApplication.h:39
Reprensents a File on disk.
Definition: WsFileNode.h:23
WsModZip()
Definition: WsModZip.cpp:66
Wt::WPushButton * m_cancel
Definition: WsModZip.h:131
Wt::WPushButton * m_ok
Definition: WsModZip.h:130
void appendToZip(const string &path)
Append the file to the zip.
Definition: WsModZip.cpp:139
#define ALLOW_ZIP
Definition: WsModZip.h:54
Wt::WWidget * buildMenuBar()
Definition: WsModZip.cpp:104
WsEditorWidget * createEditor(Wt::WContainerWidget *parent=0) const
Create the contents for an editor (create a view of options).
Definition: WsModZip.cpp:93
Wt::WRadioButton * m_zip
Definition: WsModZip.h:125
Wt::WDialog * m_dialog
Definition: WsModZip.h:121
Wt::WGroupBox * m_container
Definition: WsModZip.h:126
WsContentButtonsBar * contentButtonsBar()
WittyShare provide a container to add some buttons like export page in pdf, ..., This function allow ...
Definition: WsModule.cpp:42
Interface that provides differents methods for accessing the FsTree as well as other features...
Definition: WsUser.h:33
#define LOG
Definition: WsLogger.h:22
#define ZIP
Definition: WsModZip.h:50
WsZipEditorWidget(Wt::WContainerWidget *parent=0)
Constructor.
Definition: WsModZip.cpp:32
#define WSMODZIP
Definition: WsModZip.h:53
Wt::WWidget * createContents(Wt::WContainerWidget *parent=0) const
Create the contents.
Definition: WsModZip.cpp:88
virtual void destroyContentsMenuBar()
Definition: WsModZip.cpp:83
~WsZipEditorWidget()
Destructor.
Definition: WsModZip.cpp:36
virtual void load()
Load the widget.
Definition: WsModZip.cpp:39
virtual void load()
Definition: WsModule.cpp:26
vector< string > m_paths
Definition: WsModZip.h:119
std::string description() const
Return the description of the module.
Definition: WsModZip.cpp:281
void appendSubDir(const string &path)
A.
Definition: WsModZip.cpp:252
Wt::WRadioButton * m_fonly
Definition: WsModZip.h:123
virtual void destroyContentsMenuBar()
Definition: WsModule.cpp:47
void handleAccept()
Definition: WsModZip.cpp:144
Wt::WWidget * createContentsMenuBar(Wt::WContainerWidget *parent=0) const
Create the functionalities.
Definition: WsModZip.cpp:76
const std::string getRootPath()
return the root path of the filesystem tree, example : /var/www/demo_site
Definition: WsUser.cpp:55
~WsModZip()
Definition: WsModZip.cpp:72
#define TAR
Definition: WsModZip.h:51
Wt::WWidget * createAdmin(Wt::WContainerWidget *parent=0) const
Create the contents for an administrator.
Definition: WsModZip.cpp:99
int handleAll(int t)
Definition: WsModZip.cpp:213
int writeAndCloseZip(int format)
Definition: WsModZip.cpp:287
Wt::WButtonGroup * m_fileType
Definition: WsModZip.h:129
Wt::WLabel * m_label
Definition: WsModZip.h:133
NodePtr getAccessRoot()
return the root node of the access tree starting from the root
Definition: WsUser.cpp:50
Wt::WGroupBox * m_container2
Definition: WsModZip.h:127
int handleFiles(int t)
Definition: WsModZip.cpp:179
Wt::WLabel * m_loading
Definition: WsModZip.h:132
string m_errmsg
Definition: WsModZip.h:135
#define ERROR
Definition: WsLogger.h:42
void handleZipClick()
Definition: WsModZip.cpp:112