Search can open File URL's in mozilla/djview/xpdf/xchm
[sfinx.git] / sfinx / sfinx.C
blobdc44538adb8084ac62346a1f274d656ac3ba8f7c
2  /*
3   *   Copyright (C) 2007, Rus V. Brushkoff, All rights reserved.
4   */
6 #include <sfinx.H>
7 #include <locale.h>
9 sfinx_app *sfinx;
11 // make preferences
12 void sfinx_app::dbopen()
14  dbname_ = db_dir + "/sfinx.fdb";
15  dbuser_ = "sysdba";
16  dbpass_ = "harbour";
17  // replace this after converting database to UTF8
18  db_ = driver_->DatabaseFactory("", dbname_, dbuser_, dbpass_, "", "UTF-8", "");
19  db_->Connect();
20  log("dbopen", "Connected to database %s", dbname_.c_str());
23 void sfinx_app::listen()
25  InetAddress addr((InetAddrValidator *)0);
26  log("sfinx:listen", "server listening at %d port", SFINX_PORT);
27  try {
28   sfinx_socket server(addr);
29   while(server.isPendingConnection()) {
30     faraon_session *faraon = new faraon_session(server, SFINX_MAX_PACKET_SIZE);
31     faraon->start();
32   }
33  }
34   catch(Socket *socket) {
35   
36     tpport_t port;
37     int err = socket->getErrorNumber();
38     cerr << "client socket error : ";
39     if (err == Socket::errBindingFailed) {
40       cerr << "bind failed; port busy, bye." << endl;
41       ::exit(-1);
42    }
43     IPV4Address saddr = socket->getPeer(&port);
44     const char *host;
45     if (!saddr.isInetAddress())
46      host = "localhost";
47     else
48      host = saddr.getHostname();
49     cerr << host << ":" << port << \
50       " failed : " << socket->getErrorString() << endl;
51  }
52    cerr << "listen terminated" << endl;
56 sfinx_id_t sfinx_app::parent_slice_id(sfinx_id_t slice_id)
58  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
59    IBPP::ilConcurrency, IBPP::lrWait);
60  tr->Start();
61  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
62  st->Prepare("select parent_id from slices where id = ?");
63  st->Set(1, (int64_t)slice_id);
64  st->Execute();
65  int64_t p_id = 0;
66  if (st->Fetch())
67    st->Get(1, &p_id);
68  else {
69    debug("no parent for %lld slice !", slice_id);
70    bug();
71  }
72   tr->Commit();
73   return p_id;
76 string sfinx_app::slice_name(sfinx_id_t slice_id)
78  string name;
79  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
80    IBPP::ilConcurrency, IBPP::lrWait);
81  tr->Start();
82  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
83  st->Prepare("select name from slices where id = ?");
84  st->Set(1, (int64_t)slice_id);
85  st->Execute();
86  while (st->Fetch()) {
87    st->Get(1, name);
88  }
89  tr->Commit();
90  return name;
93 string sfinx_app::slice_directory(sfinx_id_t slice_id)
95  string t;
96  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
97    IBPP::ilConcurrency, IBPP::lrWait);
98  tr->Start();
99  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
100  st->Prepare("select directory from slices where id = ?");
101  st->Set(1, (int64_t)slice_id);
102  st->Execute();
103  while (st->Fetch()) {
104    st->Get(1, t);
106  tr->Commit();
107  return t;
110 // set path_name to sorted location (slice names as dirs)
111 bool sfinx_app::set_sorted_path(sfinx_object_t &obj)
113  string path;
114  sfinx->files_module_conf.get(FILES_MODULE_SORTED_TREE_PATH, obj.path_name);
115  sfinx_object_t t = obj;
116  while (1) {
117   if (t.slice_id == 1) // root slice
118     break;
119   path.insert(0, "/" + slice_directory(t.slice_id)); // TODO: handle spaces in names
120   t.slice_id = parent_slice_id(t.slice_id);
122   obj.path_name += path;
123   return false;
126 // returns true on error
127 bool sfinx_app::sorted_path_mkdir(sfinx_object_t &obj)
129  if (set_sorted_path(obj))
130    return true;
131  return system(("mkdir -p " + obj.path_name).c_str());
134 CommandOption *sfinx_opt_list = 0;
136 CommandOptionArg dbdir_opt("dbdir", "d", "\tSfinx Database Dir", false,
137   &sfinx_opt_list);
138 CommandOptionArg user_opt("user", "u", "\t\tsetuid() to user", false,
139   &sfinx_opt_list);
141 #include <sys/types.h>
142 #include <pwd.h>
143 #include <unistd.h>
144 #include <errno.h>
146 void sfinx_app::parse_command_options(void)
148  static bool called; // ×ÙÚÙ×ÁÅÍ ÐÏÒÁÎØÛÅ ÄÁÎÎÕ f()
149  if (called)
150    return;
151  called = true;
152  if (dbdir_opt.numValue)
153   db_dir = dbdir_opt.values[0];
154  else
155   db_dir = "/usr/local/share/sfinx";
156  if (user_opt.numValue) {
157    struct passwd *upwd = getpwnam(user_opt.values[0]);
158    if (!upwd) {
159      log("setuid error", "No such user %s", user_opt.values[0]);
160      return;
161   }
162    if (setuid(upwd->pw_uid))
163      log("setuid error", "%s", strerror(errno));
167 int main(int argc, char **argv)
169  setlocale(LC_ALL, "");
170  char version[16];
171  sprintf(version, "v%0d.%0d.%0d", SFINX_VERSION_MAJOR, SFINX_VERSION_MINOR, SFINX_VERSION_PLEVEL);
172  sfinx = new sfinx_app(argc, argv, "sfinx", version,
173    "Rus V. Brushkoff <Rus@Sfinx.Od.UA>", "GPL", sfinx_opt_list);
174  try {
175    sfinx->dbopen();
176    sfinx->start_ui(); // start ui first
177    sfinx->listen();
179  catch(IBPP::Exception& e) {
180    log("IBPP::Exception", "%s", e.what());
181      if (sfinx->ui())
182        sfinx->ui()->alert("%s() Error !", e.Origin());
183  } 
184  return 0;
187 bool faraon_session::connect()
189  // send plain packet with daemon version
190  tx_elements.clear();
191  tx_elements.add(daemon_version);
192  // and available crypt types
193  tx_elements.add(packet_crypt_types);
194  // auth level
195  tx_elements.add(min_auth_levels);
196  // ÐÅÒÅÄÅÌÁÔØ Ó ÉÓÐÏÌØÚÏ×ÁÎÉÅÍ -lgcrypt
197  sfinx_8bit_vector_t md5_challenge(SFINX_MD5_SUM);
198  sfinx_crypter::get_random_bytes(md5_challenge, gcry_md_get_algo_dlen(GCRY_MD_MD5));
199  tx_elements.add(md5_challenge);
200  send_packet();
201  if (read_packet()) {
202    log("sfinx:connect", "Error reading faraon request");
203    return true;
206  // got SFINX_AUTH_REQUEST + auth data
207  // validate user_name/pass or rsa key
208  // ...
210  // send SFINX_ACCESS_GRANTED/SFINX_ACCESS_DENIED
211  tx_elements.clear();
212  sfinx_8bit_t access(SFINX_ACCESS_GRANTED);
213  access.set(0); // ÐÒÉÞÉÎÁ ÄÏÓÔÕÐÁ/ÏÔËÁÚÁ
214  tx_elements.add(access);
215  send_packet();
216  return false;
219 void faraon_session::run()
221  setError(1);
222  setNoDelay(1);
223  try {
224    if (connect())
225      return;
226    while(1) {
227     if (isPending(pendingInput, 10)) { // faraon'Ù ÐÒÏÓÀÔØ ...
228       if (process_requests()) {
229         log("sfinx:run", "Bad faraon request");
230         break;
231      }
232   }
233    Thread::sleep(10);
234   }
236  catch (Socket *s) {
237     tpport_t port;
238     InetAddress saddr = (InetAddress)getPeer(&port);
239     log("sfinx:run","Faraon client error at %s:%d - %s", saddr.getHostname(),
240             port, getErrorString());
242  catch (IBPP::Exception& e) {
243    log("sfinx:run", "%s", e.what());
244    sfinx->ui()->alert("%s() Error !", e.Origin());
246   final();
249 void faraon_session::get_slice(sfinx_id_t slice_id, sfinx_tid_t tid)
251  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
252    IBPP::ilConcurrency, IBPP::lrWait);
253  tr->Start();
254  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
255  st->Prepare("select m.id, m.name, m.description, m.parent_id, (select name from slices where id = m.parent_id) as parent_name, m.ctime, m.etime, m.directory from slices m where m.id = ?");
256  st->Set(1, (int64_t)slice_id);
257  st->Execute();
258  string name, directory, description, parent_name;
259  int64_t id, parent_id;
260  sfinx_timestamp_t ctime, etime;
261  if (!st->Fetch())
262    return;
263  st->Get(1, &id);
264  st->Get(2, name);
265  st->Get(3, description);
266  st->Get(4, &parent_id);
267  if (!parent_id)
268    parent_name = "Dao";
269  else {
270    st->Get(5, parent_name);
272  st->Get(6, ctime);
273  st->Get(7, etime);
274  st->Get(8, directory);
275  sfinx_slice_t slice(id, name, directory, description, parent_name, parent_id, ctime, etime, tid);
276  tr->Commit();
277  send(slice);
280 void faraon_session::fill_files(sfinx_slice_t *slice)
282  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
283    IBPP::ilConcurrency, IBPP::lrWait);
284  tr->Start();
285  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
286  st->Prepare("select id, title, name, description, ctime, etime, mtag_id, mtag_type from files where "
287    "mtag_slice_id = ? order by ctime desc");
288  st->Set(1, int64_t(slice->id));
289  st->Execute();
290  int64_t id, mtag_id;
291  int32 mtag_type;
292  sfinx_timestamp_t ctime, etime;
293  string name, description, title;
294  while (st->Fetch()) {
295    st->Get(1, &id);
296    st->Get(2, title);
297    st->Get(3, name);
298    st->Get(4, description);
299    st->Get(5, ctime);
300    st->Get(6, etime);
301    st->Get(7, &mtag_id);
302    st->Get(8, &mtag_type);
303    sfinx_object_t file(SFINX_FILE_OBJECT, (sfinx_id_t)id, slice->id, title.c_str(), ctime, etime);
304    file.description = " [ " + name + (description.size() ? ("/" + description) : "") + " ]";
305    slice->add(file);
309 void faraon_session::fill_notes(sfinx_slice_t *slice)
311  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
312    IBPP::ilConcurrency, IBPP::lrWait);
313  tr->Start();
314  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
315  st->Prepare("select id, name, ctime, etime, mtag_id, mtag_type from notes where "
316    "mtag_slice_id = ? order by ctime desc");
317  st->Set(1, int64_t(slice->id));
318  st->Execute();
319  int64_t id, mtag_id;
320  int32 mtag_type;
321  sfinx_timestamp_t ctime, etime;
322  string name, description;
323  while (st->Fetch()) {
324    st->Get(1, &id);
325    st->Get(2, name);
326    // note description - ' for [[SFCN] mtag_name ]'
327    st->Get(3, ctime);
328    st->Get(4, etime);
329    st->Get(5, &mtag_id);
330    st->Get(6, &mtag_type);
331    sfinx_object_t o;
332    o.id = mtag_id;
333    o.type = mtag_type;
334    get_object(&o);
335    description = " for ";
336    description += tagtype2str(o);
337    description += " " + o.name;
338    if (o.description.size())
339      description += (" [ " + o.description + " ]");
340    sfinx_object_t note(SFINX_NOTE_OBJECT, (sfinx_id_t)id, slice->id, name.c_str(), ctime, etime);
341    note.description = description;
342    slice->add(note);
346 void faraon_session::add_slices_from_parent(sfinx_id_t parent_id, IBPP::Transaction tr, sfinx_slice_vector_t *slices,
347   u32_t obj_mask)
349  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
350  st->Prepare("select m.id, m.name, m.description, (select name from slices where id = "
351    "m.parent_id) as parent_name, m.ctime, m.etime, m.directory from slices m where parent_id = ? "
352    "order by ctime");
353  st->Set(1, (int64_t)parent_id);
354  st->Execute();
355  string name, description, parent_name, directory;
356  int64_t id;
357  sfinx_timestamp_t ctime, etime;
358  while (st->Fetch()) {
359   st->Get(1, &id);
360   st->Get(2, name);
361   st->Get(3, description);
362   if (!parent_id)
363     parent_name = "Dao";
364   else {
365     st->Get(4, parent_name);
367   st->Get(5, ctime);
368   st->Get(6, etime);
369   st->Get(7, directory);
370   sfinx_slice_t slice(id, name, directory, description, parent_name, parent_id, ctime, etime);
371   if (obj_mask & (1 << SFINX_FILE_OBJECT))
372     fill_files(&slice);
373   if (obj_mask & (1 << SFINX_NOTE_OBJECT))
374     fill_notes(&slice);
375   slices->add(slice);
376   add_slices_from_parent(id, tr, slices, obj_mask);
380 // ÐÅÒÅÄÁÅÔ ÄÅÒÅ×Ï ÓÌÁÊÓÏ× + ×ÌÏÖÅÎÎÙÅ ÏÂØÅËÔÙ, ÔÉРËÏÔÏÒÙÈ ÏÇÒÁÎÉÞÅΠÍÁÓËÏÊ
381 // ÄÅÒÅ×Ï ÐÅÒÅÄÁÅÔÓÑ ÏÔ ËÏÒÎÑ Ë ÌÉÓÔØÑÍ
382 // ÐÏËÁ ÐÒÉÍÅÎÉÍ application-side ÒÅËÕÒÓÉÀ
383 void faraon_session::get_objects(sfinx_tid_t reply_id, u32_t obj_mask)
385  sfinx_slice_vector_t slices(reply_id);
386  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
387   IBPP::ilConcurrency, IBPP::lrWait);
388  tr->Start();
389  add_slices_from_parent(0, tr, &slices, obj_mask);
390  tr->Commit(); 
391  send(slices);
394 // convert all names from utf8 to filesystem charset
395 string sfinx_app::utf82fs(string &s)
397  size_t insize = s.size(), outsize = insize + 128, osize = outsize;
398  char *inptr = (char *)s.c_str(), *outbuf = new char[outsize], *buf = outbuf;
399  size_t nconv = iconv (from_utf8_cd, &inptr, &insize, &outbuf, &outsize);
400  string fs;
401  if (nconv == (size_t) -1) {
402    F::log("iconv", "conversion error %s", strerror(errno));
403    return fs;
404  }                   
405  // zero terminate
406  buf[osize - outsize] = 0;
407  fs = buf;
408  delete [] buf;
409  return fs;
412 string sfinx_app::fs2utf8(string &s)
414  size_t insize = s.size(), utf8size = insize * 2 + 128, osize = utf8size;
415  char *inptr = (char *)s.c_str(), *utf8buf = new char[utf8size],
416    *out = utf8buf;
417  size_t nconv = iconv (to_utf8_cd, &inptr, &insize, &utf8buf, &utf8size);
418  string utf;
419  if (nconv == (size_t) -1) {
420    F::log("iconv", "conversion error %s", strerror(errno));
421    return utf;
423  // zero terminate
424  out[osize - utf8size] = 0;
425  utf = out;
426  delete [] out;
427  return utf;
430 bool sfinx_move(string &from, string &to)
432  // debug("moving from %s -> %s", from.c_str(), to.c_str());
433  string fromfs = sfinx->utf82fs(from), tofs = sfinx->utf82fs(to);
434  int res = system(("mv \"" + fromfs + "\" \"" + tofs + "\"").c_str());
435  if (res)
436    debug("sfinx_move: res %d", res);
437  return res;
440 bool sfinx_rename(string &from, string &to)
442  return sfinx_move(from, to);
445 bool sfinx_unlink(string &file)
447  string fs = sfinx->utf82fs(file);
448  int res = unlink(fs.c_str());
449  if (res)
450    debug("sfinx_unlink %s: error %s", fs.c_str(), strerror(errno));
451  return res;
454 bool sfinx_rmdir(string &dir)
456  string fs = sfinx->utf82fs(dir);
457  int res = rmdir(fs.c_str());
458  if (res)
459    debug("sfinx_unlink %s: error %s", fs.c_str(), strerror(errno));
460  return res;
463 // TODO: make reply alert
464 void faraon_session::update_slice(sfinx_slice_t *slice)
466  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
467    IBPP::ilConcurrency, IBPP::lrWait);
468  tr->Start();
469  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr); 
470  string old_dir = sfinx->slice_directory(slice->id);
471  if (old_dir != slice->directory()) {
472    string from, to;
473    sfinx_object_t o;
474    o.type = SFINX_SLICE_OBJECT;
475    o.id = o.slice_id = slice->id;
476    sfinx->set_sorted_path(o);
477    from = o.path_name;
478    const char *p = strrchr(from.c_str(), '/');
479    if (!p)
480            bug();
481          char path[1024];
482          path[0] = 0;
483          strncat(path, from.c_str(), p - from.c_str());
484          to = path;
485          to += "/";
486          to += slice->directory();
487    sfinx_move(from, to);
489   st->Prepare("update slices set name = ?, description = ?, directory = ? where id = ?");
490   st->Set(1, slice->name());
491   st->Set(2, slice->description());
492   st->Set(3, slice->directory());
493   st->Set(4, (int64_t)slice->id);
494   st->Execute();
495   tr->Commit();
498 void faraon_session::new_slice(sfinx_slice_t *slice)
500  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
501    IBPP::ilConcurrency, IBPP::lrWait);
502  tr->Start();
503  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
504  st->Prepare("insert into slices (parent_id, name, description, directory) values  (?, ?, ?, ?)");
505  st->Set(1, (int64_t)slice->parent_id);
506  st->Set(2, slice->name());
507  st->Set(3, slice->description());
508  st->Set(4, slice->directory());
509  st->Execute();
510  tr->Commit();
513 void faraon_session::delete_slice_recursivly(sfinx_id_t slice_id)
515  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
516    IBPP::ilConcurrency, IBPP::lrWait);
517  tr->Start();
518  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
519  st->Prepare("select id from slices where parent_id = ?");
520  st->Set(1, (int64_t)slice_id);
521  st->Execute();
522  int32_t id;
523  while (st->Fetch()) {
524    st->Get(1, &id);
525    delete_slice_recursivly(id);
527  st->Prepare("delete from slices where id = ?");
528  st->Set(1, (int64_t)slice_id);
529  st->Execute();
530  tr->Commit(); // may be we need commit only at the end of the whole recursive deletion ?
533 void faraon_session::delete_slice_with_reattach(sfinx_id_t slice_id)
535  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
536    IBPP::ilConcurrency, IBPP::lrWait);
537  tr->Start();
538  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
539  st->Prepare("update slices set parent_id = (select parent_id from slices where id = ?) where parent_id = ?");
540  st->Set(1, (int64_t)slice_id);
541  st->Set(2, (int64_t)slice_id);
542  st->Execute();
543  st->Prepare("delete from slices where id = ?");
544  st->Set(1, (int64_t)slice_id);
545  st->Execute();
546  tr->Commit();
549 void faraon_session::delete_slice_assoc_data(sfinx_id_t slice_id, bool recursivly)
551  mark_files_unsorted(slice_id, recursivly, true);
552  // delete_notes();
553  // ...
556 void faraon_session::delete_slice_mark_data_unsorted(sfinx_id_t slice_id, bool recursivly)
558  mark_files_unsorted(slice_id, recursivly);
559  // mark_notes_unsorted();
560  // ...
563 void faraon_session::mark_files_unsorted(sfinx_id_t slice_id, bool recursivly, bool remove)
565  // delete from file_tags
566  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
567    IBPP::ilConcurrency, IBPP::lrWait);
568  tr->Start();
569  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
570  st->Prepare("delete from file_tags where obj_type = 1 and obj_id = ?");
571  st->Set(1, (int64_t)slice_id);
572  st->Execute();
573  // move to unsorted location
574  st->Prepare("select name from files where mtag_type = 1 and mtag_id = ?");
575  st->Set(1, (int64_t)slice_id);
576  st->Execute();
577  string udir, sdir;
578  sfinx_object_t o(SFINX_SLICE_OBJECT, slice_id, slice_id);
579  sfinx->set_sorted_path(o);
580  sdir = o.path_name + "/";
581  sfinx->files_module_conf.get(FILES_MODULE_UNSORTED_PATH, udir);
582  while(st->Fetch()) {
583    string name, from;
584    st->Get(1, name);
585    from = sdir + name;
586    if (remove)
587      sfinx_unlink(from);
588    else
589      sfinx_move(from, udir);
591  // delete from files
592  st->Prepare("delete from files where mtag_id = 1 and mtag_id = ?");
593  st->Set(1, (int64_t)slice_id);
594  st->Execute();
595  gen_desc_file(o);
596  if (recursivly) {
597    u32_t pid = sfinx->parent_slice_id(slice_id);
598    if (pid)
599      mark_files_unsorted(pid, true, remove);
601  tr->Commit(); 
604 void faraon_session::delete_from_files(sfinx_object_t *f, bool remove)
606  // delete from file_tags
607  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
608    IBPP::ilConcurrency, IBPP::lrWait);
609  tr->Start();
610  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
611  st->Prepare("delete from file_tags where file_id = ?");
612  st->Set(1, (int64_t)f->id);
613  st->Execute();
614  // move to unsorted location
615  string udir, sdir;
616  sfinx->set_sorted_path(*f);
617  sdir = f->path_name + "/";
618  sfinx->files_module_conf.get(FILES_MODULE_UNSORTED_PATH, udir);
619  string from = sdir + f->name;
620  if (remove)
621    sfinx_unlink(from);
622  else
623    sfinx_move(from, udir);
624  // delete from files
625  st->Prepare("delete from files where id = ?");
626  st->Set(1, (int64_t)f->id);
627  st->Execute();
628  tr->Commit();
629  gen_desc_file(*f);
632 void faraon_session::delete_from_notes(sfinx_object_t *o, bool remove)
634  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
635    IBPP::ilConcurrency, IBPP::lrWait);
636  tr->Start();
637  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
638  // delete note tags
639  st->Prepare("delete from note_tags where note_id = ?");
640  st->Set(1, (int64_t)o->id);
641  st->Execute();
642  // delete note
643  st->Prepare("delete from notes where id = ?");
644  st->Set(1, (int64_t)o->id);
645  st->Execute();
646  tr->Commit();
649 void faraon_session::delete_by_mtag_from_notes(sfinx_object_t *o, bool remove)
651  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
652    IBPP::ilConcurrency, IBPP::lrWait);
653  tr->Start();
654  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
655  // search for note mtagged with o
656  st->Prepare("select id from notes where mtag_type = ? and mtag_id = ?");
657  st->Set(1, (int32_t)o->type);
658  st->Set(2, (int64_t)o->id);
659  st->Execute();
660  while(st->Fetch()) {
661    int64_t dn_id;
662    st->Get(1, &dn_id);
663    sfinx_object_t dn(SFINX_NOTE_OBJECT, dn_id); // depended note
664    // × Ó×ÏÀ ÏÞÅÒÅÄØ ÕÄÁÌÑÅÍ ×ÓÅ ÏÂØÅËÔÙ, ÚÁ×ÉÓÑÝÉÅ ÏÔ ÜÔÏÊ note
665    delete_by_mtag(&dn, remove);
666    delete_from_notes(&dn, remove);
668   tr->Commit();
671 void faraon_session::delete_by_mtag_from_files(sfinx_object_t *o, bool remove)
673  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
674    IBPP::ilConcurrency, IBPP::lrWait);
675  tr->Start();
676  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
677  // search for note mtagged with o
678  st->Prepare("select id from files where mtag_type = ? and mtag_id = ?");
679  st->Set(1, (int32_t)o->type);
680  st->Set(2, (int64_t)o->id);
681  st->Execute();
682  while(st->Fetch()) {
683    int64_t df_id;
684    st->Get(1, &df_id);
685    sfinx_object_t df(SFINX_FILE_OBJECT, df_id); // depended file
686    // × Ó×ÏÀ ÏÞÅÒÅÄØ ÕÄÁÌÑÅÍ ×ÓÅ ÏÂØÅËÔÙ, ÚÁ×ÉÓÑÝÉÅ ÏÔ ÜÔÏÇÏ file
687    delete_by_mtag(&df, remove);
688    delete_from_files(&df, remove);
690   tr->Commit();
693 // ÍÏÖÅÔ ÐÅÒÅÄÁ×ÁÔØ tr ÐÏ ÒÅËÕÒÓÉÉ ?
694 void faraon_session::delete_object_recursivly(sfinx_object_t *o, bool remove)
696  // delete depended objects
697  delete_by_mtag(o, remove);
698  // delete object itself
699  switch (o->type) {
700    case SFINX_NOTE_OBJECT:
701      delete_from_notes(o, remove);
702      break;
703    case SFINX_FILE_OBJECT:
704      delete_from_files(o, remove);
705      break;
706    default:
707      break;
711 void faraon_session::update_files_module_conf(sfinx_pair_vector_t *conf)
713  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
714    IBPP::ilConcurrency, IBPP::lrWait);
715  tr->Start();
716  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
717  st->Prepare("update files_module_conf set unsorted_files_path = ?, sorted_file_tree = ?, "
718    "desc_file_name = ?, desc_file_enable = ?");
719  string t;
720  conf->get(FILES_MODULE_UNSORTED_PATH, t);
721  st->Set(1, t);
722  conf->get(FILES_MODULE_SORTED_TREE_PATH, t);
723  st->Set(2, t);
724  conf->get(FILES_MODULE_DESC_FILE_NAME, t);
725  st->Set(3, t);
726  u32_t gen_desc_files;
727  conf->get(FILES_MODULE_DESC_FILE_ENABLE, &gen_desc_files);
728  st->Set(4, (int32_t)gen_desc_files);
729  st->Execute();
730  tr->Commit();
731  module_conf_request(SFINX_FILES_MODULE_CONF_REQUEST);
734 void sfinx_app::load_module_conf(u32_t id)
736  IBPP::Transaction tr = driver_->TransactionFactory(db_, IBPP::amRead,
737    IBPP::ilConcurrency, IBPP::lrWait);
738  tr->Start();
739  IBPP::Statement st = driver_->StatementFactory(db_, tr);
740  switch (id) {
741    case SFINX_FILES_MODULE_CONF_REQUEST:
742      st->Prepare("select unsorted_files_path, sorted_file_tree, desc_file_name, desc_file_enable from files_module_conf");
743      st->Execute();
744      files_module_conf.clear();
745      files_module_conf.tid(SFINX_FILES_MODULE_CONF);
746      while (st->Fetch()) {
747        string val;
748        st->Get(1, val);
749        files_module_conf.add(FILES_MODULE_UNSORTED_PATH, val);
750        st->Get(2, val);
751        files_module_conf.add(FILES_MODULE_SORTED_TREE_PATH, val);
752        st->Get(3, val);
753        files_module_conf.add(FILES_MODULE_DESC_FILE_NAME, val);
754        int32_t enable;
755        st->Get(4, &enable);
756        files_module_conf.add(FILES_MODULE_DESC_FILE_ENABLE, enable);
757     }
758      break;
759    default:
760      log("sfinx:load_module_conf", "Unknown module id - 0x%x", id);
761      break;
763  tr->Commit();
766 void faraon_session::module_conf_request(u32_t id)
768  switch (id) {
769    case SFINX_FILES_MODULE_CONF_REQUEST:
770      sfinx->load_module_conf(id);
771      send(sfinx->files_module_conf);
772      break;
773    default:
774      log("sfinx:module_conf_request", "Unknown module id - 0x%x", id);
775      break;
779 void faraon_session::relink_slice(sfinx_slice_t *slice)
781  // move directories
782  string from, to;
783  sfinx_object_t o_from(SFINX_SLICE_OBJECT, slice->id, slice->id);
784  sfinx->set_sorted_path(o_from);
785  from = o_from.path_name;
786  sfinx_object_t o_to(SFINX_SLICE_OBJECT, slice->parent_id, slice->parent_id);
787  sfinx->set_sorted_path(o_to);
788  to = o_to.path_name;
789  sfinx->sorted_path_mkdir(SFINX_SLICE_OBJECT, slice->parent_id, slice->parent_id);
790  sfinx_move(from, to);
791 // relink
792  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
793    IBPP::ilConcurrency, IBPP::lrWait);
794  tr->Start();
795  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
796  st->Prepare("update slices set parent_id = ? where id = ?");
797  st->Set(1, (int64_t)slice->parent_id);
798  st->Set(2, (int64_t)slice->id);
799  st->Execute();
800  tr->Commit();
803 #include <dirent.h>
804 #include <errno.h>
805 #include <magic.h>
807 // f->name - current unsorted dir
808 void faraon_session::send_unsorted_dir(sfinx_file_t *f)
810  string dir;
811  sfinx->files_module_conf.get(FILES_MODULE_UNSORTED_PATH, dir);
812  sfinx_files_vector_t files(SFINX_FILES_MODULE_UNSORTED_TREE);
813  if (f->name.size())
814    dir += f->name;
815  bool mime_detect = true;
816  // TODO: change mime_detect
817  //
818  //      0 - no detect
819  //      1 - deferable detect - send list firts, ÚÁÔÅÍ ÄÏÓÙÌÁÅÍ mimes ÞÁÓÔÑÍÉ
820  //      2 - full detect
822  struct magic_set *ms;
823  if (mime_detect) {
824    ms = magic_open(MAGIC_MIME | MAGIC_PRESERVE_ATIME | MAGIC_COMPRESS);
825    if (!ms)
826      mime_detect = false;
827    else {
828      if (magic_load(ms, NULL) == -1)
829        mime_detect = false;
830    }
832  struct dirent **namelist;
833  string fsdir = sfinx->utf82fs(dir);
834  int n = scandir(fsdir.c_str(), &namelist, 0, alphasort);
835  if (n < 0) {
836    debug("%s scandir error: %s !", dir.c_str(), strerror(errno));
837    return;
839   sfinx_file_t file;
840   sfinx_progress_t prg("Processing files metadata ...");
841   prg.max(n);
842   send(prg);
843   for (int i = 0; i < n; i++) {
844    if (prg.set(i, .5)) // ÛÁÇ 0.5%
845      send(prg);
846    file.clear();
847    if (!strcmp(namelist[i]->d_name, ".") || !strcmp(namelist[i]->d_name, ".."))
848      continue;
849    file.name = namelist[i]->d_name;
850    struct stat64 inode;
851    string full_path = fsdir + '/' + file.name;
852    if (stat64(full_path.c_str(), &inode))
853      debug("%s stat error: %s", full_path.c_str(), strerror(errno));
854    else
855      file.fsize = inode.st_size;
856    if (inode.st_mode & S_IFDIR)
857      file.is_directory = true;
858    file.etime.set(inode.st_ctime); // status changes
859    file.ctime.set(inode.st_mtime); // last modification
860    file.id = file.compressed_fsize = file.mtag.type = file.mtag.id = 0;
861    if (mime_detect) {
862      const char *mimetype = magic_file(ms, full_path.c_str());
863      if (mimetype)
864        file.mimetype = mimetype;
865   } else {
866     if (file.is_directory)
867       file.mimetype = "inode/directory"; // "application/x-not-regular-file";
868     else
869       file.mimetype = "application/octet-stream";
870   }
871    free(namelist[i]);
872    // convert to utf8
873    file.name = sfinx->fs2utf8(file.name);
874    files.add(file);
876   prg.end();
877   send(prg);
878   free(namelist);
879   send(files);
882 // may be use 7z.so, progress bar ?
883 bool sfinx_compress(string &infile, string *newname)
885  string fsfile = sfinx->utf82fs(infile);
886  int res = system(("7zr a -mx=9 " + fsfile + ".7z " + fsfile +
887    " >/dev/null 2>&1").c_str());
888  if (res) {
889    debug("sfinx_compress %s: res %d", fsfile.c_str(), res);
890    return true;
891  } else
892    sfinx_unlink(infile);
893  *newname = infile + ".7z";
894  return false;
897 bool sfinx_decompress(string &infile, string *newname)
899  string fsfile = sfinx->utf82fs(infile);
900  int res = system(("7zr x -y -o `dirname " + fsfile + "` " + fsfile +
901    " >/dev/null 2>&1").c_str());
902  if (res) {
903    debug("sfinx_decompress %s: res %d", fsfile.c_str(), res);
904    return true;
905  } else
906    sfinx_unlink(infile);
907  *newname = infile.erase(infile.size() - 3, 3); // get rid off ".7z"
908  return false;
911 // × ÄÉÒÅËÔÏÒÉÉ Ó ÉÍÅÎÅÍ ÓÌÁÊÓÁ ÄÌÑ ×ÓÅÈ ÆÁÊÌÏ× ÓÏÚÄÁÅÍ description.txt ×ÉÄÁ:
913 //  slice_name - slice_decription
915 //  -----------------------------
917 // file1
919 // size1 - XXX
920 // csum1 - XXX
921 // compressed size1 - XXX
922 // compressed csum1 - XXX
923 // ctime1 - YYYY
924 // etime1 - YYYY
926 //  title1
928 //  authority1
930 //  description1
932 //  comments1
934 // -------------------------------
936 // file2 ...
938 bool faraon_session::gen_desc_file(sfinx_object_t &o)
940  string dir, fname;
941  sfinx_object_t t(SFINX_SLICE_OBJECT, o.slice_id, o.slice_id);
942  sfinx->set_sorted_path(t);
943  dir = t.path_name;
944  sfinx->files_module_conf.get(FILES_MODULE_DESC_FILE_NAME, fname);
945  string desc_fname = dir + "/" + fname;
946  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
947    IBPP::ilConcurrency, IBPP::lrWait);
948  tr->Start();
949  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
950  st->Prepare("select name, description, ctime, etime from slices where id = ?");
951  st->Set(1, (int64_t)o.slice_id);
952  st->Execute();
953  if (!st->Fetch()) { // hmm, no such slice ?
954    sfinx_unlink(desc_fname);
955    debug("no such slice %lld", o.slice_id);
956    return true;
957  } else {
958    ofstream f(sfinx->utf82fs(desc_fname).c_str(), ios::out | ios::binary | ios::trunc);
959    if (!f) {
960      debug("Cant open desc file %s", desc_fname.c_str());
961      return true;
962   }
963    string t;
964    st->Get(1, t); // name
965    f << endl;
966    f << t << " - ";
967    st->Get(2, t); // description
968    f << t << endl << endl;
969    // ctime/etime
970    IBPP::Timestamp xtime;
971    st->Get(3, xtime);
972          int year, month, day, hour, min, sec;
973          xtime.GetDate(year, month, day);
974          xtime.GetTime(hour, min, sec);
975          char buf[64];
976          sprintf(buf, "Slice created: %02d/%02d/%04d %02d:%02d:%02d", day, month, year, hour, min, sec);
977          f << buf << endl;
978          st->Get(4, xtime);
979          xtime.GetDate(year, month, day);
980          xtime.GetTime(hour, min, sec);
981          sprintf(buf, "Slice modified: %02d/%02d/%04d %02d:%02d:%02d", day, month, year, hour, min, sec);
982          f << buf << endl;       
983          f.close();
985  // store_compressed
986  // mimetype
987  st->Prepare("select id, name, title, authority, description, comments, ctime, etime, "
988    "fsize, sha256, fsize_compressed, sha256_compressed, csum_last_checked, csum_valid, "
989    "store_in_sorted_location from files where mtag_slice_id = ?");
990  st->Set(1, (int64_t)o.slice_id);
991  st->Execute();
992  while (st->Fetch()) {
993    ofstream f(desc_fname.c_str(), ios::out | ios::binary | ios::app);
994    if (!f) {
995      debug("Cant open desc file %s", desc_fname.c_str());
996      return true;
997   }
998    int64_t fid;
999    st->Get(1, &fid);
1000    string t;
1001    f << endl << "-------------------------------------------------------------------" << endl << endl;
1002    st->Get(2, t); // name
1003    f << "Name: " << sfinx->utf82fs(t) << endl;
1004    st->Get(3, t); // title
1005    f << "Title: " << sfinx->utf82fs(t) << endl;   
1006    st->Get(4, t); // authority
1007    f << "Authority: " << sfinx->utf82fs(t) << endl;
1008    st->Get(5, t); // description
1009    f << "Description: " << sfinx->utf82fs(t) << endl;
1010    st->Get(6, t); // comments
1011    f << "Comments: " << sfinx->utf82fs(t) << endl;
1012    IBPP::Timestamp xtime;
1013    int year, month, day, hour, min, sec;
1014    char buf[64];
1015    st->Get(7, xtime);
1016          xtime.GetDate(year, month, day);
1017          xtime.GetTime(hour, min, sec);
1018          sprintf(buf, "Entry created: %02d/%02d/%04d %02d:%02d:%02d", day, month, year, hour, min, sec);
1019          f << buf << endl;
1020    st->Get(8, xtime);
1021          xtime.GetDate(year, month, day);
1022          xtime.GetTime(hour, min, sec);
1023          sprintf(buf, "Entry modifed: %02d/%02d/%04d %02d:%02d:%02d", day, month, year, hour, min, sec);
1024          f << buf << endl;
1025    int64_t fsize, compressed_fsize;
1026    st->Get(9, fsize);
1027    f << "Size: " << fsize << endl;
1028    st->Get(10, t); // csum
1029    f << "Csum: " << t << endl;
1030    st->Get(11, compressed_fsize);
1031    f << "Compressed size: " << compressed_fsize << endl;
1032    st->Get(12, t); // compressed_csum
1033    f << "Compressed csum: " << t << endl;
1034    // additional tags
1035    IBPP::Statement st1 = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1036    st1->Prepare("select obj_id, obj_type from file_tags where file_id = ?");
1037    st1->Set(1, (int64_t)fid);
1038    st1->Execute();
1039    bool comma = false;
1040    while (st1->Fetch()) {
1041      if (comma)
1042          f << ", ";
1043      else
1044          f << "Additional Tags: ";
1045      int64_t id;
1046      int32_t type;
1047      st1->Get(1, &id);
1048      st1->Get(2, &type);
1049      sfinx_object_t ot;
1050      ot.id = id;
1051      ot.type = type;
1052      get_object(&ot);
1053      f << tagtype2str(ot) << ": ";
1054      f << sfinx->utf82fs(ot.name) << " [ ";
1055      f << sfinx->utf82fs(ot.description) << " ]";
1056      comma = true;
1057      f << endl;
1058   }
1059    f.close();
1060  } // while (files)
1061   tr->Commit();
1062   return false;
1065 // sets slice_id, name, description for type/id
1066 // return true if success
1067 bool faraon_session::get_object(sfinx_object_t *dst, sfinx_type_t obj_type, sfinx_id_t obj_id)
1069  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
1070    IBPP::ilConcurrency, IBPP::lrWait);
1071  tr->Start();
1072  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1073  int64_t slice_id;
1074  switch (obj_type) {
1075    case SFINX_SLICE_OBJECT:
1076      st->Prepare("select name, description, ctime, etime from slices where id = ?");
1077      st->Set(1, (int64_t)obj_id);
1078      st->Execute();
1079      if (!st->Fetch())
1080        return false;
1081      st->Get(1, dst->name);
1082      st->Get(2, dst->description);
1083      st->Get(3, dst->ctime);
1084      st->Get(4, dst->etime);
1085      dst->slice_id = obj_id;
1086      break;
1087    case SFINX_FILE_OBJECT:
1088      st->Prepare("select name, description, mtag_slice_id, ctime, etime from files where id = ?");
1089      st->Set(1, (int64_t)obj_id);
1090      st->Execute();
1091      if (!st->Fetch())
1092        return false;
1093      st->Get(1, dst->name);
1094      st->Get(2, dst->description);
1095      st->Get(3, &slice_id);
1096      st->Get(4, dst->ctime);
1097      st->Get(5, dst->etime);
1098      dst->slice_id = slice_id;
1099      break;
1100    case SFINX_NOTE_OBJECT:
1101      st->Prepare("select name, mtag_slice_id, secured, ctime, etime from notes where id = ?");
1102      st->Set(1, (int64_t)obj_id);
1103      st->Execute();
1104      if (!st->Fetch())
1105        return false;
1106      st->Get(1, dst->name);
1107      st->Get(2, &slice_id);
1108      st->Get(4, dst->ctime);
1109      st->Get(5, dst->etime);
1110      dst->slice_id = slice_id;     
1111      //st->Get(3, dst->description); // set secured
1112      break;
1113    default:
1114      return false;
1116   tr->Commit();
1117   return true;
1120 // send note by id
1121 void faraon_session::send_note(sfinx_note_t *n)
1123  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
1124    IBPP::ilConcurrency, IBPP::lrWait);
1125  tr->Start();
1126  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1127  st->Prepare("select name, url, text, ctime, etime, mtag_type, mtag_id, secured from notes where id = ?");
1128  st->Set(1, (int64_t)n->id);
1129  st->Execute();
1130  sfinx_note_t note;
1131  note.copy(n);
1132  if (!st->Fetch()) {
1133    sfinx_string_t alert(SFINX_ALERT);
1134    alert.set("No such note in database !");
1135    send(alert);
1136    return;
1137  } else {
1138    st->Get(1, note.name);
1139    st->Get(2, note.url);
1140    st->Get(3, note.text);
1141    st->Get(4, note.ctime);
1142    st->Get(5, note.etime);
1143    int32_t mtag_type;
1144    st->Get(6, &mtag_type);
1145    note.mtag.type = mtag_type;
1146    int64_t mtag_id;
1147    st->Get(7, &mtag_id);
1148    note.mtag.id = mtag_id;
1149    get_object(&note.mtag);
1150    int16_t secured;
1151    st->Get(8, &secured);
1152    note.secured = secured;
1154  // fill note tags
1155  st->Prepare("select obj_id, obj_type from note_tags where note_id = ?");
1156  st->Set(1, (int64_t)n->id);
1157  st->Execute();
1158  while (st->Fetch()) {
1159    int64_t tag_id;
1160    int32_t tag_type;
1161    st->Get(1, &tag_id);
1162    st->Get(2, &tag_type);
1163    // get tag by type and id
1164    sfinx_object_t o;
1165    o.type = tag_type;
1166    o.id = tag_id;
1167    if (get_object(&o))
1168      note.tags.push_back(o);
1170  tr->Commit();
1171  send(note);
1174 // send file by id
1175 void faraon_session::send_file(sfinx_file_t *f)
1177  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
1178    IBPP::ilConcurrency, IBPP::lrWait);
1179  tr->Start();
1180  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1181  // store_compressed
1182  // mimetype
1183  st->Prepare("select name, title, authority, description, comments, ctime, etime, "
1184    "fsize, sha256, fsize_compressed, sha256_compressed, csum_last_checked, csum_valid, "
1185    "store_in_sorted_location, mtag_type, mtag_id from files where id = ?");
1186  st->Set(1, (int64_t)f->id);
1187  st->Execute();
1188  sfinx_file_t file(f->tid());
1189  file.id = f->id;
1190  if (!st->Fetch()) {
1191    sfinx_string_t alert(SFINX_ALERT);
1192    alert.set("No such file in database !");
1193    send(alert);
1194    return;
1195  } else {
1196    st->Get(1, file.name);
1197    st->Get(2, file.title);
1198    st->Get(3, file.authority);
1199    st->Get(4, file.description);
1200    st->Get(5, file.comments);
1201    st->Get(6, file.ctime);
1202    st->Get(7, file.etime);
1203    int64_t fsize, compressed_fsize;
1204    st->Get(8, fsize);
1205    st->Get(9, file.csum);
1206    st->Get(10, compressed_fsize);
1207    file.fsize = fsize;
1208    file.compressed_fsize = compressed_fsize;
1209    st->Get(11, file.compressed_csum);
1210    int16_t sorted_location;
1211    st->Get(14, &sorted_location);
1212    file.sorted_location = sorted_location;
1213    file.mimetype = "Not Set";
1214    int64_t mid;
1215    int32_t mtype;
1216    st->Get(15, &mtype);
1217    file.mtag.type = mtype;
1218    st->Get(16, &mid);
1219    file.mtag.id = mid;
1220    get_object(&file.mtag);
1222  // fill file slices
1223  st->Prepare("select obj_id, obj_type from file_tags where file_id = ?");
1224  st->Set(1, (int64_t)f->id);
1225  st->Execute();
1226  while (st->Fetch()) {
1227    int64_t id;
1228    int32_t type;
1229    st->Get(1, &id);
1230    st->Get(2, &type);
1231    sfinx_object_t o;
1232    o.id = id;
1233    o.type = type;
1234    if (get_object(&o))
1235      file.tags.push_back(o);
1237   tr->Commit();
1238   send(file);
1241 void faraon_session::files_module_classify(sfinx_file_t *f)
1243  IBPP::Transaction tr;
1244  IBPP::Statement st;
1245  sfinx_string_t reply(SFINX_FILES_MODULE_CLASSIFY_REPLY);
1246  string compressed_name, dir, fname;
1247  sfinx_hash_t csum(GCRY_MD_SHA256), compressed_csum(GCRY_MD_SHA256);
1248  sfinx->files_module_conf.get(FILES_MODULE_UNSORTED_PATH, dir);
1249  fname = dir + "/" + f->name;
1250  // rename file
1251  if (f->name != f->orig_name) {
1252    string from = dir + "/" + f->orig_name, to = dir + "/" + f->name;
1253    if (sfinx_rename(from, to)) {
1254      reply.set("Error renaming file !");
1255      goto out;
1256    }
1258  // checksum file
1259  reply.set("Error calculating checksum for file !");
1260  if (f->generate_csum && csum.hash(sfinx->utf82fs(fname)))
1261    goto out;
1262  f->csum = csum.strvalue();
1263  if (f->sorted_location) {
1264    reply.set("Error creating Sorted Location !");
1265    if (sfinx->sorted_path_mkdir(f->mtag))
1266        goto out;
1267    reply.set("Error moving file to Sorted Location !");
1268    if (sfinx_move(fname, f->mtag.path_name))
1269      goto out;
1271  fname = f->mtag.path_name + "/" + f->name;
1272  // get size
1273  struct stat64 inode;
1274  reply.set("Error getting file size !");
1275  if (stat64(sfinx->utf82fs(fname).c_str(), &inode))
1276    goto out;
1277  else
1278    f->fsize = inode.st_size;
1279  // compress file
1280  if (f->store_compressed) {
1281    // check if file already compressed
1282    bool compressed = false;
1283    if (f->name.size() > 3) {
1284      string ext(f->name, f->name.size() - 3);
1285      if (ext == ".7z")
1286        compressed = true;
1287   }
1288    reply.set("Error compressing file !");
1289    if (!compressed) {
1290      if (sfinx_compress(fname, &compressed_name))
1291        goto out;
1292      else
1293        f->name += ".7z";
1294    } else
1295        compressed_name = fname;
1296    reply.set("Error calculating checksum for compressed file !");
1297    if (f->generate_csum && compressed_csum.hash(sfinx->utf82fs(compressed_name)))
1298      goto out;
1299    f->compressed_csum = compressed_csum.strvalue();
1300    reply.set("Error getting compressed file size !");
1301    if (stat64(sfinx->utf82fs(compressed_name).c_str(), &inode))
1302      goto out;
1303    else
1304      f->compressed_fsize = inode.st_size;
1306  // add to files
1307  tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite, IBPP::ilConcurrency, IBPP::lrWait);
1308  tr->Start();
1309  st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1310  st->Prepare("insert into files (name, title, authority, description, comments, mtag_id, mtag_type, "
1311    "mtag_slice_id, fsize, sha256, fsize_compressed, sha256_compressed, store_in_sorted_location) values "
1312    "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
1313  st->Set(1, f->name);
1314  st->Set(2, f->title);
1315  st->Set(3, f->authority);
1316  st->Set(4, f->description);
1317  st->Set(5, f->comments);
1318  st->Set(6, (int64_t)f->mtag.id);
1319  st->Set(7, (int32_t)f->mtag.type);
1320  st->Set(8, (int64_t)f->mtag.slice_id);
1321  st->Set(9, (int64_t)f->fsize);
1322  st->Set(10, f->csum);
1323  st->Set(11, (int64_t)f->compressed_fsize);
1324  st->Set(12, f->compressed_csum);
1325  st->Set(13, f->sorted_location);
1326  st->Execute();
1328  st->Prepare("select id from files where name = ? and mtag_type = ? and mtag_id = ?");
1329  st->Set(1, f->name);
1330  st->Set(2, (int32_t)f->mtag.type);
1331  st->Set(3, (int64_t)f->mtag.id);
1332  st->Execute();
1333  int64_t file_id;
1334  if (!st->Fetch())
1335    bug();
1336  else {
1337    st->Get(1, &file_id);
1338 //   debug("added file has id - %d", file_id);
1340  // add to file_tags
1341  for (u32_t i = 0; i < f->tags.size(); i++) {
1342    st->Prepare("insert into file_tags (file_id, obj_id, obj_type) values (?, ?, ?)");
1343    st->Set(1, file_id);
1344    st->Set(2, (int64_t)f->tags[i].id);
1345    st->Set(3, (int32_t)f->tags[i].type);
1346    st->Execute();
1348  tr->Commit();
1349  u32_t gen_desc_files;
1350  sfinx->files_module_conf.get(FILES_MODULE_DESC_FILE_ENABLE, &gen_desc_files);
1351  if (gen_desc_files) { // generate decription file
1352    reply.set("Error generating description file !");
1353    if (gen_desc_file(f->mtag))
1354      goto out;
1356   reply.set(""); // No error
1357 out:
1358  send(reply);
1361 void faraon_session::notes_module_add(sfinx_note_t *n)
1363  IBPP::Transaction tr;
1364  IBPP::Statement st;
1365  sfinx_string_t reply(SFINX_NOTES_MODULE_ADD_REPLY);
1366  // add to files
1367  tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite, IBPP::ilConcurrency, IBPP::lrWait);
1368  tr->Start();
1369  st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1370  st->Prepare("insert into notes (name, text, url, mtag_id, mtag_type, mtag_slice_id) values (?, ?, ?, ?, ?, ?)");
1371  st->Set(1, n->name);
1372  st->Set(2, n->text);
1373  st->Set(3, n->url);
1374  st->Set(4, (int64_t)n->mtag.id);
1375  st->Set(5, (int32_t)n->mtag.type);
1376  st->Set(6, (int64_t)n->mtag.slice_id);
1377  st->Execute();
1378  // get new note id
1379  st->Prepare("select id from notes where name = ? and mtag_type = ? and mtag_id = ? and mtag_slice_id = ?");
1380  st->Set(1, n->name);
1381  st->Set(2, (int32_t)n->mtag.type);
1382  st->Set(3, (int64_t)n->mtag.id);
1383  st->Set(4, (int64_t)n->mtag.slice_id);
1384  st->Execute();
1385  int64_t note_id;
1386  if (!st->Fetch())
1387    bug();
1388  else {
1389    st->Get(1, &note_id);
1390 //   debug("added file has id - %d", file_id);
1392  // add note_tags
1393  for (u32_t i = 0; i < n->tags.size(); i++) {
1394    st->Prepare("insert into note_tags (note_id, obj_id, obj_type) values (?, ?, ?)");
1395    st->Set(1, note_id);
1396    st->Set(2, (int64_t)n->tags[i].id);
1397    st->Set(3, (int32_t)n->tags[i].type);
1398    st->Execute();
1400  tr->Commit();
1401  reply.set(""); // No error
1402  send(reply);
1405 bool faraon_session::get_file_by_id(sfinx_file_t *f)
1407  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
1408    IBPP::ilConcurrency, IBPP::lrWait);
1409  tr->Start();
1410  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1411  // store_compressed
1412  // mimetype
1413  st->Prepare("select name, title, authority, description, comments, ctime, etime, mtag_id, "
1414    "mtag_type, fsize, sha256, fsize_compressed, sha256_compressed, csum_last_checked, csum_valid, "
1415    "store_in_sorted_location, mtag_slice_id from files where id = ?");
1416  st->Set(1, (int64_t)f->id);
1417  st->Execute();
1418  if (!st->Fetch())
1419    return false;
1420  else {
1421    st->Get(1, f->name);
1422    st->Get(2, f->title);
1423    st->Get(3, f->authority);
1424    st->Get(4, f->description);
1425    st->Get(5, f->comments);
1426    st->Get(6, f->ctime);
1427    st->Get(7, f->etime);
1428    int64_t fsize, compressed_fsize, mtag_id, mtag_slice_id;
1429    int32_t mtag_type;
1430    st->Get(8, mtag_id);
1431    st->Get(9, mtag_type);
1432    st->Get(10, fsize);
1433    st->Get(11, f->csum);
1434    st->Get(12, compressed_fsize);
1435    f->mtag.id = mtag_id;
1436    f->mtag.type = mtag_type;
1437    f->fsize = fsize;
1438    f->compressed_fsize = compressed_fsize;
1439    st->Get(13, f->compressed_csum);
1440    int32_t sorted_location;
1441    st->Get(16, &sorted_location);
1442    f->sorted_location = sorted_location;
1443    st->Get(17, &mtag_slice_id);
1444    f->mtag.slice_id = mtag_slice_id;
1445    // st->Get(xxx, f->mimetype);
1447  // fill file tags
1448  f->tags.clear();
1449  st->Prepare("select obj_id, obj_type from file_tags where file_id = ?");
1450  st->Set(1, (int64_t)f->id);
1451  st->Execute();
1452  while (st->Fetch()) {
1453    int64_t id;
1454    int32_t type;
1455    st->Get(1, &id);
1456    st->Get(2, &type);
1457    sfinx_object_t o;
1458    o.id = id;
1459    o.type = type;
1460    if (get_object(&o))
1461      f->tags.push_back(o);
1463   tr->Commit();
1464   return true;
1467 void faraon_session::delete_file(sfinx_file_t *f)
1469  string fname;
1470  sfinx->files_module_conf.get(FILES_MODULE_UNSORTED_PATH, fname);
1471  fname += ("/" + f->name);
1472  if (f->is_directory)
1473    sfinx_rmdir(fname);
1474  else
1475    sfinx_unlink(fname);
1478 void faraon_session::update_file(sfinx_file_t *f)
1480  sfinx_file_t old_file;
1481  old_file.id = f->id;
1482  if (!get_file_by_id(&old_file))
1483    bug();
1484  IBPP::Transaction tr;
1485  IBPP::Statement st;
1486  sfinx_string_t reply(SFINX_FILES_MODULE_EDIT_REPLY);
1487  string compressed_name, sorted_location, dir, fname;
1488  if (f->sorted_location) {
1489    sfinx_object_t o(f->mtag.type, f->mtag.id, f->mtag.slice_id);
1490    sfinx->set_sorted_path(o);
1491    dir = o.path_name;
1492  } else
1493    sfinx->files_module_conf.get(FILES_MODULE_UNSORTED_PATH, dir);
1494  fname = dir + "/" + f->name;
1495  if (old_file.store_compressed && !f->store_compressed) {
1496    string n = dir + "/" + f->orig_name;
1497    sfinx_decompress(n, &f->orig_name);
1498    f->compressed_csum.clear();
1499    f->compressed_fsize = 0;
1501  if (!old_file.store_compressed && f->store_compressed) {
1502    // compress
1503    // calculate csum
1505  // rename file
1506  if (f->name != f->orig_name) {
1507    string from = dir + "/" + f->orig_name, to = dir + "/" + f->name;
1508    if (sfinx_rename(from, to)) {
1509      reply.set("Error renaming file !");
1510      goto out;
1511    }
1513  // update file
1514  tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite, IBPP::ilConcurrency, IBPP::lrWait);
1515  tr->Start();
1516  st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1517  st->Prepare("update files set name = ?, title = ?, authority = ?, description = ?, comments = ?, "
1518    "mtag_id = ?, mtag_type = ?, mtag_slice_id = ?, fsize = ?, sha256 = ?, fsize_compressed = ?, sha256_compressed = ?, "
1519    "store_in_sorted_location = ? where id = ?");
1520  st->Set(1, f->name);
1521  st->Set(2, f->title);
1522  st->Set(3, f->authority);
1523  st->Set(4, f->description);
1524  st->Set(5, f->comments);
1525  st->Set(6, (int64_t)f->mtag.id);
1526  st->Set(7, (int32_t)f->mtag.type);
1527  st->Set(8, (int64_t)f->mtag.slice_id);
1528  st->Set(9, (int64_t)f->fsize);
1529  st->Set(10, f->csum);
1530  st->Set(11, (int64_t)f->compressed_fsize);
1531  st->Set(12, f->compressed_csum);
1532  st->Set(13, f->sorted_location);
1533  st->Set(14, (int64_t)f->id);
1534  st->Execute();
1536  // add to file_tags
1537  st->Prepare("delete from file_tags where file_id = ?");
1538  st->Set(1, (int64_t)f->id);
1539  st->Execute();
1540  for (u32_t i = 0; i < f->tags.size(); i++) {
1541    st->Prepare("insert into file_tags (file_id, obj_id, obj_type) values (?, ?, ?)");
1542    st->Set(1, (int64_t)f->id);
1543    sfinx_object_t o = f->tags[i];
1544    st->Set(2, (int64_t)o.id);
1545    st->Set(3, (int32_t)o.type);
1546    st->Execute();
1548  tr->Commit();
1549  u32_t gen_desc_files;
1550  sfinx->files_module_conf.get(FILES_MODULE_DESC_FILE_ENABLE, &gen_desc_files);
1551   // move file and gendesc
1552   if (old_file.sorted_location && f->sorted_location &&
1553     (old_file.mtag.slice_id != f->mtag.slice_id)) {
1554       sfinx_object_t o(old_file.mtag.type, old_file.mtag.id, old_file.mtag.slice_id);
1555       sfinx->set_sorted_path(o);
1556       string from = o.path_name + "/" + old_file.name;
1557       o.type = f->mtag.type;
1558       o.id = f->mtag.id;
1559       o.slice_id = f->mtag.slice_id;
1560       sfinx->set_sorted_path(o);
1561       string to = o.path_name + "/" + f->name;
1562       sfinx->sorted_path_mkdir(f->mtag.type, f->mtag.id, f->mtag.slice_id);
1563       sfinx_move(from, to);
1564       // regen descs
1565       if (gen_desc_files) {
1566         reply.set("Error generating new description file");
1567         if (gen_desc_file(f->mtag))
1568           goto out;
1569         reply.set("Error generating old description file");
1570         if (gen_desc_file(old_file.mtag))
1571           goto out;
1572      }
1573   } else { // simple gendesc
1574    if (gen_desc_files) { // generate decription file
1575      reply.set("Error generating description file !");
1576      if (gen_desc_file(f->mtag))
1577        goto out;
1578    }
1580   reply.set(""); // No error
1581 out:
1582  send(reply);
1585 void faraon_session::update_note(sfinx_note_t *n)
1587  IBPP::Transaction tr;
1588  IBPP::Statement st;
1589  sfinx_string_t reply(SFINX_NOTES_MODULE_EDIT_REPLY);
1590  tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite, IBPP::ilConcurrency, IBPP::lrWait);
1591  tr->Start();
1592  st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1593  st->Prepare("update notes set name = ?, url = ?, text = ?, mtag_id = ?, mtag_type = ?, mtag_slice_id = ?,"
1594    "secured = ? where id = ?");
1595  st->Set(1, n->name);
1596  st->Set(2, n->url);
1597  st->Set(3, n->text);
1598  st->Set(4, (int64_t)n->mtag.id);
1599  st->Set(5, (int32_t)n->mtag.type);
1600  st->Set(6, (int64_t)n->mtag.slice_id);
1601  st->Set(7, (int16_t)n->secured);
1602  st->Set(8, (int64_t)n->id);
1603  st->Execute();
1604  // add to note_tags
1605  st->Prepare("delete from note_tags where note_id = ?");
1606  st->Set(1, (int64_t)n->id);
1607  st->Execute();
1608  for (u32_t i = 0; i < n->tags.size(); i++) {
1609    st->Prepare("insert into note_tags (note_id, obj_id, obj_type) values (?, ?, ?)");
1610    st->Set(1, (int64_t)n->id);
1611    st->Set(2, (int64_t)n->tags[i].id);
1612    st->Set(3, (int32_t)n->tags[i].type);
1613    st->Execute();
1615  tr->Commit();
1616  reply.set(""); // No error
1617  send(reply);
1620 // use get_file_by_id ?
1621 void faraon_session::search_in_files(string &pattern, sfinx_pair_vector_t *r, string &where)
1623  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
1624    IBPP::ilConcurrency, IBPP::lrWait);
1625  tr->Start();
1626  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr),
1627    st1 = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1628  string query = "select id, name, title, authority, description, comments, ctime, etime, mtag_id, "
1629      "mtag_type, fsize, sha256, fsize_compressed, sha256_compressed, csum_last_checked, csum_valid, "
1630      "store_in_sorted_location, mtag_slice_id from files where (name like ? or title like ? or "
1631      "authority like ? or description like ? or comments like ?)";
1632  query += where;
1633  st->Prepare(query);
1634  st->Set(1, pattern);
1635  st->Set(2, pattern);
1636  st->Set(3, pattern);
1637  st->Set(4, pattern);
1638  st->Set(5, pattern);
1639  st->Execute();
1640  int64_t rid = r->len();
1641  while (st->Fetch()) {
1642    sfinx_file_t file;
1643    int64_t fid;
1644    st->Get(1, &fid);
1645    file.id = fid;
1646    st->Get(2, file.name);
1647    st->Get(3, file.title);
1648    st->Get(4, file.authority);
1649    st->Get(5, file.description);
1650    st->Get(6, file.comments);
1651    st->Get(7, file.ctime);
1652    st->Get(8, file.etime);
1653    int64_t fsize, compressed_fsize, mtag_id, mtag_slice_id;
1654    int32_t mtag_type;
1655    st->Get(9, mtag_id);
1656    st->Get(10, mtag_type);
1657    st->Get(11, fsize);
1658    st->Get(12, file.csum);
1659    st->Get(13, compressed_fsize);
1660    file.mtag.id = mtag_id;
1661    file.mtag.type = mtag_type;
1662    file.fsize = fsize;
1663    file.compressed_fsize = compressed_fsize;
1664    st->Get(14, file.compressed_csum);
1665    int32_t sorted_location;
1666    st->Get(17, &sorted_location);
1667    file.sorted_location = sorted_location;
1668    st->Get(18, &mtag_slice_id);
1669    file.mtag.slice_id = mtag_slice_id;
1670    file.mimetype = "Not Set";
1671    // fill file slices
1672    st1->Prepare("select obj_id, obj_type from file_tags where file_id = ?");
1673    st1->Set(1, fid);
1674    st1->Execute();
1675    while (st1->Fetch()) {
1676      int64_t id;
1677      int32_t type;
1678      st1->Get(1, &id);
1679      st1->Get(2, &type);
1680      sfinx_object_t o;
1681      o.id = id;
1682      o.type = type;
1683      if (get_object(&o))
1684        file.tags.push_back(o);
1685    }
1686     r->add(rid++, &file);
1688   tr->Commit();
1691 void faraon_session::search_in_slices(string &pattern, sfinx_pair_vector_t *r, string &where)
1693  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
1694    IBPP::ilConcurrency, IBPP::lrWait);
1695  tr->Start();
1696  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1697  string query = "select id, name, description, ctime, etime from slices where (name like ? or "
1698      "description like ?)";
1699  query += where;
1700  st->Prepare(query);
1701  st->Set(1, pattern);
1702  st->Set(2, pattern);
1703  st->Execute();
1704  int64_t rid = r->len();
1705  while (st->Fetch()) {
1706    sfinx_slice_t slice;
1707    int64_t sid;
1708    st->Get(1, &sid);
1709    slice.id = sid;
1710    st->Get(2, slice.name_);
1711    st->Get(3, slice.description_);
1712    st->Get(4, slice.ctime);
1713    st->Get(5, slice.etime);
1714    r->add(rid++, &slice);
1716   tr->Commit();
1719 void faraon_session::search_in_notes(string &pattern, sfinx_pair_vector_t *r, string &where)
1721  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
1722    IBPP::ilConcurrency, IBPP::lrWait);
1723  tr->Start();
1724  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1725  string query = "select id, name, url, text, ctime, etime, mtag_type, mtag_id, mtag_slice_id from notes "
1726    "where (name like ? or url like ? or text like ?)";
1727  query += where;
1728  st->Prepare(query);
1729  st->Set(1, pattern);
1730  st->Set(2, pattern);
1731  st->Set(3, pattern);
1732  st->Execute();
1733  int64_t rid = r->len();
1734  while (st->Fetch()) {
1735    sfinx_note_t note;
1736    int64_t nid;
1737    st->Get(1, &nid);
1738    note.id = nid;
1739    st->Get(2, note.name);
1740    st->Get(3, note.url);
1741    st->Get(4, note.text);
1742    st->Get(5, note.ctime);
1743    st->Get(6, note.etime);
1744    int64_t mtag_id, mtag_slice_id;
1745    int32_t mtag_type;
1746    st->Get(7, mtag_type);
1747    st->Get(8, mtag_id);
1748    st->Get(9, mtag_slice_id);
1749    note.mtag.id = mtag_id;
1750    note.mtag.type = mtag_type;
1751    note.mtag.slice_id = mtag_slice_id;
1752    r->add(rid++, &note);
1754   tr->Commit();
1757 // TODO: make threaded search, add sort rules
1758 void faraon_session::search_query(sfinx_search_query_t *q)
1760  sfinx_pair_vector_t r(SFINX_ELEMENT_SEARCH_RESULT);
1761  string pattern = '%' + q->pattern + '%';
1762  string where, where_slices;
1763  if (q->rtags.size()) { // build where
1764    char buf[64], buf_slices[64];
1765    where = where_slices = " and (";
1766    for (u32_t i = 0; i < q->rtags.size(); i++) {
1767      if (i) {
1768        where += " or ";
1769        where_slices += " or ";
1770     }
1771      sprintf(buf, "mtag_slice_id = %lld", q->rtags[i].slice_id);
1772      sprintf(buf_slices, "id = %lld", q->rtags[i].slice_id);
1773      where += buf;
1774      where_slices += buf_slices;
1775    }
1776    where += ")";
1777    where_slices += ")";
1779  if (q->area(SFINX_SLICE_OBJECT))
1780    search_in_slices(pattern, &r, where_slices);
1781  if (q->area(SFINX_NOTE_OBJECT))
1782    search_in_notes(pattern, &r, where);
1783  if (q->area(SFINX_FILE_OBJECT))
1784    search_in_files(pattern, &r, where);
1785  send(r);
1788 bool faraon_session::process_requests()
1790  if (read_packet()) {
1791    log("sfinx:process", "Error reading faraon request");
1792    return true;
1794  sfinx_t *el;
1795  string root;
1796  sfinx_object_t o;
1797  sfinx_string_t reply;
1798  while ((el = rx_elements.next())) {
1799    switch (el->tid()) {
1800      case SFINX_NOTES_MODULE_UNSORT:
1801        o.type = SFINX_NOTE_OBJECT;
1802        o.id = ((sfinx_note_t *)el)->id;
1803        o.slice_id = ((sfinx_file_t *)el)->mtag.slice_id;
1804        delete_object_recursivly(&o);
1805        reply.tid(SFINX_NOTES_MODULE_UNSORT_REPLY);
1806        send(reply);
1807        break;
1808      case SFINX_NOTES_MODULE_UNLINK:
1809        o.type = SFINX_NOTE_OBJECT;
1810        o.id = ((sfinx_note_t *)el)->id;
1811        o.slice_id = ((sfinx_file_t *)el)->mtag.slice_id;
1812        delete_object_recursivly(&o, 1);
1813        reply.tid(SFINX_NOTES_MODULE_UNLINK_REPLY);
1814        send(reply);
1815        break;
1816      case SFINX_NOTES_MODULE_EDIT:
1817        update_note((sfinx_note_t *)el);
1818        break;
1819      case SFINX_NOTES_MODULE_EDIT_REQUEST:
1820        send_note((sfinx_note_t *)el);
1821        break;
1822      case SFINX_NOTES_MODULE_ADD:
1823        notes_module_add((sfinx_note_t *)el);
1824        break;
1825      case SFINX_FILES_MODULE_SORTED_UNLINK:
1826        o.type = SFINX_FILE_OBJECT;
1827        o.id = ((sfinx_file_t *)el)->id;
1828        o.slice_id = ((sfinx_file_t *)el)->mtag.slice_id;
1829        delete_object_recursivly(&o, 1);
1830        reply.tid(SFINX_FILES_MODULE_SORTED_UNLINK_REPLY);
1831        send(reply);
1832        break;
1833      case SFINX_FILES_MODULE_UNSORT:
1834        o.type = SFINX_FILE_OBJECT;
1835        o.id = ((sfinx_file_t *)el)->id;
1836        o.slice_id = ((sfinx_file_t *)el)->mtag.slice_id;
1837        delete_object_recursivly(&o);
1838        reply.tid(SFINX_FILES_MODULE_UNSORT_REPLY);
1839        send(reply);
1840        break;
1841      case SFINX_FILES_MODULE_UNSORTED_DELETE:
1842        delete_file((sfinx_file_t *)el);
1843        break;
1844      case SFINX_ELEMENT_SEARCH_QUERY:
1845        search_query((sfinx_search_query_t *)el);
1846        break;
1847      case SFINX_FILES_MODULE_EDIT_FILE:
1848        update_file((sfinx_file_t *)el);
1849        break;
1850      case SFINX_FILES_MODULE_EDIT_REQUEST:
1851        send_file((sfinx_file_t *)el);
1852        break;
1853      case SFINX_FILES_MODULE_CLASSIFY_REQUEST:
1854        files_module_classify((sfinx_file_t *)el);
1855        break;
1856      case SFINX_FILES_MODULE_UNSORTED_TREE_REQUEST:
1857        send_unsorted_dir((sfinx_file_t *)el);
1858        break;
1859      case SFINX_FILES_MODULE_CONF:
1860        update_files_module_conf((sfinx_pair_vector_t *)el);
1861        break;
1862      case SFINX_FILES_MODULE_CONF_REQUEST:
1863        module_conf_request(el->tid());
1864        break;
1865      case SFINX_SLICE_RELINK:
1866        relink_slice((sfinx_slice_t *)el);
1867        break;
1868      case SFINX_DELETE_SLICE_ASSOC_DATA:
1869        delete_slice_assoc_data(((sfinx_32bit_t *)el)->get(), 0);
1870        break;
1871      case SFINX_DELETE_SLICE_ASSOC_DATA_RECURSIVLY:
1872        delete_slice_assoc_data(((sfinx_32bit_t *)el)->get(), 1);
1873        break;
1874      case SFINX_DELETE_SLICE_MARK_DATA_UNSORTED:
1875        delete_slice_mark_data_unsorted(((sfinx_32bit_t *)el)->get(), 0);
1876        break;
1877      case SFINX_DELETE_SLICE_MARK_DATA_UNSORTED_RECURSIVLY:
1878        delete_slice_mark_data_unsorted(((sfinx_32bit_t *)el)->get(), 1);
1879        break;
1880      case SFINX_DELETE_SLICE_WITH_REATTACH:
1881        delete_slice_with_reattach(((sfinx_32bit_t *)el)->get());
1882        break;
1883      case SFINX_DELETE_SLICE_RECURSIVLY:
1884        delete_slice_recursivly(((sfinx_32bit_t *)el)->get());
1885        break;
1886      case SFINX_NEW_SLICE:
1887        new_slice((sfinx_slice_t *)el);
1888        break;
1889      case SFINX_EDIT_SLICE:
1890        update_slice((sfinx_slice_t *)el);
1891        break;
1892      case SFINX_OBJECTS_TREE_REQUEST:
1893        get_objects(SFINX_OBJECTS_TREE, ((sfinx_32bit_t *)el)->get());
1894        break;
1895      case SFINX_EDIT_SLICE_REQUEST:
1896        get_slice(((sfinx_32bit_t *)el)->get(), SFINX_EDIT_SLICE);
1897        break;
1898      default:
1899        log("sfinx:process", "Unknown element %s (id - 0x%x)", sfinx_cmd2str(el->tid()), el->tid());
1900        break;
1901    }
1903  return false;