.
[sfinx.git] / sfinx / sfinx.C
blob873ad7bda781ad46b5d2bb95e80bad01b50d01b7
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 void sfinx_app::dbopen()
13  dbname_ = "/usr/local/sfinx/sfinx.fdb";
14  dbuser_ = "sysdba";
15  dbpass_ = "harbour";
16  db_ = driver_->DatabaseFactory("", dbname_, dbuser_, dbpass_);
17  db_->Connect();
18  log("dbopen", "Connected to database %s", dbname_.c_str());
21 void sfinx_app::listen()
23  InetAddress addr((InetAddrValidator *)0);
24  log("sfinx:listen", "server listening at %d port", SFINX_PORT);
25  try {
26   sfinx_socket server(addr);
27   while(server.isPendingConnection()) {
28     faraon_session *faraon = new faraon_session(server, SFINX_MAX_PACKET_SIZE);
29     faraon->start();
30   }
31  }
32   catch(Socket *socket) {
33   
34     tpport_t port;
35     int err = socket->getErrorNumber();
36     cerr << "client socket error : ";
37     if (err == Socket::errBindingFailed) {
38       cerr << "bind failed; port busy, bye." << endl;
39       ::exit(-1);
40    }
41     IPV4Address saddr = socket->getPeer(&port);
42     const char *host;
43     if (!saddr.isInetAddress())
44      host = "localhost";
45     else
46      host = saddr.getHostname();
47     cerr << host << ":" << port << \
48       " failed : " << socket->getErrorString() << endl;
49  }
50    cerr << "listen terminated" << endl;
53 /*u32_t sfinx_app::get_object_slice(u32_t obj_type, u32_t obj_id)
55  sfinx_object_t o(obj_type, obj_id);
56  while (1) {
57    if (o.otype == SFINX_SLICE_OBJECT)
58      return o.oid;
59    if (!parent_object(o, &o))
60      bug();
61  }
62 }*/
64 sfinx_id_t sfinx_app::parent_slice_id(sfinx_id_t slice_id)
66  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
67    IBPP::ilConcurrency, IBPP::lrWait);
68  tr->Start();
69  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
70  st->Prepare("select parent_id from slices where id = ?");
71  st->Set(1, (int64_t)slice_id);
72  st->Execute();
73  int64_t p_id = 0;
74  if (st->Fetch())
75    st->Get(1, &p_id);
76  else
77    debug("no parent for %lld slice !", slice_id);
78  tr->Commit();
79  return p_id;
82 string sfinx_app::slice_name(sfinx_id_t slice_id)
84  string name;
85  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
86    IBPP::ilConcurrency, IBPP::lrWait);
87  tr->Start();
88  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
89  st->Prepare("select name from slices where id = ?");
90  st->Set(1, (int64_t)slice_id);
91  st->Execute();
92  while (st->Fetch()) {
93    st->Get(1, name);
94  }
95  tr->Commit();
96  return name;
99 string sfinx_app::slice_directory(sfinx_id_t slice_id)
101  string t;
102  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
103    IBPP::ilConcurrency, IBPP::lrWait);
104  tr->Start();
105  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
106  st->Prepare("select directory from slices where id = ?");
107  st->Set(1, (int64_t)slice_id);
108  st->Execute();
109  while (st->Fetch()) {
110    st->Get(1, t);
112  tr->Commit();
113  return t;
116 bool sfinx_app::parent_object(sfinx_object_t &src, sfinx_object_t *dst)
118  debug("par_obj");
119  switch (src.type) {
120    case SFINX_SLICE_OBJECT:
121      *dst = src;
122      dst->id = parent_slice_id(src.id);
123      return true;
124    default:
125      break;
127   return false;
130 // for objects other than slices if the main_obj_id == SFINX_SLICE_OBJECT
131 // directory is the slice one
132 // for other main_obj_id we look up in the hierarchy - all is created from the
133 // some slice
134 // TODO: think about editing object property (main_obj_xxx) !
136 bool sfinx_app::set_sorted_path(sfinx_object_t &obj)
138  string path;
139  sfinx->files_module_conf.get(FILES_MODULE_SORTED_TREE_PATH, obj.path_name);
140  sfinx_object_t t = obj;
141  while (1) {
142    if (t.type == SFINX_SLICE_OBJECT) {
143      path.insert(0, "/" + slice_directory(t.id)); // TODO: handle spaces in names
144    if (t.id == 1) // root slice
145      break;
146   }
147    if (!parent_object(obj, &t))
148      return false;
149    obj = t;
151  obj.path_name += path;
152  return true;
155 // returns true on error
156 bool sfinx_app::sorted_path_mkdir(sfinx_object_t &obj)
158  if (set_sorted_path(obj))
159    return true;
160  return system(("mkdir -p " + obj.path_name).c_str());
163 int main(int argc, char **argv)
165  setlocale(LC_ALL, "");
166  char version[16];
167  sprintf(version, "v%0d.%0d.%0d", SFINX_VERSION_MAJOR, SFINX_VERSION_MINOR, SFINX_VERSION_PLEVEL);
168  sfinx = new sfinx_app(argc, argv, "sfinx", version,
169    "Harbour <Harbour@Sfinx.Od.UA>", "GPL");
170  try {
171    sfinx->dbopen();
172    sfinx->start_ui(); // start ui first
173    sfinx->listen();
175  catch(IBPP::Exception& e) {
176    log("IBPP::Exception", "%s", e.what());
177      if (sfinx->ui())
178        sfinx->ui()->alert("%s() Error !", e.Origin());
179  } 
180  return 0;
183 bool faraon_session::connect()
185  // send plain packet with daemon version
186  tx_elements.clear();
187  tx_elements.add(daemon_version);
188  // and available crypt types
189  tx_elements.add(packet_crypt_types);
190  // auth level
191  tx_elements.add(min_auth_levels);
192  // ÐÅÒÅÄÅÌÁÔØ Ó ÉÓÐÏÌØÚÏ×ÁÎÉÅÍ -lgcrypt
193  sfinx_8bit_vector_t md5_challenge(SFINX_MD5_SUM);
194  sfinx_crypter::get_random_bytes(md5_challenge, gcry_md_get_algo_dlen(GCRY_MD_MD5));
195  tx_elements.add(md5_challenge);
196  send_packet();
197  if (read_packet()) {
198    log("sfinx:connect", "Error reading faraon request");
199    return true;
202  // got SFINX_AUTH_REQUEST + auth data
203  // validate user_name/pass or rsa key
204  // ...
206  // send SFINX_ACCESS_GRANTED/SFINX_ACCESS_DENIED
207  tx_elements.clear();
208  sfinx_8bit_t access(SFINX_ACCESS_GRANTED);
209  access.set(0); // ÐÒÉÞÉÎÁ ÄÏÓÔÕÐÁ/ÏÔËÁÚÁ
210  tx_elements.add(access);
211  send_packet();
212  return false;
215 void faraon_session::run()
217  setError(1);
218  setNoDelay(1);
219  try {
220    if (connect())
221      return;
222    while(1) {
223     if (isPending(pendingInput, 10)) { // faraon'Ù ÐÒÏÓÀÔØ ...
224       if (process_requests()) {
225         log("sfinx:run", "Bad faraon request");
226         break;
227      }
228   }
229    Thread::sleep(10);
230   }
232  catch (Socket *s) {
233     tpport_t port;
234     InetAddress saddr = (InetAddress)getPeer(&port);
235     log("sfinx:run","Faraon client error at %s:%d - %s", saddr.getHostname(),
236             port, getErrorString());
238  catch (IBPP::Exception& e) {
239    log("sfinx:run", "%s", e.what());
240    sfinx->ui()->alert("%s() Error !", e.Origin());
242   final();
245 void faraon_session::get_slice(sfinx_id_t slice_id, sfinx_tid_t tid)
247  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
248    IBPP::ilConcurrency, IBPP::lrWait);
249  tr->Start();
250  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
251  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 = ?");
252  st->Set(1, (int64_t)slice_id);
253  st->Execute();
254  string name, directory, description, parent_name;
255  int64_t id, parent_id;
256  sfinx_timestamp_t ctime, etime;
257  if (!st->Fetch())
258    return;
259  st->Get(1, &id);
260  st->Get(2, name);
261  st->Get(3, description);
262  st->Get(4, &parent_id);
263  if (!parent_id)
264    parent_name = "Dao";
265  else {
266    st->Get(5, parent_name);
268  st->Get(6, ctime);
269  st->Get(7, etime);
270  st->Get(8, directory);
271  sfinx_slice_t slice(id, name, directory, description, parent_name, parent_id, ctime, etime, tid);
272  tr->Commit();
273  send(slice);
276 void faraon_session::get_slices(sfinx_tid_t el_id, sfinx_id_t except)
278  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
279    IBPP::ilConcurrency, IBPP::lrWait);
280  tr->Start();
281  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
282  if (!except)
283    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 order by id");
284  else {
285    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 id <> ? order by id");
286    st->Set(1, int64_t(except));
288  st->Execute();
289  string name, description, parent_name, directory;
290  int64_t id, parent_id;
291  sfinx_timestamp_t ctime, etime;
292  sfinx_slice_vector_t slices(el_id);
293  while (st->Fetch()) {
294   st->Get(1, &id);
295   st->Get(2, name);
296   st->Get(3, description);
297   st->Get(4, &parent_id);
298   if (!parent_id)
299     parent_name = "Dao";
300   else {
301     st->Get(5, parent_name);
303   st->Get(6, ctime);
304   st->Get(7, etime);
305   st->Get(8, directory);
306   sfinx_slice_t slice(id, name, directory, description, parent_name, parent_id, ctime, etime);
307   slices.add(slice);
309   tr->Commit();
310   send(slices);
313 void faraon_session::fill_files(sfinx_slice_t *slice)
317 void faraon_session::fill_notes(sfinx_slice_t *slice)
319  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
320    IBPP::ilConcurrency, IBPP::lrWait);
321  tr->Start();
322  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
323  st->Prepare("select id, name, ctime, etime from notes where "
324    "main_obj_slice_id = ?");
325  st->Set(1, int64_t(slice->id));
326  st->Execute();
327  int64_t id;
328  sfinx_timestamp_t ctime, etime;
329  string name;
330  while (st->Fetch()) {
331    st->Get(1, &id);
332    st->Get(2, name);
333    st->Get(3, ctime);
334    st->Get(4, etime);
335    sfinx_object_t note(SFINX_NOTE_OBJECT, (sfinx_id_t)id, slice->id, name.c_str(), ctime, etime);
336    slice->add(note);
340 // ÐÅÒÅÄÁÅÔ ÄÅÒÅ×Ï ÓÌÁÊÓÏ× + ×ÌÏÖÅÎÎÙÅ ÏÂØÅËÔÙ, ÔÉРËÏÔÏÒÙÈ ÏÇÒÁÎÉÞÅΠÍÁÓËÏÊ
341 void faraon_session::get_objects(sfinx_tid_t reply_id, u32_t obj_mask)
343  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
344    IBPP::ilConcurrency, IBPP::lrWait);
345  tr->Start();
346  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
347  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 order by id");
348  st->Execute();
349  string name, description, parent_name, directory;
350  int64_t id, parent_id;
351  sfinx_timestamp_t ctime, etime;
352  sfinx_slice_vector_t slices(reply_id);
353  while (st->Fetch()) {
354   st->Get(1, &id);
355   st->Get(2, name);
356   st->Get(3, description);
357   st->Get(4, &parent_id);
358   if (!parent_id)
359     parent_name = "Dao";
360   else {
361     st->Get(5, parent_name);
363   st->Get(6, ctime);
364   st->Get(7, etime);
365   st->Get(8, directory);
366   sfinx_slice_t slice(id, name, directory, description, parent_name, parent_id, ctime, etime);
367   if (obj_mask & (1 << SFINX_FILE_OBJECT))
368     fill_files(&slice);
369   if (obj_mask & (1 << SFINX_NOTE_OBJECT))
370     fill_notes(&slice);
371   slices.add(slice);
373   tr->Commit();
374   send(slices);
377 bool move(string &from, string &to)
379  return system(("mv \"" + from + "\" \"" + to + "\"").c_str());
382 // TODO: make reply alert
383 void faraon_session::update_slice(sfinx_slice_t *slice)
385  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
386    IBPP::ilConcurrency, IBPP::lrWait);
387  tr->Start();
388  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
389  string old_dir = sfinx->slice_directory(slice->id);
390  if (old_dir != slice->directory()) {
391    string from, to;
392    sfinx_object_t o;
393    o.type = SFINX_SLICE_OBJECT;
394    o.id = slice->id;
395    sfinx->set_sorted_path(o);
396    from = o.path_name;
397    const char *p = strrchr(from.c_str(), '/');
398    if (!p)
399            bug();
400          char path[1024];
401          path[0] = 0;
402          strncat(path, from.c_str(), p - from.c_str());
403          to = path;
404          to += "/";
405          to += slice->directory();
406    move(from, to);
408   st->Prepare("update slices set etime = NULL, name = ?, description = ?, directory = ? where id = ?");
409   st->Set(1, slice->name());
410   st->Set(2, slice->description());
411   st->Set(3, slice->directory());
412   st->Set(4, (int64_t)slice->id);
413   st->Execute();
414   tr->Commit();
417 void faraon_session::new_slice(sfinx_slice_t *slice)
419  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
420    IBPP::ilConcurrency, IBPP::lrWait);
421  tr->Start();
422  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
423  st->Prepare("insert into slices (parent_id, name, description, directory) values  (?, ?, ?, ?)");
424  st->Set(1, (int64_t)slice->parent_id);
425  st->Set(2, slice->name());
426  st->Set(3, slice->description());
427  st->Set(4, slice->directory());
428  st->Execute();
429  tr->Commit();
432 void faraon_session::delete_slice_recursivly(sfinx_id_t slice_id)
434  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
435    IBPP::ilConcurrency, IBPP::lrWait);
436  tr->Start();
437  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
438  st->Prepare("select id from slices where parent_id = ?");
439  st->Set(1, (int64_t)slice_id);
440  st->Execute();
441  int32_t id;
442  while (st->Fetch()) {
443    st->Get(1, &id);
444    delete_slice_recursivly(id);
446  st->Prepare("delete from slices where id = ?");
447  st->Set(1, (int64_t)slice_id);
448  st->Execute();
449  tr->Commit(); // may be we need commit only at the end of the whole recursive deletion ?
452 void faraon_session::delete_slice_with_reattach(sfinx_id_t slice_id)
454  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
455    IBPP::ilConcurrency, IBPP::lrWait);
456  tr->Start();
457  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
458  st->Prepare("update slices set parent_id = (select parent_id from slices where id = ?) where parent_id = ?");
459  st->Set(1, (int64_t)slice_id);
460  st->Set(2, (int64_t)slice_id);
461  st->Execute();
462  st->Prepare("delete from slices where id = ?");
463  st->Set(1, (int64_t)slice_id);
464  st->Execute();
465  tr->Commit();
468 void faraon_session::delete_slice_assoc_data(sfinx_id_t slice_id, bool recursivly)
470  mark_files_unsorted(slice_id, recursivly, true);
471  // delete_notes();
472  // ...
475 void faraon_session::delete_slice_mark_data_unsorted(sfinx_id_t slice_id, bool recursivly)
477  mark_files_unsorted(slice_id, recursivly);
478  // mark_notes_unsorted();
479  // ...
482 void faraon_session::mark_files_unsorted(sfinx_id_t slice_id, bool recursivly, bool remove)
484  // delete from file_tags
485  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
486    IBPP::ilConcurrency, IBPP::lrWait);
487  tr->Start();
488  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
489  st->Prepare("delete from file_tags where obj_type = 1 and obj_id = ?");
490  st->Set(1, (int64_t)slice_id);
491  st->Execute();
492  // move to unsorted location
493  st->Prepare("select name from files where main_obj_type = 1 and main_obj_id = ?");
494  st->Set(1, (int64_t)slice_id);
495  st->Execute();
496  string udir, sdir;
497  sfinx_object_t o(SFINX_SLICE_OBJECT, slice_id, slice_id);
498  sfinx->set_sorted_path(o);
499  sdir = o.path_name + "/";
500  sfinx->files_module_conf.get(FILES_MODULE_UNSORTED_PATH, udir);
501  while(st->Fetch()) {
502    string name, from;
503    st->Get(1, name);
504    from = sdir + name;
505    if (remove)
506      unlink(from.c_str());
507    else
508      move(from, udir);
510  // delete from files
511  st->Prepare("delete from files where main_obj_id = 1 and main_obj_id = ?");
512  st->Set(1, (int64_t)slice_id);
513  st->Execute();
514  gen_desc_file(SFINX_SLICE_OBJECT, slice_id, slice_id);
515  if (recursivly) {
516    u32_t pid = sfinx->parent_slice_id(slice_id);
517    if (pid)
518      mark_files_unsorted(pid, true, remove);
520  tr->Commit(); 
523 // ÕÓÔÁÎÏ×ÌÅΠfile_id = main_slice_id É name
524 // ÎÕÖÎÏ ÎÁÊÔÉ ÆÁÊÌ Õ ËÏÔÏÒÏÇÏ ÉÌÉ parent ÉÌÉ ÒÏÄÎÏÊ ÓÌÁÊÓ ÔÁËÏÊ-ÖÅ
525 void faraon_session::mark_file_unsorted(sfinx_file_t *f, bool remove)
527  // delete from file_tags
528  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
529    IBPP::ilConcurrency, IBPP::lrWait);
530  tr->Start();
531  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
532  f->main_obj_id = f->file_id;
533  f->main_obj_type = SFINX_SLICE_OBJECT;
534  // get file_id
535  st->Prepare("select id from files where main_obj_type = ? and main_obj_id = ? and main_slice_id = ? and name = ?");
536  st->Set(1, (int32_t)f->main_obj_type);
537  st->Set(2, (int64_t)f->main_obj_id);
538  st->Set(3, (int64_t)f->main_slice_id);
539  st->Set(4, f->name);
540  int64_t file_id;
541  st->Execute();
542  if (!st->Fetch()) { // try to find parent id
543    bug();
544    return;
545  } else
546    st->Get(1, file_id);
547  st->Prepare("delete from file_tags where file_id = ?");
548  st->Set(1, file_id);
549  st->Execute();
550  // move to unsorted location
551  string udir, sdir;
552  sfinx_object_t o(f->main_obj_type, f->main_obj_id, f->main_slice_id);
553  sfinx->set_sorted_path(o);
554  sdir = o.path_name + "/";
555  sfinx->files_module_conf.get(FILES_MODULE_UNSORTED_PATH, udir);
556  string from = sdir + f->name;
557  if (remove)
558    unlink(from.c_str());
559  else
560    move(from, udir);
561  // delete from files
562  st->Prepare("delete from files where id = ?");
563  st->Set(1, file_id);
564  st->Execute();
565  tr->Commit();
566  gen_desc_file(f->main_obj_type, f->main_obj_id, f->main_slice_id);
569 void faraon_session::update_files_module_conf(sfinx_pair_vector_t *conf)
571  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
572    IBPP::ilConcurrency, IBPP::lrWait);
573  tr->Start();
574  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
575  st->Prepare("update files_module_conf set unsorted_files_path = ?, sorted_file_tree = ?, "
576    "desc_file_name = ?, desc_file_enable = ?");
577  string t;
578  conf->get(FILES_MODULE_UNSORTED_PATH, t);
579  st->Set(1, t);
580  conf->get(FILES_MODULE_SORTED_TREE_PATH, t);
581  st->Set(2, t);
582  conf->get(FILES_MODULE_DESC_FILE_NAME, t);
583  st->Set(3, t);
584  u32_t gen_desc_files;
585  conf->get(FILES_MODULE_DESC_FILE_ENABLE, &gen_desc_files);
586  st->Set(4, (int32_t)gen_desc_files);
587  st->Execute();
588  tr->Commit();
589  module_conf_request(SFINX_FILES_MODULE_CONF_REQUEST);
592 void sfinx_app::load_module_conf(u32_t id)
594  IBPP::Transaction tr = driver_->TransactionFactory(db_, IBPP::amRead,
595    IBPP::ilConcurrency, IBPP::lrWait);
596  tr->Start();
597  IBPP::Statement st = driver_->StatementFactory(db_, tr);
598  switch (id) {
599    case SFINX_FILES_MODULE_CONF_REQUEST:
600      st->Prepare("select unsorted_files_path, sorted_file_tree, desc_file_name, desc_file_enable from files_module_conf");
601      st->Execute();
602      files_module_conf.clear();
603      files_module_conf.tid(SFINX_FILES_MODULE_CONF);
604      while (st->Fetch()) {
605        string val;
606        st->Get(1, val);
607        files_module_conf.add(FILES_MODULE_UNSORTED_PATH, val);
608        st->Get(2, val);
609        files_module_conf.add(FILES_MODULE_SORTED_TREE_PATH, val);
610        st->Get(3, val);
611        files_module_conf.add(FILES_MODULE_DESC_FILE_NAME, val);
612        int32_t enable;
613        st->Get(4, &enable);
614        files_module_conf.add(FILES_MODULE_DESC_FILE_ENABLE, enable);
615     }
616      break;
617    default:
618      log("sfinx:load_module_conf", "Unknown module id - 0x%x", id);
619      break;
621  tr->Commit();
624 void faraon_session::module_conf_request(u32_t id)
626  switch (id) {
627    case SFINX_FILES_MODULE_CONF_REQUEST:
628      sfinx->load_module_conf(id);
629      send(sfinx->files_module_conf);
630      break;
631    default:
632      log("sfinx:module_conf_request", "Unknown module id - 0x%x", id);
633      break;
637 void faraon_session::relink_slice(sfinx_slice_t *slice)
639  // move directories
640  string from, to;
641  sfinx_object_t o_from(SFINX_SLICE_OBJECT, slice->id, slice->id);
642  sfinx->set_sorted_path(o_from);
643  from = o_from.path_name;
644  sfinx_object_t o_to(SFINX_SLICE_OBJECT, slice->parent_id, slice->parent_id);
645  sfinx->set_sorted_path(o_to);
646  to = o_to.path_name;
647  sfinx->sorted_path_mkdir(SFINX_SLICE_OBJECT, slice->parent_id, slice->parent_id);
648  move(from, to);
649 // relink
650  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite,
651    IBPP::ilConcurrency, IBPP::lrWait);
652  tr->Start();
653  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
654  st->Prepare("update slices set parent_id = ? where id = ?");
655  st->Set(1, (int64_t)slice->parent_id);
656  st->Set(2, (int64_t)slice->id);
657  st->Execute();
658  tr->Commit();
661 #include <dirent.h>
662 #include <errno.h>
663 #include <magic.h>
665 // × file_id ÈÒÁÎÉÔÓÑ id ÔÅËÕÝÅÊ ÄÉÒÅËÔÏÒÉÉ-ÓÌÁÊÓÁ × ËÏÔÏÒÏÊ ÎÁÈÏÄÉÍÓÑ/×ÙÂÒÁÌÉ
666 // × main_slice_id - parent_id ÄÉÒÅËÔÏÒÉÉ
667 // name - full dir path
668 // orig_name - dir entry
669 void faraon_session::send_dir(bool sorted, sfinx_file_t *f)
671  string dir;
672  sfinx->files_module_conf.get(sorted ? FILES_MODULE_SORTED_TREE_PATH : FILES_MODULE_UNSORTED_PATH, dir);
673  sfinx_files_vector_t files(sorted ? SFINX_FILES_MODULE_SORTED_TREE : SFINX_FILES_MODULE_UNSORTED_TREE);
674  if (f->name.size())
675    dir += f->name;
676  bool mime_detect = true;
677  // TODO: change mime_detect
678  //
679  //      0 - no detect
680  //      1 - deferable detect - send list firts, ÚÁÔÅÍ ÄÏÓÙÌÁÅÍ mimes ÞÁÓÔÑÍÉ
681  //      2 - full detect
683  struct magic_set *ms;
684  if (mime_detect) {
685    ms = magic_open(MAGIC_MIME | MAGIC_PRESERVE_ATIME | MAGIC_COMPRESS);
686    if (!ms)
687      mime_detect = false;
688    else {
689      if (magic_load(ms, NULL) == -1)
690        mime_detect = false;
691    }
693  struct dirent **namelist;
694  int n = scandir(dir.c_str(), &namelist, 0, alphasort);
695  if (n < 0) {
696    debug("%s scandir error: %s !", dir.c_str(), strerror(errno));
697    return;
699   sfinx_file_t file;
700   sfinx_progress_t prg("Processing files metadata ...");
701   prg.max(n);
702   send(prg);
703   u32_t p_id = 0;
704   if (sorted)
705     p_id = sfinx->parent_slice_id(f->file_id);
706   for (int i = 0; i < n; i++) {
707    if (prg.set(i, .5)) // ÛÁÇ 0.5%
708      send(prg);
709    file.clear();
710    if (!strcmp(namelist[i]->d_name, ".") || !strcmp(namelist[i]->d_name, ".."))
711      continue;
712    file.name = namelist[i]->d_name;
713    struct stat64 inode;
714    string full_path = dir + '/' + file.name;
715    if (stat64(full_path.c_str(), &inode))
716      debug("%s stat error: %s", full_path.c_str(), strerror(errno));
717    else
718      file.fsize = inode.st_size;
719    if (inode.st_mode & S_IFDIR)
720      file.is_directory = true;
721    file.etime.set(inode.st_ctime); // status changes
722    file.ctime.set(inode.st_mtime); // last modification
723    if (sorted) {
724      // set parent_id for up traverse
725      file.compressed_fsize = p_id;
726      if (file.is_directory) { // set dir id & dir parent_id from database
727       IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
728         IBPP::ilConcurrency, IBPP::lrWait);
729       tr->Start();
730       IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
731       st->Prepare("select id from slices where directory = ? and parent_id = ?");
732       st->Set(1, file.name);
733       st->Set(2, (int64_t)f->file_id);
734       st->Execute();
735       if (!st->Fetch())
736         debug("*** no data for name %s and pid %d", file.name.c_str(), f->file_id);
737       else {
738         int64_t id;
739         st->Get(1, &id);
740         file.file_id = id;
741         file.main_obj_id = f->file_id;
742         file.main_obj_type = SFINX_SLICE_OBJECT;
743         // debug("for name %s id %d, pid %d", file.name.c_str(), id, f->file_id);
744      }
745       tr->Commit();
746      } else { // file - ÄÏÓÔÁÔÏÞÎÏ ÕÓÔÁÎÏ×ÉÔØ dir id, ÞÔÏ ÂÕÄÅÔ main_slice_id ÄÌÑ ÄÁÎÎÏÇÏ ÆÁÊÌÁ
747        file.file_id = f->file_id;
748        file.main_obj_type = file.main_obj_id = 0;
749     }
750    } else { // not sorted
751      file.file_id = 0;
752      file.compressed_fsize = file.main_obj_type = file.main_obj_id = 0;
753   }
754    if (mime_detect) {
755      const char *mimetype = magic_file(ms, full_path.c_str());
756      if (mimetype)
757        file.mimetype = mimetype;
758   } else {
759     if (file.is_directory)
760       file.mimetype = "inode/directory"; // "application/x-not-regular-file";
761     else
762       file.mimetype = "application/octet-stream";
763   }
764    free(namelist[i]);
765    files.add(file);
767   prg.end();
768   send(prg);
769   free(namelist);
770   send(files);
773 // may be use 7z.so ?
774 bool compress(string &infile, string *newname)
776  int res = system(("/usr/local/bin/sfinx_compress.sh " + infile).c_str());
777  if (res)
778    return true;
779  else
780    unlink(infile.c_str());
781  *newname = infile + ".7z";
782  return false;
785 // × ÄÉÒÅËÔÏÒÉÉ main_slice_id ÄÌÑ ×ÓÅÈ ÆÁÊÌÏ× ÓÏÚÄÁÅÍ description.txt ×ÉÄÁ:
787 //  slice_name - slice_decription
789 //  -----------------------------
791 // file1
793 // size1 - XXX
794 // csum1 - XXX
795 // compressed size1 - XXX
796 // compressed csum1 - XXX
797 // ctime1 - YYYY
798 // etime1 - YYYY
800 //  title1
802 //  authority1
804 //  description1
806 //  comments1
808 // -------------------------------
810 // file2 ...
812 bool faraon_session::gen_desc_file(sfinx_type_t obj_type, sfinx_id_t obj_id, sfinx_id_t slice_id)
814  string dir, fname;
815  // u32_t slice_id = sfinx->get_object_slice(obj_type, obj_id);
816  sfinx_object_t o(SFINX_SLICE_OBJECT, slice_id, slice_id);
817  sfinx->set_sorted_path(o);
818  dir = o.path_name;
819  sfinx->files_module_conf.get(FILES_MODULE_DESC_FILE_NAME, fname);
820  string desc_fname = dir + "/" + fname;
821  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
822    IBPP::ilConcurrency, IBPP::lrWait);
823  tr->Start();
824  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
825  st->Prepare("select name, description, ctime, etime from slices where id = ?");
826  st->Set(1, (int64_t)slice_id);
827  st->Execute();
828  if (!st->Fetch()) { // hmm, no such slice ?
829    unlink(desc_fname.c_str());
830    return false;
831  } else {
832    ofstream f(desc_fname.c_str(), ios::out | ios::binary | ios::trunc);
833    if (!f)
834      return true;
835    string t;
836    st->Get(1, t); // name
837    f << endl;
838    f << t << " - ";
839    st->Get(2, t); // description
840    f << t << endl << endl;
841    // ctime/etime
842    IBPP::Timestamp xtime;
843    st->Get(3, xtime);
844          int year, month, day, hour, min, sec;
845          xtime.GetDate(year, month, day);
846          xtime.GetTime(hour, min, sec);
847          char buf[64];
848          sprintf(buf, "Slice created: %02d/%02d/%04d %02d:%02d:%02d", day, month, year, hour, min, sec);
849          f << buf << endl;
850          st->Get(4, xtime);
851          xtime.GetDate(year, month, day);
852          xtime.GetTime(hour, min, sec);
853          sprintf(buf, "Slice modified: %02d/%02d/%04d %02d:%02d:%02d", day, month, year, hour, min, sec);
854          f << buf << endl;       
855          f.close();
857  // store_compressed
858  // mimetype
859  st->Prepare("select id, name, title, authority, description, comments, ctime, etime, main_slice_id, "
860    "fsize, sha256, fsize_compressed, sha256_compressed, csum_last_checked, csum_valid, "
861    "store_in_sorted_location from files where main_obj_type = 1 and main_obj_id = ?");
862  st->Set(1, (int64_t)slice_id);
863  st->Execute();
864  while (st->Fetch()) {
865    ofstream f(desc_fname.c_str(), ios::out | ios::binary | ios::app);
866    if (!f)
867      return true;
868    int64_t fid;
869    st->Get(1, &fid);
870    string t;
871    f << endl << "-------------------------------------------------------------------" << endl << endl;
872    st->Get(2, t); // name
873    f << "Name: " << t << endl;
874    st->Get(3, t); // title
875    f << "Title: " << t << endl;   
876    st->Get(4, t); // authority
877    f << "Authority: " << t << endl;
878    st->Get(5, t); // description
879    f << "Description: " << t << endl;
880    st->Get(6, t); // comments
881    f << "Comments: " << t << endl;
882    IBPP::Timestamp xtime;
883    int year, month, day, hour, min, sec;
884    char buf[64];
885    st->Get(7, xtime);
886          xtime.GetDate(year, month, day);
887          xtime.GetTime(hour, min, sec);
888          sprintf(buf, "Entry created: %02d/%02d/%04d %02d:%02d:%02d", day, month, year, hour, min, sec);
889          f << buf << endl;
890    st->Get(8, xtime);
891          xtime.GetDate(year, month, day);
892          xtime.GetTime(hour, min, sec);
893          sprintf(buf, "Entry modifed: %02d/%02d/%04d %02d:%02d:%02d", day, month, year, hour, min, sec);
894          f << buf << endl;
895    int64_t fsize, compressed_fsize;
896    int64_t main_slice_id;
897    st->Get(9, main_slice_id);
898    st->Get(10, fsize);
899    f << "Size: " << fsize << endl;
900    st->Get(11, t); // csum
901    f << "Csum: " << t << endl;
902    st->Get(12, compressed_fsize);
903    f << "Compressed size: " << compressed_fsize << endl;
904    st->Get(13, t); // compressed_csum
905    f << "Compressed csum: " << t << endl;
906    // additional slices
907    IBPP::Statement st1 = sfinx->driver_->StatementFactory(sfinx->db_, tr);
908    st1->Prepare("select s.name, s.description from slices s, file_tags fs where fs.file_id = ? and fs.obj_id = s.id and fs.obj_type = 1");
909    st1->Set(1, (int64_t)fid);
910    st1->Execute();
911    if (st1->Fetch()) {
912      f << "Additional Slices: ";
913      bool comma = false;
914      while (st1->Fetch()) {
915        if (comma)
916          f << ", ";
917        st1->Get(1, t); // name
918        f << t << " [ ";
919        st1->Get(2, t); // description
920        f << t << " ]";
921        comma = true;
922      }
923        f << endl;
924    }
925    f.close();
927   tr->Commit();
928   return false;
931 // send file by name & main_obj
932 void faraon_session::send_file(sfinx_file_t *f)
934  //debug("name - %s, fid - %d, msid - %d", f->name.c_str(), f->file_id, f->main_slice_id);
935  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
936    IBPP::ilConcurrency, IBPP::lrWait);
937  tr->Start();
938  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
939  // store_compressed
940  // mimetype
941  // main_slice_id ?
942  st->Prepare("select id, name, title, authority, description, comments, ctime, etime, "
943    "fsize, sha256, fsize_compressed, sha256_compressed, csum_last_checked, csum_valid, "
944    "store_in_sorted_location from files where main_obj_type = 1 and main_obj_id = ? and name = ?");
945  st->Set(1, (int64_t)f->file_id);
946  st->Set(2, f->name);
947  st->Execute();
948  int64_t fid;
949  sfinx_file_t file(f->tid());
950  if (!st->Fetch()) {
951    sfinx_string_t alert(SFINX_ALERT);
952    alert.set("No such file in database !");
953    send(alert);
954    return;
955  } else {
956    st->Get(1, &fid);
957    file.file_id = fid;
958    st->Get(2, file.name);
959    st->Get(3, file.title);
960    st->Get(4, file.authority);
961    st->Get(5, file.description);
962    st->Get(6, file.comments);
963    st->Get(7, file.ctime);
964    st->Get(8, file.etime);
965    int64_t fsize, compressed_fsize;
966    st->Get(9, fsize);
967    st->Get(10, file.csum);
968    st->Get(11, compressed_fsize);
969    file.main_obj_id = f->file_id;
970    file.main_obj_type = SFINX_SLICE_OBJECT;
971    file.fsize = fsize;
972    file.compressed_fsize = compressed_fsize;
973    st->Get(12, file.compressed_csum);
974    int32_t sorted_location;
975    st->Get(15, &sorted_location);
976    file.sorted_location = sorted_location;
977    file.mimetype = "Not Set";
979  // fill file slices
980  st->Prepare("select obj_id, obj_type from file_tags where file_id = ?");
981  st->Set(1, fid);
982  st->Execute();
983  while (st->Fetch()) {
984    int64_t obj_id;
985    int32_t obj_type;
986    st->Get(1, &obj_id);
987    st->Get(2, &obj_type);
988    sfinx_object_t o(obj_id, obj_type, f->main_slice_id);
989    file.objects.push_back(o);
991  tr->Commit();
992  send(file);
995 void faraon_session::files_module_classify(sfinx_file_t *f)
997  IBPP::Transaction tr;
998  IBPP::Statement st;
999  sfinx_string_t reply(SFINX_FILES_MODULE_CLASSIFY_REPLY);
1000  string compressed_name, sorted_location, dir, fname;
1001  sfinx_hash_t csum(GCRY_MD_SHA256), compressed_csum(GCRY_MD_SHA256);
1002  sfinx->files_module_conf.get(FILES_MODULE_UNSORTED_PATH, dir);
1003  fname = dir + "/" + f->name;
1004  // rename file
1005  if (f->name != f->orig_name) {
1006    if (rename((dir + "/" + f->orig_name).c_str(), (dir + "/" + f->name).c_str())) {
1007      reply.set("Error renaming file !");
1008      goto out;
1009    }
1011  // checksum file
1012  reply.set("Error calculating checksum for file !");
1013  if (f->generate_csum && csum.hash(fname))
1014    goto out;
1015  f->csum = csum.strvalue();
1016  if (f->sorted_location) {
1017    sfinx_object_t o(f->main_obj_type, f->main_obj_id, f->main_slice_id);
1018    reply.set("Error creating Sorted Location !");
1019    if (!sfinx->set_sorted_path(o))
1020      goto out;
1021    sorted_location = o.path_name;
1022    if (sfinx->sorted_path_mkdir(f->main_obj_type, f->main_obj_id, f->main_slice_id))
1023        goto out;
1024    reply.set("Error moving file to Sorted Location !");
1025    if (move(fname, sorted_location))
1026      goto out;
1028  fname = sorted_location + "/" + f->name;
1029  // get size
1030  struct stat64 inode;
1031  reply.set("Error getting file size !");
1032  if (stat64(fname.c_str(), &inode))
1033    goto out;
1034  else
1035    f->fsize = inode.st_size;
1036  // compress file
1037  if (f->store_compressed) {
1038    // check if file already compressed
1039    bool compressed = false;
1040    if (f->name.size() > 3) {
1041      string ext(f->name, f->name.size() - 3);
1042      if (ext == ".7z")
1043        compressed = true;
1044   }
1045    reply.set("Error compressing file !");
1046    if (!compressed) {
1047      if (compress(fname, &compressed_name))
1048        goto out;
1049      else
1050        f->name += ".7z";
1051    } else
1052        compressed_name = fname;
1053    reply.set("Error calculating checksum for compressed file !");
1054    if (f->generate_csum && compressed_csum.hash(compressed_name))
1055      goto out;
1056    f->compressed_csum = compressed_csum.strvalue();
1057    reply.set("Error getting compressed file size !");
1058    if (stat64(compressed_name.c_str(), &inode))
1059      goto out;
1060    else
1061      f->compressed_fsize = inode.st_size;
1063  // add to files
1064  tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite, IBPP::ilConcurrency, IBPP::lrWait);
1065  tr->Start();
1066  st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1067  st->Prepare("insert into files (name, title, authority, description, comments, main_obj_id, main_obj_type, fsize, "
1068    "sha256, fsize_compressed, sha256_compressed, store_in_sorted_location) values  (?, ?, ?, ?, ?, ?, ?, "
1069    "?, ?, ?, ?, ?)");
1070  st->Set(1, f->name);
1071  st->Set(2, f->title);
1072  st->Set(3, f->authority);
1073  st->Set(4, f->description);
1074  st->Set(5, f->comments);
1075  st->Set(6, (int64_t)f->main_obj_id);
1076  st->Set(7, (int32_t)f->main_obj_type);
1077  st->Set(8, (int64_t)f->fsize);
1078  st->Set(9, f->csum);
1079  st->Set(10, (int64_t)f->compressed_fsize);
1080  st->Set(11, f->compressed_csum);
1081  st->Set(12, f->sorted_location);
1082  st->Execute();
1084  st->Prepare("select id from files where name = ? and main_obj_type = ? and main_obj_id = ?");
1085  st->Set(1, f->name);
1086  st->Set(2, (int32_t)f->main_obj_type);
1087  st->Set(3, (int64_t)f->main_obj_id);
1088  st->Execute();
1089  int64_t file_id;
1090  if (!st->Fetch())
1091    bug();
1092  else {
1093    st->Get(1, &file_id);
1094 //   debug("added file has id - %d", file_id);
1096  // add to file_tags
1097  for (u32_t i = 0; i < f->objects.size(); i++) {
1098    st->Prepare("insert into file_tags (file_id, obj_id. obj_type) values (?, ?, ?)");
1099    st->Set(1, file_id);
1100    sfinx_object_t o = f->objects[i];
1101    st->Set(2, (int64_t)o.id);
1102    st->Set(3, (int32_t)o.type);
1103    st->Execute();
1105  tr->Commit();
1106  u32_t gen_desc_files;
1107  sfinx->files_module_conf.get(FILES_MODULE_DESC_FILE_ENABLE, &gen_desc_files);
1108  if (gen_desc_files) { // generate decription file
1109    reply.set("Error generating description file !");
1110    if (gen_desc_file(f->main_obj_type, f->main_obj_id, f->main_slice_id))
1111      goto out;
1113   reply.set(""); // No error
1114 out:
1115  send(reply);
1118 void faraon_session::notes_module_add(sfinx_note_t *n)
1120  IBPP::Transaction tr;
1121  IBPP::Statement st;
1122  sfinx_string_t reply(SFINX_NOTES_MODULE_ADD_REPLY);
1123  // add to files
1124  tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite, IBPP::ilConcurrency, IBPP::lrWait);
1125  tr->Start();
1126  st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1127  st->Prepare("insert into notes (name, text, url, main_obj_id, main_obj_type, main_obj_slice_id) values (?, ?, ?, ?, ?, ?)");
1128  st->Set(1, n->name);
1129  st->Set(2, n->text);
1130  st->Set(3, n->url);
1131  st->Set(4, (int64_t)n->main_obj_id);
1132  st->Set(5, (int32_t)n->main_obj_type);
1133  st->Set(6, (int64_t)n->main_slice_id);
1134  st->Execute();
1136 /* st->Prepare("select id from notes where name = ? and main_obj_type = ? and main_obj_id = ?");
1137  st->Set(1, n->name);
1138  st->Set(2, (int32_t)f->main_obj_type);
1139  st->Set(3, (int32_t)f->main_obj_id);
1140  st->Execute();
1141  int64_t note_id;
1142  if (!st->Fetch())
1143    bug();
1144  else {
1145    st->Get(1, &note_id);
1146 //   debug("added file has id - %d", file_id);
1148  // add note_tags
1149  for (u32_t i = 0; i < f->objects.size(); i++) {
1150    st->Prepare("insert into file_tags (file_id, obj_id. obj_type) values (?, ?, ?)");
1151    st->Set(1, file_id);
1152    sfinx_object_t o = f->objects[i];
1153    st->Set(2, (int64_t)o.oid);
1154    st->Set(3, (int64_t)o.otype);
1155    st->Execute();
1156  }*/
1157  tr->Commit();
1158  reply.set(""); // No error
1159  send(reply);
1162 bool faraon_session::get_file_by_id(sfinx_file_t *f)
1164  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
1165    IBPP::ilConcurrency, IBPP::lrWait);
1166  tr->Start();
1167  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1168  // store_compressed
1169  // mimetype
1170  st->Prepare("select name, title, authority, description, comments, ctime, etime, main_obj_id, "
1171    "main_obj_type, fsize, sha256, fsize_compressed, sha256_compressed, csum_last_checked, csum_valid, "
1172    "store_in_sorted_location, main_slice_id from files where id = ?");
1173  st->Set(1, (int64_t)f->file_id);
1174  st->Execute();
1175  if (!st->Fetch())
1176    return false;
1177  else {
1178    st->Get(1, f->name);
1179    st->Get(2, f->title);
1180    st->Get(3, f->authority);
1181    st->Get(4, f->description);
1182    st->Get(5, f->comments);
1183    st->Get(6, f->ctime);
1184    st->Get(7, f->etime);
1185    int64_t fsize, compressed_fsize, main_obj_id, main_slice_id;
1186    int32_t main_obj_type;
1187    st->Get(8, main_obj_id);
1188    st->Get(9, main_obj_type);
1189    st->Get(10, fsize);
1190    st->Get(11, f->csum);
1191    st->Get(12, compressed_fsize);
1192    f->main_obj_id = main_obj_id;
1193    f->main_obj_type = main_obj_type;
1194    f->fsize = fsize;
1195    f->compressed_fsize = compressed_fsize;
1196    st->Get(13, f->compressed_csum);
1197    int32_t sorted_location;
1198    st->Get(16, &sorted_location);
1199    f->sorted_location = sorted_location;
1200    st->Get(17, &main_slice_id);
1201    f->main_slice_id = main_slice_id;
1202    // st->Get(xxx, f->mimetype);
1204  // fill file tags
1205  f->objects.clear();
1206  st->Prepare("select obj_id, obj_type from file_tags where file_id = ?");
1207  st->Set(1, (int64_t)f->file_id);
1208  st->Execute();
1209  while (st->Fetch()) {
1210    int32_t object_type;
1211    int64_t object_id;
1212    st->Get(1, &object_id);
1213    st->Get(2, &object_type);
1214    sfinx_object_t o(object_type, object_id, f->main_slice_id);
1215    f->objects.push_back(o);
1217  tr->Commit();
1218  return true;
1221 void faraon_session::edit_file(sfinx_file_t *f)
1223  sfinx_file_t old_file;
1224  old_file.file_id = f->file_id;
1225  if (!get_file_by_id(&old_file))
1226    bug();
1227  IBPP::Transaction tr;
1228  IBPP::Statement st;
1229  sfinx_string_t reply(SFINX_FILES_MODULE_EDIT_REPLY);
1230  string compressed_name, sorted_location, dir, fname;
1231  if (f->sorted_location) {
1232    sfinx_object_t o(f->main_obj_type, f->main_obj_id, f->main_slice_id);
1233    sfinx->set_sorted_path(o);
1234    dir = o.path_name;
1235  } else
1236    sfinx->files_module_conf.get(FILES_MODULE_UNSORTED_PATH, dir);
1237  fname = dir + "/" + f->name;
1238  // rename file
1239  if (f->name != f->orig_name) {
1240    if (rename((dir + "/" + f->orig_name).c_str(), (dir + "/" + f->name).c_str())) {
1241      reply.set("Error renaming file !");
1242      goto out;
1243    }
1245  // add to files
1246  tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amWrite, IBPP::ilConcurrency, IBPP::lrWait);
1247  tr->Start();
1248  st = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1249  st->Prepare("update files set name = ?, title = ?, authority = ?, description = ?, comments = ?, "
1250    "main_obj_id = ?, main_obj_type = ?, fsize = ?, sha256 = ?, fsize_compressed = ?, sha256_compressed = ?, "
1251    "store_in_sorted_location = ? where id = ?");
1252  st->Set(1, f->name);
1253  st->Set(2, f->title);
1254  st->Set(3, f->authority);
1255  st->Set(4, f->description);
1256  st->Set(5, f->comments);
1257  st->Set(6, (int64_t)f->main_obj_id);
1258  st->Set(7, (int32_t)f->main_obj_type);
1259  st->Set(8, (int64_t)f->fsize);
1260  st->Set(9, f->csum);
1261  st->Set(10, (int64_t)f->compressed_fsize);
1262  st->Set(11, f->compressed_csum);
1263  st->Set(12, f->sorted_location);
1264  st->Set(13, (int64_t)f->file_id);
1265  st->Execute();
1267  // add to file_tags
1268  st->Prepare("delete from file_tags where file_id = ?");
1269  st->Set(1, (int64_t)f->file_id);
1270  st->Execute();
1271  for (u32_t i = 0; i < f->objects.size(); i++) {
1272    st->Prepare("insert into file_tags (file_id, obj_id, obj_type) values (?, ?, ?)");
1273    st->Set(1, (int64_t)f->file_id);
1274    sfinx_object_t o = f->objects[i];
1275    st->Set(2, (int64_t)o.id);
1276    st->Set(3, (int32_t)o.type);
1277    st->Execute();
1279  tr->Commit();
1280  u32_t gen_desc_files;
1281  sfinx->files_module_conf.get(FILES_MODULE_DESC_FILE_ENABLE, &gen_desc_files);
1282  if (gen_desc_files) { // generate decription file
1283    reply.set("Error generating description file !");
1284    if (gen_desc_file(f->main_obj_type, f->main_obj_id, f->main_slice_id))
1285      goto out;
1287   // move file
1288   if (old_file.sorted_location && f->sorted_location &&
1289     ((old_file.main_obj_id != f->main_obj_id) ||
1290     (old_file.main_obj_type != f->main_obj_type))) {
1291       sfinx_object_t o(old_file.main_obj_type, old_file.main_obj_id, old_file.main_slice_id);
1292       sfinx->set_sorted_path(o);
1293       string from = o.path_name + "/" + old_file.name;
1294       o.type = f->main_obj_type;
1295       o.id = f->main_obj_id;
1296       sfinx->set_sorted_path(o);
1297       string to = o.path_name + "/" + f->name;
1298       sfinx->sorted_path_mkdir(f->main_obj_type, f->main_obj_id, f->main_slice_id);
1299       move(from, to);
1300       // regen descs
1301       gen_desc_file(f->main_obj_type, f->main_obj_id, f->main_slice_id);
1302       gen_desc_file(old_file.main_obj_type, old_file.main_obj_id, old_file.main_slice_id);
1303   }
1304   reply.set(""); // No error
1305 out:
1306  send(reply);
1309 void faraon_session::search_in_files(string &pattern, sfinx_pair_vector_t *r)
1311  IBPP::Transaction tr = sfinx->driver_->TransactionFactory(sfinx->db_, IBPP::amRead,
1312    IBPP::ilConcurrency, IBPP::lrWait);
1313  tr->Start();
1314  IBPP::Statement st = sfinx->driver_->StatementFactory(sfinx->db_, tr),
1315    st1 = sfinx->driver_->StatementFactory(sfinx->db_, tr);
1316  st->Prepare("select id, name, title, authority, description, comments, ctime, etime, main_obj_id, "
1317    "main_obj_type, fsize, sha256, fsize_compressed, sha256_compressed, csum_last_checked, csum_valid, "
1318    "store_in_sorted_location, main_slice_id from files where name like ? or title like ? or authority like ? or "
1319    "description like ? or comments like ?");
1320  st->Set(1, pattern);
1321  st->Set(2, pattern);
1322  st->Set(3, pattern);
1323  st->Set(4, pattern);
1324  st->Set(5, pattern);
1325  st->Execute();
1326  int64_t rid = 0;
1327  while (st->Fetch()) {
1328    sfinx_file_t file;
1329    int64_t fid;
1330    st->Get(1, &fid);
1331    file.file_id = fid;
1332    st->Get(2, file.name);
1333    st->Get(3, file.title);
1334    st->Get(4, file.authority);
1335    st->Get(5, file.description);
1336    st->Get(6, file.comments);
1337    st->Get(7, file.ctime);
1338    st->Get(8, file.etime);
1339    int64_t fsize, compressed_fsize, main_obj_id, main_slice_id;
1340    int32_t main_obj_type;
1341    st->Get(9, main_obj_id);
1342    st->Get(10, main_obj_type);
1343    st->Get(11, fsize);
1344    st->Get(12, file.csum);
1345    st->Get(13, compressed_fsize);
1346    file.main_obj_id = main_obj_id;
1347    file.main_obj_type = main_obj_type;
1348    file.fsize = fsize;
1349    file.compressed_fsize = compressed_fsize;
1350    st->Get(14, file.compressed_csum);
1351    int32_t sorted_location;
1352    st->Get(17, &sorted_location);
1353    file.sorted_location = sorted_location;
1354    st->Get(18, &main_slice_id);
1355    file.main_slice_id = main_slice_id;
1356    file.mimetype = "Not Set";
1357    // fill file slices
1358    st1->Prepare("select obj_id, obj_type from file_tags where file_id = ?");
1359    st1->Set(1, fid);
1360    st1->Execute();
1361    while (st1->Fetch()) {
1362      int64_t obj_id;
1363      int32_t obj_type;
1364      st1->Get(1, &obj_id);
1365      st1->Get(2, &obj_type);
1366      sfinx_object_t o(obj_type, obj_id, file.main_slice_id);
1367      file.objects.push_back(o);
1368    }
1369    r->add(rid++, &file);
1371  tr->Commit();
1374 void faraon_session::search_query(sfinx_search_query_t *q)
1376  // debug("got pattern - %s", q->pattern.c_str());
1377  sfinx_pair_vector_t r(SFINX_ELEMENT_SEARCH_RESULT);
1378  // TODO: make threaded search, add sort rules
1379  string ptrn = '%' + q->pattern + '%';
1380  // search_in_slices(q->pattern, &r);
1381  search_in_files(ptrn, &r);
1382  // search_in_notes(q->pattern, &r);
1383  send(r);
1386 bool faraon_session::process_requests()
1388  if (read_packet()) {
1389    log("sfinx:process", "Error reading faraon request");
1390    return true;
1392  sfinx_t *el;
1393  string root;
1394  while ((el = rx_elements.next())) {
1395    switch (el->tid()) {
1396      case SFINX_NOTES_MODULE_ADD:
1397        notes_module_add((sfinx_note_t *)el);
1398        break;
1399      case SFINX_NOTES_MODULE_TREE_REQUEST:
1400        get_objects(SFINX_NOTES_MODULE_TREE, (1 << SFINX_NOTE_OBJECT));
1401        break;
1402      case SFINX_FILES_MODULE_SORTED_UNLINK:
1403        mark_file_unsorted((sfinx_file_t *)el, true);
1404        break;
1405      case SFINX_FILES_MODULE_UNSORT:
1406        mark_file_unsorted((sfinx_file_t *)el);
1407        break;
1408      case SFINX_FILES_MODULE_UNLINK:
1409        unlink(((sfinx_string_t *)el)->c_str());
1410        break;
1411      case SFINX_ELEMENT_SEARCH_QUERY:
1412        search_query((sfinx_search_query_t *)el);
1413        break;
1414      case SFINX_FILES_MODULE_EDIT_FILE:
1415        edit_file((sfinx_file_t *)el);
1416        break;
1417      case SFINX_FILES_MODULE_EDIT_FILE_REQUEST:
1418        send_file((sfinx_file_t *)el);
1419        break;
1420      case SFINX_FILES_MODULE_CLASSIFY_REQUEST:
1421        files_module_classify((sfinx_file_t *)el);
1422        break;
1423      case SFINX_FILES_MODULE_SORTED_TREE_REQUEST:
1424        send_dir(true, (sfinx_file_t *)el);
1425        break;
1426      case SFINX_FILES_MODULE_UNSORTED_TREE_REQUEST:
1427        send_dir(false, (sfinx_file_t *)el);
1428        break;
1429      case SFINX_FILES_MODULE_CONF:
1430        update_files_module_conf((sfinx_pair_vector_t *)el);
1431        break;
1432      case SFINX_FILES_MODULE_CONF_REQUEST:
1433 //     case SFINX_XXX_MODULE_CONF_REQUEST:
1434        module_conf_request(el->tid());
1435        break;
1436      case SFINX_SLICE_RELINK:
1437        relink_slice((sfinx_slice_t *)el);
1438        break;
1439      case SFINX_DELETE_SLICE_ASSOC_DATA:
1440        delete_slice_assoc_data(((sfinx_32bit_t *)el)->get(), 0);
1441        break;
1442      case SFINX_DELETE_SLICE_ASSOC_DATA_RECURSIVLY:
1443        delete_slice_assoc_data(((sfinx_32bit_t *)el)->get(), 1);
1444        break;
1445      case SFINX_DELETE_SLICE_MARK_DATA_UNSORTED:
1446        delete_slice_mark_data_unsorted(((sfinx_32bit_t *)el)->get(), 0);
1447        break;
1448      case SFINX_DELETE_SLICE_MARK_DATA_UNSORTED_RECURSIVLY:
1449        delete_slice_mark_data_unsorted(((sfinx_32bit_t *)el)->get(), 1);
1450        break;
1451      case SFINX_DELETE_SLICE_WITH_REATTACH:
1452        delete_slice_with_reattach(((sfinx_32bit_t *)el)->get());
1453        break;
1454      case SFINX_DELETE_SLICE_RECURSIVLY:
1455        delete_slice_recursivly(((sfinx_32bit_t *)el)->get());
1456        break;
1457      case SFINX_NEW_SLICE:
1458        new_slice((sfinx_slice_t *)el);
1459        break;
1460      case SFINX_EDIT_SLICE:
1461        update_slice((sfinx_slice_t *)el);
1462        break;
1463      case SFINX_OBJECTS_TREE_REQUEST:
1464        get_objects(SFINX_OBJECTS_TREE, ((sfinx_32bit_t *)el)->get());
1465        break;
1466      case SFINX_SLICES_MODULE_TREE_REQUEST:
1467        get_slices(SFINX_SLICES_MODULE_TREE);
1468        break;
1469      case SFINX_SLICES_MODULE_TREE_REQUEST_EXCEPT:
1470        get_slices(SFINX_SLICES_MODULE_TREE_EXCEPT, ((sfinx_32bit_t *)el)->get());
1471        break;
1472      case SFINX_EDIT_SLICE_REQUEST:
1473        get_slice(((sfinx_32bit_t *)el)->get(), SFINX_EDIT_SLICE);
1474        break;
1475      default:
1476        log("sfinx:process", "Unknown element id - 0x%x", el->tid());
1477        break;
1478    }
1480  return false;