| 1 | <?php |
|---|
| 2 | |
|---|
| 3 | require_once(IA_ROOT_DIR."common/db/db.php"); |
|---|
| 4 | require_once(IA_ROOT_DIR."common/db/tags.php"); |
|---|
| 5 | require_once(IA_ROOT_DIR."common/db/attachment.php"); |
|---|
| 6 | require_once(IA_ROOT_DIR."common/security.php"); |
|---|
| 7 | require_once(IA_ROOT_DIR."common/textblock.php"); |
|---|
| 8 | require_once(IA_ROOT_DIR."common/common.php"); |
|---|
| 9 | |
|---|
| 10 | // Textblock-related db functions. |
|---|
| 11 | // |
|---|
| 12 | // FIXME: this is beyond retarded, refactor mercilessly. |
|---|
| 13 | |
|---|
| 14 | // Add a new revision |
|---|
| 15 | // FIXME: hash parameter? |
|---|
| 16 | function textblock_add_revision( |
|---|
| 17 | $name, $title, $content, $user_id, $security = "public", |
|---|
| 18 | $forum_topic = null, $timestamp = null, $creation_timestamp = null, |
|---|
| 19 | $remote_ip_info = null) { |
|---|
| 20 | $name = normalize_page_name($name); |
|---|
| 21 | |
|---|
| 22 | // Change special characters in content |
|---|
| 23 | $content = text_change_special_chars($content); |
|---|
| 24 | |
|---|
| 25 | $tb = array( |
|---|
| 26 | 'name' => $name, |
|---|
| 27 | 'title' => $title, |
|---|
| 28 | 'text' => $content, |
|---|
| 29 | 'user_id' => $user_id, |
|---|
| 30 | 'security' => $security, |
|---|
| 31 | 'forum_topic' => $forum_topic, |
|---|
| 32 | 'timestamp' => $timestamp, |
|---|
| 33 | 'creation_timestamp' => $creation_timestamp, |
|---|
| 34 | 'remote_ip_info' => $remote_ip_info, |
|---|
| 35 | ); |
|---|
| 36 | log_assert_valid(textblock_validate($tb)); |
|---|
| 37 | |
|---|
| 38 | // get current revision |
|---|
| 39 | $query = sprintf("SELECT * FROM ia_textblock |
|---|
| 40 | WHERE `name` = '%s'", |
|---|
| 41 | db_escape($name)); |
|---|
| 42 | $current_revision = db_fetch($query); |
|---|
| 43 | |
|---|
| 44 | if ($current_revision) { |
|---|
| 45 | // copy current version to revision table |
|---|
| 46 | db_insert('ia_textblock_revision', $current_revision); |
|---|
| 47 | |
|---|
| 48 | // replace current version |
|---|
| 49 | $query = sprintf("DELETE FROM ia_textblock |
|---|
| 50 | WHERE `name` = '%s' |
|---|
| 51 | LIMIT 1", |
|---|
| 52 | db_escape($name)); |
|---|
| 53 | db_query($query); |
|---|
| 54 | } |
|---|
| 55 | |
|---|
| 56 | // Evil. |
|---|
| 57 | if ($creation_timestamp === null) { |
|---|
| 58 | $creation_timestamp = db_date_format(); |
|---|
| 59 | } else { |
|---|
| 60 | log_assert(is_db_date($creation_timestamp), "Invalid timestamp"); |
|---|
| 61 | } |
|---|
| 62 | if ($timestamp === null) { |
|---|
| 63 | $timestamp = db_date_format(); |
|---|
| 64 | } else { |
|---|
| 65 | log_assert(is_db_date($timestamp), "Invalid timestamp"); |
|---|
| 66 | } |
|---|
| 67 | $query = sprintf("INSERT INTO ia_textblock |
|---|
| 68 | (name, `text`, `title`, `creation_timestamp`, |
|---|
| 69 | `timestamp`, `user_id`, `security`, `forum_topic`, |
|---|
| 70 | `remote_ip_info`) |
|---|
| 71 | VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', %s, %s)", |
|---|
| 72 | db_escape($name), db_escape($content), db_escape($title), |
|---|
| 73 | db_escape($creation_timestamp), db_escape($timestamp), |
|---|
| 74 | db_escape($user_id), db_escape($security), db_quote($forum_topic), |
|---|
| 75 | db_quote($remote_ip_info)); |
|---|
| 76 | return db_query($query); |
|---|
| 77 | } |
|---|
| 78 | |
|---|
| 79 | // Delete $revision from database |
|---|
| 80 | // The revision is identified by name and timestamp |
|---|
| 81 | // $curr is true if $revision is the current revision and false otherwise |
|---|
| 82 | function textblock_delete_revision($revision, $curr) |
|---|
| 83 | { |
|---|
| 84 | if ($curr == false) { |
|---|
| 85 | $name = $revision['name']; |
|---|
| 86 | $timestamp = $revision['timestamp']; |
|---|
| 87 | $query = "DELETE FROM `ia_textblock_revision` |
|---|
| 88 | WHERE `name` = ".db_quote($name)." && |
|---|
| 89 | `timestamp` = ".db_quote($timestamp); |
|---|
| 90 | db_query($query); |
|---|
| 91 | } else { |
|---|
| 92 | $name = $revision['name']; |
|---|
| 93 | $query = "REPLACE INTO `ia_textblock` |
|---|
| 94 | (SELECT * FROM `ia_textblock_revision` |
|---|
| 95 | WHERE `name` = ".db_quote($name)." |
|---|
| 96 | ORDER BY `timestamp` DESC LIMIT 1)"; |
|---|
| 97 | db_query($query); |
|---|
| 98 | |
|---|
| 99 | //delete last_rev from ia_textblock_revision |
|---|
| 100 | $query = "DELETE FROM `ia_textblock_revision` |
|---|
| 101 | WHERE `name` = ".db_quote($name)." |
|---|
| 102 | ORDER BY `timestamp` DESC LIMIT 1"; |
|---|
| 103 | db_query($query); |
|---|
| 104 | } |
|---|
| 105 | } |
|---|
| 106 | |
|---|
| 107 | // This is the function called by most query functions. |
|---|
| 108 | function textblock_complex_query($options) |
|---|
| 109 | { |
|---|
| 110 | // log_print_r($options); |
|---|
| 111 | |
|---|
| 112 | $field_list = "`name`, `title`, `creation_timestamp`, `timestamp`, `security`, `user_id`, |
|---|
| 113 | `forum_topic`, `remote_ip_info`"; |
|---|
| 114 | |
|---|
| 115 | // Select content. |
|---|
| 116 | if (getattr($options, 'content', false) == true) { |
|---|
| 117 | $field_list .= ", `text`"; |
|---|
| 118 | } |
|---|
| 119 | |
|---|
| 120 | // Add a join for username. |
|---|
| 121 | if (getattr($options, 'username', false) == true) { |
|---|
| 122 | $field_list .= ", `username` as `user_name`, `full_name` as `user_fullname`, rating_cache"; |
|---|
| 123 | $join = "LEFT JOIN ia_user ON `user_id` = `ia_user`.`id`"; |
|---|
| 124 | } else { |
|---|
| 125 | $join = ""; |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | // prefix or page_name |
|---|
| 129 | if (getattr($options, 'page_name') === null) { |
|---|
| 130 | log_assert(is_string($options['prefix'])); |
|---|
| 131 | $where = sprintf("WHERE `name` LIKE '%s%%'", db_escape(strtolower($options['prefix']))); |
|---|
| 132 | } else { |
|---|
| 133 | $where = sprintf("WHERE `name` = '%s'", db_escape(strtolower($options['page_name']))); |
|---|
| 134 | } |
|---|
| 135 | |
|---|
| 136 | if (strtolower(getattr($options, 'order') == 'desc')) { |
|---|
| 137 | $order = 'DESC'; |
|---|
| 138 | } else { |
|---|
| 139 | $order = 'ASC'; |
|---|
| 140 | } |
|---|
| 141 | |
|---|
| 142 | // When doing a history query. |
|---|
| 143 | if (getattr($options, 'history', false) == true) { |
|---|
| 144 | log_assert(is_whole_number($options['limit_start'])); |
|---|
| 145 | log_assert(is_whole_number($options['limit_count'])); |
|---|
| 146 | $query = sprintf("SELECT $field_list FROM ia_textblock $join %s |
|---|
| 147 | UNION ALL SELECT $field_list FROM ia_textblock_revision $join %s |
|---|
| 148 | ORDER BY `timestamp` %s LIMIT %d, %d", |
|---|
| 149 | $where, $where, $order, $options['limit_start'], $options['limit_count']); |
|---|
| 150 | } else { |
|---|
| 151 | $query = "SELECT $field_list FROM ia_textblock |
|---|
| 152 | $join $where ORDER BY ia_textblock.`creation_timestamp` $order"; |
|---|
| 153 | } |
|---|
| 154 | // log_print("QUERY: " . $query); |
|---|
| 155 | return db_fetch_all($query); |
|---|
| 156 | } |
|---|
| 157 | |
|---|
| 158 | // Get a certain revision of a textblock. Parameters: |
|---|
| 159 | // $name: Textblock name. |
|---|
| 160 | // $rev_num: Revision number. Latest if null(default). |
|---|
| 161 | // $username: Get user name info. |
|---|
| 162 | function textblock_get_revision($name, $rev_num = null, $username = false) |
|---|
| 163 | { |
|---|
| 164 | $name = normalize_page_name($name); |
|---|
| 165 | log_assert(is_normal_page_name($name)); |
|---|
| 166 | if (is_null($rev_num)) { |
|---|
| 167 | // Quick latest revision query. |
|---|
| 168 | $res = textblock_complex_query(array( |
|---|
| 169 | 'page_name' => $name, |
|---|
| 170 | 'content' => true, |
|---|
| 171 | 'username' => $username, |
|---|
| 172 | )); |
|---|
| 173 | } else { |
|---|
| 174 | $res = textblock_complex_query(array( |
|---|
| 175 | 'page_name' => $name, |
|---|
| 176 | 'content' => true, |
|---|
| 177 | 'username' => $username, |
|---|
| 178 | 'history' => true, |
|---|
| 179 | 'limit_start' => (int)$rev_num - 1, |
|---|
| 180 | 'limit_count' => 1, |
|---|
| 181 | )); |
|---|
| 182 | } |
|---|
| 183 | return array_key_exists(0, $res) ? $res[0] : null; |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | // Get all revisions of a text_block. |
|---|
| 187 | // $name: The textblock name. |
|---|
| 188 | // $content: If true also get content. Defaults to false. |
|---|
| 189 | // $username: If true join for username. Defaults to true. |
|---|
| 190 | function textblock_get_revision_list($name, $content = false, $username = true, |
|---|
| 191 | $start = 1, $count = 99999999) { |
|---|
| 192 | $name = normalize_page_name($name); |
|---|
| 193 | log_assert(is_normal_page_name($name)); |
|---|
| 194 | return textblock_complex_query(array( |
|---|
| 195 | 'content' => $content, |
|---|
| 196 | 'username' => $username, |
|---|
| 197 | 'page_name' => $name, |
|---|
| 198 | 'history' => true, |
|---|
| 199 | 'limit_start' => $start - 1, |
|---|
| 200 | 'limit_count' => $count, |
|---|
| 201 | )); |
|---|
| 202 | } |
|---|
| 203 | |
|---|
| 204 | // Get all textblocks(without content) with a certain prefix). |
|---|
| 205 | // Ordered by name. |
|---|
| 206 | function textblock_get_by_prefix($prefix, $content = false, $username = false, |
|---|
| 207 | $order = 'asc') { |
|---|
| 208 | return textblock_complex_query(array( |
|---|
| 209 | 'content' => $content, |
|---|
| 210 | 'username' => $username, |
|---|
| 211 | 'prefix' => $prefix, |
|---|
| 212 | 'order' => $order, |
|---|
| 213 | )); |
|---|
| 214 | } |
|---|
| 215 | |
|---|
| 216 | // Get all textblocks(without content) with a certain prefix. |
|---|
| 217 | // Ordered by name. |
|---|
| 218 | function textblock_get_changes($prefix, $content = false, $username = true, |
|---|
| 219 | $offset = 0, $count = 50) { |
|---|
| 220 | return textblock_complex_query(array( |
|---|
| 221 | 'content' => $content, |
|---|
| 222 | 'username' => $username, |
|---|
| 223 | 'prefix' => $prefix, |
|---|
| 224 | 'history' => true, |
|---|
| 225 | 'order' => 'desc', |
|---|
| 226 | 'limit_start' => $offset, |
|---|
| 227 | 'limit_count' => $count, |
|---|
| 228 | )); |
|---|
| 229 | } |
|---|
| 230 | |
|---|
| 231 | // Count revisions for a certain textblock. |
|---|
| 232 | // FIXME: undefined if it doesn't exist. |
|---|
| 233 | function textblock_get_revision_count($name) { |
|---|
| 234 | $name = normalize_page_name($name); |
|---|
| 235 | log_assert(is_normal_page_name($name)); |
|---|
| 236 | |
|---|
| 237 | $query = sprintf("SELECT COUNT(*) AS `cnt` FROM ia_textblock_revision |
|---|
| 238 | WHERE `name` = '%s'", |
|---|
| 239 | db_escape(strtolower($name))); |
|---|
| 240 | $row = db_fetch($query); |
|---|
| 241 | return $row['cnt'] + 1; |
|---|
| 242 | } |
|---|
| 243 | |
|---|
| 244 | // Grep through textblocks. This is mostly a hack needed for macro_grep.php |
|---|
| 245 | // Also used for round deletion |
|---|
| 246 | function textblock_grep($substr, $page, $regexp = false, $offset = null, $count = null) { |
|---|
| 247 | if (!$regexp) { |
|---|
| 248 | $compare = "LIKE"; |
|---|
| 249 | } else { |
|---|
| 250 | $compare = "REGEXP"; |
|---|
| 251 | } |
|---|
| 252 | $query = sprintf("SELECT `name`, `title`, `creation_timestamp`, `timestamp`, |
|---|
| 253 | `user_id`, `security`, `forum_topic`, |
|---|
| 254 | `remote_ip_info` |
|---|
| 255 | FROM ia_textblock |
|---|
| 256 | WHERE `name` LIKE '%s' AND |
|---|
| 257 | (`text` $compare '%s' OR `title` $compare '%s') |
|---|
| 258 | ORDER BY `name`", |
|---|
| 259 | db_escape($page), db_escape($substr), db_escape($substr)); |
|---|
| 260 | |
|---|
| 261 | if (is_whole_number($offset) && is_whole_number($count)) { |
|---|
| 262 | $query .= sprintf(" LIMIT %s, %s", |
|---|
| 263 | db_escape($offset), db_escape($count)); |
|---|
| 264 | } |
|---|
| 265 | return db_fetch_all($query); |
|---|
| 266 | } |
|---|
| 267 | |
|---|
| 268 | function textblock_grep_count($substr, $page, $regexp = false) { |
|---|
| 269 | if (!$regexp) { |
|---|
| 270 | $compare = "LIKE"; |
|---|
| 271 | } else { |
|---|
| 272 | $compare = "REGEXP"; |
|---|
| 273 | } |
|---|
| 274 | $query = sprintf("SELECT COUNT(*) as `cnt` |
|---|
| 275 | FROM ia_textblock |
|---|
| 276 | WHERE `name` LIKE '%s' AND |
|---|
| 277 | (`text` $compare '%s' OR `title` $compare '%s')", |
|---|
| 278 | db_escape($page), db_escape($substr), db_escape($substr)); |
|---|
| 279 | return db_fetch($query); |
|---|
| 280 | } |
|---|
| 281 | |
|---|
| 282 | // Delete a certain page, including all revisions and attachments. |
|---|
| 283 | // WARNING: This is irreversible. |
|---|
| 284 | function textblock_delete($page_name) { |
|---|
| 285 | $page_name = normalize_page_name($page_name); |
|---|
| 286 | log_assert(is_normal_page_name($page_name)); |
|---|
| 287 | |
|---|
| 288 | $pageesc = db_escape($page_name); |
|---|
| 289 | $atts = attachment_get_all($page_name); |
|---|
| 290 | foreach ($atts as $att) { |
|---|
| 291 | if (!attachment_delete($att)) { |
|---|
| 292 | log_warn('Could not delete attachment from '.$page_name); |
|---|
| 293 | return false; |
|---|
| 294 | } |
|---|
| 295 | } |
|---|
| 296 | tag_clear('textblock', $page_name); |
|---|
| 297 | |
|---|
| 298 | db_query("DELETE FROM `ia_textblock_revision` WHERE `name` = '$pageesc'"); |
|---|
| 299 | db_query("DELETE FROM `ia_textblock` WHERE `name` = '$pageesc'"); |
|---|
| 300 | |
|---|
| 301 | return (db_affected_rows() != 0); |
|---|
| 302 | } |
|---|
| 303 | |
|---|
| 304 | // Move a page from old_name to new_name. |
|---|
| 305 | // Also drags attachments. |
|---|
| 306 | function textblock_move($old_name, $new_name) { |
|---|
| 307 | $old_name = normalize_page_name($old_name); |
|---|
| 308 | $new_name = normalize_page_name($new_name); |
|---|
| 309 | log_assert(is_normal_page_name($old_name)); |
|---|
| 310 | log_assert(is_normal_page_name($new_name)); |
|---|
| 311 | //log_print("Moving textblock $old_name to $new_name"); |
|---|
| 312 | |
|---|
| 313 | // Move current version. |
|---|
| 314 | $query = sprintf("UPDATE `ia_textblock` |
|---|
| 315 | SET `name` = '%s' |
|---|
| 316 | WHERE `name` = '%s'", |
|---|
| 317 | db_escape($new_name), db_escape($old_name)); |
|---|
| 318 | db_query($query); |
|---|
| 319 | |
|---|
| 320 | // Move history. |
|---|
| 321 | $query = sprintf("UPDATE `ia_textblock_revision` |
|---|
| 322 | SET `name` = '%s' |
|---|
| 323 | WHERE `name` = '%s'", |
|---|
| 324 | db_escape($new_name), db_escape($old_name)); |
|---|
| 325 | db_query($query); |
|---|
| 326 | |
|---|
| 327 | // Get a list of attachments. |
|---|
| 328 | $files = attachment_get_all($old_name); |
|---|
| 329 | |
|---|
| 330 | // Move attachments in db. |
|---|
| 331 | $query = sprintf("UPDATE `ia_file` |
|---|
| 332 | SET `page` = '%s' |
|---|
| 333 | WHERE `page` = '%s'", |
|---|
| 334 | db_escape($new_name), db_escape($old_name)); |
|---|
| 335 | db_query($query); |
|---|
| 336 | |
|---|
| 337 | // Move attachments on disk. Ooops. |
|---|
| 338 | foreach ($files as $file) { |
|---|
| 339 | $old_filename = attachment_get_filepath($file); |
|---|
| 340 | $file['page'] = $new_name; |
|---|
| 341 | $new_filename = attachment_get_filepath($file); |
|---|
| 342 | |
|---|
| 343 | if (!@rename($old_filename, $new_filename)) { |
|---|
| 344 | log_error("Failed moving attachment from $old_filename to $new_filename"); |
|---|
| 345 | } |
|---|
| 346 | } |
|---|
| 347 | } |
|---|
| 348 | |
|---|
| 349 | // Copy a textblock to new_name. |
|---|
| 350 | // Also copies attachments. |
|---|
| 351 | function textblock_copy($old_textblock, $new_name, $user_id, $remote_ip_info) { |
|---|
| 352 | log_assert(!textblock_validate($old_textblock)); |
|---|
| 353 | $new_name = normalize_page_name($new_name); |
|---|
| 354 | log_assert(is_normal_page_name($new_name)); |
|---|
| 355 | |
|---|
| 356 | $new_textblock = $old_textblock; |
|---|
| 357 | $new_textblock['name'] = $new_name; |
|---|
| 358 | $new_textblock['user_id'] = $user_id; |
|---|
| 359 | $new_textblock['creation_timestamp'] = null; |
|---|
| 360 | // Keep creation_timestamp correct when textblock with new name already exists |
|---|
| 361 | $aux = textblock_get_revision($new_name); |
|---|
| 362 | if ($aux) { |
|---|
| 363 | $new_textblock['creation_timestamp'] = $aux['creation_timestamp']; |
|---|
| 364 | } |
|---|
| 365 | textblock_add_revision($new_textblock['name'], $new_textblock['title'], |
|---|
| 366 | $new_textblock['text'], $new_textblock['user_id'], |
|---|
| 367 | $new_textblock['security'], |
|---|
| 368 | $new_textblock['forum_topic'], |
|---|
| 369 | null, $new_textblock['creation_timestamp'], |
|---|
| 370 | $remote_ip_info); |
|---|
| 371 | |
|---|
| 372 | // Get a list of attachments. |
|---|
| 373 | $files = attachment_get_all($old_textblock["name"]); |
|---|
| 374 | |
|---|
| 375 | // Copy attachments in db and hard drive |
|---|
| 376 | foreach ($files as $file) { |
|---|
| 377 | // Copy in db and get new id |
|---|
| 378 | $new_id = attachment_insert($file['name'], $file['size'], |
|---|
| 379 | $file['mime_type'], $new_name, $user_id, $remote_ip_info); |
|---|
| 380 | |
|---|
| 381 | // Copy on hard drive |
|---|
| 382 | $old_filename = attachment_get_filepath($file); |
|---|
| 383 | $file['page'] = $new_name; |
|---|
| 384 | $file['id'] = $new_id; |
|---|
| 385 | $new_filename = attachment_get_filepath($file); |
|---|
| 386 | |
|---|
| 387 | if (!@copy($old_filename, $new_filename)) { |
|---|
| 388 | log_error("Failed copying attachment from $old_filename to $new_filename"); |
|---|
| 389 | } |
|---|
| 390 | } |
|---|
| 391 | } |
|---|
| 392 | |
|---|
| 393 | ?> |
|---|