logontime.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /*
  2. * Logon/logoff time manager and asynchronous updater
  3. */
  4. #include <memory>
  5. #include <mutex>
  6. #include <unordered_map>
  7. #include <cstdio>
  8. #include <kopano/kcodes.h>
  9. #include "logontime.hpp"
  10. #include "ECDatabase.h"
  11. #include "ECSecurity.h"
  12. #include "ECSession.h"
  13. #include "edkmdb.h"
  14. namespace KC {
  15. static std::unordered_map<unsigned int, time_t> ltm_ontime_cache, ltm_offtime_cache;
  16. static std::mutex ltm_ontime_mutex, ltm_offtime_mutex;
  17. static ECRESULT ltm_sync_time(ECDatabase *db,
  18. const std::pair<unsigned int, time_t> &e, bool dir)
  19. {
  20. FILETIME ft;
  21. UnixTimeToFileTime(e.second, &ft);
  22. std::string query = "SELECT hierarchy_id FROM stores WHERE stores.user_id=" + stringify(e.first) + " LIMIT 1";
  23. DB_RESULT result;
  24. ECRESULT ret = db->DoSelect(query, &result);
  25. if (ret != erSuccess)
  26. return ret;
  27. if (db->GetNumRows(result) == 0)
  28. return erSuccess;
  29. DB_ROW row = db->FetchRow(result);
  30. if (row == nullptr)
  31. return erSuccess;
  32. unsigned int store_id = strtoul(row[0], NULL, 0);
  33. unsigned int prop = dir ? PR_LAST_LOGON_TIME : PR_LAST_LOGOFF_TIME;
  34. result = DB_RESULT();
  35. query = "REPLACE INTO properties (tag, type, hierarchyid, val_hi, val_lo) VALUES(" +
  36. stringify(PROP_ID(prop)) + "," + stringify(PROP_TYPE(prop)) + "," +
  37. stringify(store_id) + "," + stringify(ft.dwHighDateTime) + "," +
  38. stringify(ft.dwLowDateTime) + ")";
  39. return db->DoInsert(query);
  40. }
  41. void sync_logon_times(ECDatabase *db)
  42. {
  43. /*
  44. * Switchgrab the global map, so that we can run it to the database
  45. * without holdings locks.
  46. */
  47. bool failed = false;
  48. ltm_ontime_mutex.lock();
  49. decltype(ltm_ontime_cache) logon_time = std::move(ltm_ontime_cache);
  50. ltm_ontime_mutex.unlock();
  51. ltm_offtime_mutex.lock();
  52. decltype(ltm_offtime_cache) logoff_time = std::move(ltm_offtime_cache);
  53. ltm_offtime_mutex.unlock();
  54. if (logon_time.size() > 0 || logoff_time.size() > 0)
  55. ec_log_debug("Writing out logon/logoff time cache (%zu/%zu entries) to DB",
  56. logon_time.size(), logoff_time.size());
  57. for (const auto &i : logon_time)
  58. failed |= ltm_sync_time(db, i, 0) != erSuccess;
  59. for (const auto &i : logoff_time)
  60. failed |= ltm_sync_time(db, i, 1) != erSuccess;
  61. if (failed)
  62. ec_log_warn("Writeout of logon/off time cache unsuccessful");
  63. }
  64. /*
  65. * Save the current time as the last logon time for the logged-on user of
  66. * @ses.
  67. */
  68. void record_logon_time(ECSession *ses, bool logon)
  69. {
  70. unsigned int uid = ses->GetSecurity()->GetUserId();
  71. time_t now = time(NULL);
  72. if (logon) {
  73. ltm_ontime_mutex.lock();
  74. ltm_ontime_cache[uid] = now;
  75. ltm_ontime_mutex.unlock();
  76. } else {
  77. ltm_offtime_mutex.lock();
  78. ltm_offtime_cache[uid] = now;
  79. ltm_offtime_mutex.unlock();
  80. }
  81. }
  82. } /* namespace */