PageRenderTime 24ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/mnemo/lib/Driver/Sql.php

https://github.com/sgtcarneiro/horde
PHP | 365 lines | 201 code | 36 blank | 128 comment | 16 complexity | 43a2926b0f1b4bc899eb2203cb52cba0 MD5 | raw file
  1. <?php
  2. /**
  3. * Mnemo storage implementation for Horde's Horde_Db database abstraction
  4. * layer.
  5. *
  6. * Copyright 2001-2011 The Horde Project (http://www.horde.org/)
  7. *
  8. * See the enclosed file LICENSE for license information (ASL). If you
  9. * did not receive this file, see http://www.horde.org/licenses/asl.php.
  10. *
  11. * @author Chuck Hagenbuch <chuck@horde.org>
  12. * @author Michael J. Rubinsky <mrubinsk@horde.org>
  13. * @package Mnemo
  14. */
  15. class Mnemo_Driver_Sql extends Mnemo_Driver
  16. {
  17. /**
  18. * The database connection object.
  19. *
  20. * @var Horde_Db_Adapter
  21. */
  22. protected $_db;
  23. /**
  24. * Share table name
  25. *
  26. * @var string
  27. */
  28. protected $_table;
  29. /**
  30. * Charset
  31. *
  32. * @var string
  33. */
  34. protected $_charset;
  35. /**
  36. * Construct a new SQL storage object.
  37. *
  38. * @param string $notepad The name of the notepad to load/save notes from.
  39. * @param array $params The connection parameters
  40. *
  41. * @throws InvalidArguementException
  42. */
  43. public function __construct($notepad, $params = array())
  44. {
  45. if (empty($params['db']) || empty($params['table'])) {
  46. throw new InvalidArgumentException('Missing required connection parameter(s).');
  47. }
  48. $this->_notepad = $notepad;
  49. $this->_db = $params['db'];
  50. $this->_table = $params['table'];
  51. $this->_charset = $params['charset'];
  52. }
  53. /**
  54. * Retrieve one note from the database.
  55. *
  56. * @param string $noteId The ID of the note to retrieve.
  57. * @param string $passphrase A passphrase with which this note was
  58. * supposed to be encrypted.
  59. *
  60. * @return array The array of note attributes.
  61. * @throws Mnemo_Exception
  62. * @throws Horde_Exception_NotFound
  63. */
  64. public function get($noteId, $passphrase = null)
  65. {
  66. $query = 'SELECT * FROM ' . $this->_table .
  67. ' WHERE memo_owner = ? AND memo_id = ?';
  68. $values = array($this->_notepad, $noteId);
  69. try {
  70. $row = $this->_db->selectOne($query, $values);
  71. } catch (Horde_Db_Exception $e) {
  72. throw new Mnemo_Exception($e->getMessage());
  73. }
  74. if (!count($row)) {
  75. throw new Horde_Exception_NotFound(_("Not Found"));
  76. }
  77. return $this->_buildNote($row, $passphrase);
  78. }
  79. /**
  80. * Retrieve one note from the database by UID.
  81. *
  82. * @param string $uid The UID of the note to retrieve.
  83. * @param string $passphrase A passphrase with which this note was
  84. * supposed to be encrypted.
  85. *
  86. * @return array The array of note attributes.
  87. * @throws Mnemo_Exception
  88. * @throws Horde_Exception_NotFound
  89. */
  90. public function getByUID($uid, $passphrase = null)
  91. {
  92. $query = 'SELECT * FROM ' . $this->_table . ' WHERE memo_uid = ?';
  93. $values = array($uid);
  94. try {
  95. $row = $this->_db->selectOne($query, $values);
  96. } catch (Horde_Db_Exception $e) {
  97. throw new Mnemo_Exception($e->getMessage());
  98. }
  99. if (!count($row)) {
  100. throw new Horde_Exception_NotFound('Not found');
  101. }
  102. $this->_notepad = $row['memo_owner'];
  103. return $this->_buildNote($row, $passphrase);
  104. }
  105. /**
  106. * Add a note to the backend storage.
  107. *
  108. * @param string $desc The first line of the note.
  109. * @param string $body The whole note body.
  110. * @param string $category The category of the note.
  111. * @param string $uid A Unique Identifier for the note.
  112. * @param string $passphrase The passphrase to encrypt the note with.
  113. *
  114. * @return string The unique ID of the new note.
  115. * @throws Mnemo_Exception
  116. */
  117. public function add($desc, $body, $category = '', $uid = null, $passphrase = null)
  118. {
  119. $noteId = strval(new Horde_Support_Randomid());
  120. if ($passphrase) {
  121. $body = $this->_encrypt($body, $passphrase);
  122. Mnemo::storePassphrase($noteId, $passphrase);
  123. }
  124. if (is_null($uid)) {
  125. $uid = strval(new Horde_Support_Uuid());
  126. }
  127. $query = 'INSERT INTO ' . $this->_table .
  128. ' (memo_owner, memo_id, memo_desc, memo_body, memo_category, memo_uid)' .
  129. ' VALUES (?, ?, ?, ?, ?, ?)';
  130. $values = array($this->_notepad,
  131. $noteId,
  132. Horde_String::convertCharset($desc, 'UTF-8', $this->_charset),
  133. Horde_String::convertCharset($body, 'UTF-8', $this->_charset),
  134. Horde_String::convertCharset($category, 'UTF-8', $this->_charset),
  135. Horde_String::convertCharset($uid, 'UTF-8', $this->_charset));
  136. try {
  137. $this->_db->insert($query, $values);
  138. } catch (Horde_Db_Exception $e) {
  139. throw new Mnemo_Exception($e->getMessage());
  140. }
  141. // Log the creation of this item in the history log.
  142. // @TODO: Inject the history driver
  143. $history = $GLOBALS['injector']->getInstance('Horde_History');
  144. $history->log('mnemo:' . $this->_notepad . ':' . $uid, array('action' => 'add'), true);
  145. return $noteId;
  146. }
  147. /**
  148. * Modify an existing note.
  149. *
  150. * @param string $noteId The note to modify.
  151. * @param string $desc The description (long) of the note.
  152. * @param string $body The description (long) of the note.
  153. * @param string $category The category of the note.
  154. * @param string $passphrase The passphrase to encrypt the note with.
  155. *
  156. * @throws Mnemo_Exception
  157. */
  158. public function modify($noteId, $desc, $body, $category = null, $passphrase = null)
  159. {
  160. if ($passphrase) {
  161. $body = $this->_encrypt($body, $passphrase);
  162. Mnemo::storePassphrase($noteId, $passphrase);
  163. }
  164. $query = 'UPDATE ' . $this->_table . ' SET memo_desc = ?, memo_body = ?';
  165. $values = array(Horde_String::convertCharset($desc, 'UTF-8', $this->_charset),
  166. Horde_String::convertCharset($body, 'UTF-8', $this->_charset));
  167. // Don't change the category if it isn't provided.
  168. // @TODO: Category -> Tags
  169. if (!is_null($category)) {
  170. $query .= ', memo_category = ?';
  171. $values[] = Horde_String::convertCharset($category, 'UTF-8', $this->_charset);
  172. }
  173. $query .= ' WHERE memo_owner = ? AND memo_id = ?';
  174. array_push($values, $this->_notepad, $noteId);
  175. try {
  176. $this->_db->update($query, $values);
  177. } catch (Horde_Db_Exception $e) {
  178. throw new Mnemo_Exception($e->getMessage());
  179. }
  180. // Log the modification of this item in the history log.
  181. $note = $this->get($noteId);
  182. if (!empty($note['uid'])) {
  183. $history = $GLOBALS['injector']->getInstance('Horde_History');
  184. $history->log('mnemo:' . $this->_notepad . ':' . $note['uid'], array('action' => 'modify'), true);
  185. }
  186. }
  187. /**
  188. * Move a note to a new notepad.
  189. *
  190. * @param string $noteId The note to move.
  191. * @param string $newNotepad The new notepad.
  192. *
  193. * @throws Mnemo_Exception
  194. */
  195. public function move($noteId, $newNotepad)
  196. {
  197. // Get the note's details for use later.
  198. $note = $this->get($noteId);
  199. $query = 'UPDATE ' . $this->_table .
  200. ' SET memo_owner = ?' .
  201. ' WHERE memo_owner = ? AND memo_id = ?';
  202. $values = array($newNotepad, $this->_notepad, $noteId);
  203. try {
  204. $result = $this->_db->update($query, $values);
  205. } catch (Horde_Db_Exception $e) {
  206. throw new Mnemo_Exception($e->getMessage());
  207. }
  208. // Log the moving of this item in the history log.
  209. if (!empty($note['uid'])) {
  210. $history = $GLOBALS['injector']->getInstance('Horde_History');
  211. $history->log('mnemo:' . $this->_notepad . ':' . $note['uid'], array('action' => 'delete'), true);
  212. $history->log('mnemo:' . $newNotepad . ':' . $note['uid'], array('action' => 'add'), true);
  213. }
  214. }
  215. /**
  216. * Delete a note permanently
  217. *
  218. * @param string $noteId The note to delete.
  219. *
  220. * @throws Mnemo_Exception
  221. */
  222. public function delete($noteId)
  223. {
  224. // Get the note's details for use later.
  225. $note = $this->get($noteId);
  226. $query = 'DELETE FROM ' . $this->_table .
  227. ' WHERE memo_owner = ? AND memo_id = ?';
  228. $values = array($this->_notepad, $noteId);
  229. try {
  230. $this->_db->delete($query, $values);
  231. } catch (Horde_Db_Exception $e) {
  232. throw new Mnemo_Exception($e->getMessage());
  233. }
  234. // Log the deletion of this item in the history log.
  235. if (!empty($note['uid'])) {
  236. $history = $GLOBALS['injector']->getInstance('Horde_History');
  237. $history->log('mnemo:' . $this->_notepad . ':' . $note['uid'], array('action' => 'delete'), true);
  238. }
  239. }
  240. /**
  241. * Remove ALL notes belonging to the curernt user.
  242. *
  243. * @throws Mnemo_Exception
  244. */
  245. public function deleteAll()
  246. {
  247. $query = sprintf('DELETE FROM %s WHERE memo_owner = ?',
  248. $this->_table);
  249. $values = array($this->_notepad);
  250. try {
  251. $this->_db->delete($query, $values);
  252. } catch (Horde_Db_Exception $e) {
  253. throw new Mnemo_Exception($e->getMessage());
  254. }
  255. }
  256. /**
  257. * Retrieves all of the notes from $this->_notepad from the
  258. * database.
  259. *
  260. * @throws Mnemo_Exception
  261. */
  262. public function retrieve()
  263. {
  264. $query = sprintf('SELECT * FROM %s WHERE memo_owner = ?', $this->_table);
  265. $values = array($this->_notepad);
  266. try {
  267. $rows = $this->_db->selectAll($query, $values);
  268. } catch (Horde_Db_Exception $e) {
  269. throw new Mnemo_Exception($e->getMessage());
  270. }
  271. // Store the retrieved values in a fresh $memos list.
  272. $this->_memos = array();
  273. foreach ($rows as $row) {
  274. $this->_memos[$row['memo_id']] = $this->_buildNote($row);
  275. }
  276. }
  277. /**
  278. *
  279. * @param array $row Hash of the note data, db keys.
  280. * @param string $passphrase The encryption passphrase.
  281. *
  282. * @return array a Task hash.
  283. * @throws Mnemo_Exception
  284. */
  285. protected function _buildNote($row, $passphrase = null)
  286. {
  287. // Make sure notes always have a UID.
  288. if (empty($row['memo_uid'])) {
  289. $row['memo_uid'] = strval(new Horde_Support_Guid());
  290. $query = 'UPDATE ' . $this->_table .
  291. ' SET memo_uid = ?' .
  292. ' WHERE memo_owner = ? AND memo_id = ?';
  293. $values = array($row['memo_uid'], $row['memo_owner'], $row['memo_id']);
  294. try {
  295. $this->_db->update($query, $values);
  296. } catch (Horde_Db_Exception $e) {
  297. throw new Mnemo_Exception($e->getMessage());
  298. }
  299. }
  300. // Decrypt note if requested.
  301. $encrypted = false;
  302. $body = Horde_String::convertCharset($row['memo_body'], $this->_charset, 'UTF-8');
  303. if (strpos($body, '-----BEGIN PGP MESSAGE-----') === 0) {
  304. $encrypted = true;
  305. if (empty($passphrase)) {
  306. $passphrase = Mnemo::getPassphrase($row['memo_id']);
  307. }
  308. if (empty($passphrase)) {
  309. $body = new Mnemo_Exception(_("This note has been encrypted."), Mnemo::ERR_NO_PASSPHRASE);
  310. } else {
  311. try {
  312. $body = $this->_decrypt($body, $passphrase);
  313. $body = $body->message;
  314. } catch (Mnemo_Exception $e) {
  315. $body = $e;
  316. }
  317. Mnemo::storePassphrase($row['memo_id'], $passphrase);
  318. }
  319. }
  320. // Create a new task based on $row's values.
  321. return array('memolist_id' => $row['memo_owner'],
  322. 'memo_id' => $row['memo_id'],
  323. 'uid' => Horde_String::convertCharset($row['memo_uid'], $this->_charset, 'UTF-8'),
  324. 'desc' => Horde_String::convertCharset($row['memo_desc'], $this->_charset, 'UTF-8'),
  325. 'body' => $body,
  326. 'category' => Horde_String::convertCharset($row['memo_category'], $this->_charset, 'UTF-8'),
  327. 'encrypted' => $encrypted);
  328. }
  329. }