Whyblocked reminds you why you blocked someone.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

194 lines
4.8KB

  1. /* This file is part of whyblocked.
  2. * Copyright © 2018, 2019 tastytea <tastytea@tastytea.de>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, version 3.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <iostream>
  17. #include <string>
  18. #include <vector>
  19. #include <iterator>
  20. #include <experimental/filesystem>
  21. #include <basedir.h>
  22. #include <sqlite/connection.hpp>
  23. #include <sqlite/execute.hpp>
  24. #include <sqlite/query.hpp>
  25. #include "whyblocked.hpp"
  26. using std::cerr;
  27. namespace fs = std::experimental::filesystem;
  28. Database::data::operator bool() const
  29. {
  30. return !user.empty();
  31. }
  32. const string Database::get_filepath() const
  33. {
  34. fs::path filepath;
  35. xdgHandle xdg;
  36. xdgInitHandle(&xdg);
  37. filepath = xdgDataHome(&xdg);
  38. xdgWipeHandle(&xdg);
  39. filepath /= "whyblocked";
  40. if (!fs::exists(filepath))
  41. {
  42. fs::create_directories(filepath);
  43. }
  44. filepath /= "database.sqlite";
  45. if (!fs::exists(filepath))
  46. {
  47. sqlite::connection con(filepath);
  48. sqlite::execute(con, "CREATE TABLE blocks(user TEXT PRIMARY KEY, "
  49. "blocked INTEGER, reason TEXT);", true);
  50. sqlite::execute(con, "CREATE TABLE urls(user TEXT, url TEXT);", true);
  51. }
  52. return filepath;
  53. }
  54. bool Database::add_user(const Database::data &userdata)
  55. {
  56. try
  57. {
  58. int blocked_int = 0;
  59. if (userdata.blocked)
  60. {
  61. blocked_int = 1;
  62. }
  63. sqlite::connection con(get_filepath());
  64. {
  65. sqlite::execute ins(con, "INSERT INTO blocks VALUES(?, ?, ?);");
  66. ins % userdata.user % blocked_int % userdata.reason;
  67. ins();
  68. }
  69. {
  70. for (const string &receipt : userdata.receipts)
  71. {
  72. sqlite::execute ins(con, "INSERT INTO urls VALUES(?, ?);");
  73. ins % userdata.user % receipt;
  74. ins();
  75. }
  76. }
  77. _data.push_back(userdata);
  78. }
  79. catch (const std::exception &e)
  80. {
  81. cerr << "An error occurred: " << e.what() << std::endl;
  82. return false;
  83. }
  84. return true;
  85. }
  86. bool Database::remove(const string &user)
  87. {
  88. try
  89. {
  90. sqlite::connection con(get_filepath());
  91. sqlite::execute rm_blocks(con, "DELETE FROM blocks WHERE user = ?;");
  92. sqlite::execute rm_urls(con, "DELETE FROM urls WHERE user = ?;");
  93. rm_blocks % user;
  94. rm_urls % user;
  95. rm_blocks();
  96. rm_urls();
  97. reload();
  98. }
  99. catch (const std::exception &e)
  100. {
  101. cerr << "An error occurred: " << e.what() << std::endl;
  102. return false;
  103. }
  104. return true;
  105. }
  106. const vector<Database::data> Database::query(const string &sql_query) const
  107. {
  108. try
  109. {
  110. sqlite::connection con(get_filepath());
  111. sqlite::query q_blocks(con, sql_query);
  112. sqlite::result_type res_blocks = q_blocks.get_result();
  113. std::vector<data> result;
  114. while(res_blocks->next_row())
  115. {
  116. const string user = res_blocks->get_string(0);
  117. const int blocked = res_blocks->get_int(1);
  118. const string reason = res_blocks->get_string(2);
  119. bool blocked_bool = false;
  120. if (blocked == 1)
  121. {
  122. blocked_bool = true;
  123. }
  124. sqlite::query q_urls(con,
  125. "SELECT * FROM urls WHERE user = \'" + user + "\';");
  126. sqlite::result_type res_urls = q_urls.get_result();
  127. vector<string> receipts;
  128. while(res_urls->next_row())
  129. {
  130. receipts.push_back(res_urls->get_string(1));
  131. }
  132. result.push_back(
  133. {
  134. user,
  135. blocked_bool,
  136. reason,
  137. receipts
  138. });
  139. }
  140. return result;
  141. }
  142. catch (const std::exception &e)
  143. {
  144. cerr << "An error occurred: " << e.what() << std::endl;
  145. return {};
  146. }
  147. }
  148. bool Database::reload()
  149. {
  150. auto buffer = query();
  151. if (buffer.empty())
  152. {
  153. return false;
  154. }
  155. else
  156. {
  157. _data = std::move(buffer);
  158. return true;
  159. }
  160. }
  161. std::vector<Database::data> &Database::get_data()
  162. {
  163. return _data;
  164. }
  165. const Database::data Database::get_user(const string &user) const
  166. {
  167. for (const Database::data &entry : _data)
  168. {
  169. if (entry.user == user)
  170. {
  171. return entry;
  172. }
  173. }
  174. return {};
  175. }