Fixed (well, implemented) log clearing functionality on uploaded files.
authorDan
Tue, 15 Sep 2009 14:37:03 -0400
changeset 1114 4f4d63a281cd
parent 1113 000791abdc7e
child 1115 b3c249d06990
Fixed (well, implemented) log clearing functionality on uploaded files.
includes/namespaces/file.php
includes/pageutils.php
language/english/core.json
--- a/includes/namespaces/file.php	Sat Sep 12 09:56:39 2009 -0400
+++ b/includes/namespaces/file.php	Tue Sep 15 14:37:03 2009 -0400
@@ -87,17 +87,22 @@
     $html .= $lang->get('onpage_filebox_lbl_size', array('size' => $size));
     
     $html .= '<br />' . $lang->get('onpage_filebox_lbl_uploaded') . ' ' . $datestring . '</p>';
-    if ( substr($mimetype, 0, 6) != 'image/' && ( substr($mimetype, 0, 5) != 'text/' || $mimetype == 'text/html' || $mimetype == 'text/javascript' ) )
+    // are we dealing with an image?
+    $is_image = substr($mimetype, 0, 6) == 'image/';
+    
+    // for anything other than plain text and 
+    if ( !$is_image && ( substr($mimetype, 0, 5) != 'text/' || $mimetype == 'text/html' || $mimetype == 'text/javascript' ) )
     {
       $html .= '<div class="warning-box">
               ' . $lang->get('onpage_filebox_msg_virus_warning') . '
             </div>';
     }
-    if ( substr($mimetype, 0, 6) == 'image/' )
+    if ( $is_image )
     {
+      // show a thumbnail of the image
       $html .= '<p>
               <a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn).'">
-                <img style="border: 0;" alt="'.$paths->page.'" src="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn.htmlspecialchars(urlSeparator).'preview').'" />
+                <img style="border: 0;" alt="' . htmlspecialchars($paths->page) . '" src="' . makeUrlNS('Special', "DownloadFile/$selfn/{$r['time_id']}", 'preview', true) . '" />
               </a>
             </p>';
     }
@@ -105,13 +110,24 @@
             <a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn.'/'.$r['time_id'].htmlspecialchars(urlSeparator).'download').'">
               ' . $lang->get('onpage_filebox_btn_download') . '
             </a>';
-    if(!$paths->page_protected && ( $paths->wiki_mode || $session->get_permissions('upload_new_version') ))
+    // allow reupload if:
+    //   * we are allowed to upload new versions, and
+    //      - the file is unprotected, or
+    //      - we have permission to override protection
+    
+    if ( !$this->perms )
+      $this->perms = $session->fetch_page_acl($this->page_id, $this->namespace);
+    
+    if ( $this->perms->get_permissions('upload_new_version') && ( !$this->page_protected || $this->perms->get_permissions('even_when_protected') ) )
     {
-      $html .= '  |  <a href="'.makeUrlNS('Special', 'UploadFile'.'/'.$selfn).'">
+      // upload new version link
+      $html .= '  |  <a href="'.makeUrlNS('Special', "UploadFile/$selfn", false, true).'">
               ' . $lang->get('onpage_filebox_btn_upload_new') . '
             </a>';
     }
+    // close off paragraph
     $html .= '</p>';
+    // only show this if there's more than one revision
     if ( $db->numrows() > 1 )
     {
       // requery, sql_result_seek() doesn't work on postgres
@@ -132,9 +148,10 @@
       
       $html .= '<h3>' . $lang->get('onpage_filebox_heading_history') . '</h3><p>';
       $last_rollback_id = false;
+      $download_flag = $is_image ? false : 'download';
       while ( $r = $db->fetchrow($q) )
       {
-        $html .= '(<a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn.'/'.$r['time_id'].htmlspecialchars(urlSeparator).'download').'">' . $lang->get('onpage_filebox_btn_this_version') . '</a>) ';
+        $html .= '(<a href="'.makeUrlNS('Special', "DownloadFile/$selfn/{$r['time_id']}", $download_flag, true).'">' . $lang->get('onpage_filebox_btn_this_version') . '</a>) ';
         if ( $session->get_permissions('history_rollback') && $last_rollback_id )
           $html .= ' (<a href="#rollback:' . $last_rollback_id . '" onclick="ajaxRollback(\''.$last_rollback_id.'\'); return false;">' . $lang->get('onpage_filebox_btn_revert') . '</a>) ';
         else if ( $session->get_permissions('history_rollback') && !$last_rollback_id )
@@ -174,5 +191,77 @@
     $html .= '</div><br />';
     return $html;
   }
+  
+  /**
+   * Delete a file from the database and filesystem based on file ID.
+   * @param int File ID
+   * @return null
+   */
+  
+  public static function delete_file($file_id)
+  {
+    global $db, $session, $paths, $template, $plugins; // Common objects
+    
+    if ( !is_int($file_id) )
+      // seriously?
+      return null;
+    
+    // pull file info
+    $q = $db->sql_query('SELECT filename, page_id, time_id, file_extension, file_key FROM ' . table_prefix . "files WHERE file_id = $file_id;");
+    if ( !$q )
+      $db->_die();
+    
+    if ( $db->numrows() < 1 )
+    {
+      $db->free_result();
+      return null;
+    }
+    
+    $row = $db->fetchrow();
+    $db->free_result();
+    
+    // make sure the image isn't used by multiple revisions
+    $q = $db->sql_query('SELECT 1 FROM ' . table_prefix . "files WHERE file_key = '{$row['file_key']}';");
+    if ( !$q )
+      $db->_die();
+    if ( $db->numrows() < 1 )
+    {
+      // remove from filesystem
+      $file_path = ENANO_ROOT . "/files/{$row['file_key']}{$row['file_extension']}";
+      @unlink($file_path);
+      // old filename standard
+      $file_path = ENANO_ROOT . "/files/{$row['file_key']}-{$row['time_id']}{$row['file_extension']}";
+      @unlink($file_path);
+    }
+    $db->free_result();
+    
+    // remove from cache
+    if ( $dp = @opendir(ENANO_ROOT . '/cache/') )
+    {
+      $regexp = '#' . preg_quote($row['filename']) . '-' . $row['time_id'] . '-[0-9]+x[0-9]+' . preg_quote($row['file_extension']) . '#';
+      while ( $dh = @readdir($dp) )
+      {
+        if ( preg_match($regexp, $dh) )
+        {
+          // it's a match, delete the cached thumbnail
+          @unlink(ENANO_ROOT . "/cache/$dh");
+        }
+      }
+      closedir($dp);
+    }
+    
+    // remove from database
+    $q = $db->sql_query('DELETE FROM ' . table_prefix . "files WHERE file_id = $file_id;");
+    if ( !$q )
+      $db->_die();
+    
+    // remove from logs
+    $page_id_db = $db->escape($row['page_id']);
+    $q = $db->sql_query('DELETE FROM ' . table_prefix . "logs WHERE page_id = '{$page_id_db}' AND namespace = 'File' AND action = 'reupload' AND time_id = {$row['time_id']};");
+    if ( !$q )
+      $db->_die();
+    
+    return true;
+  }
 }
 
--- a/includes/pageutils.php	Sat Sep 12 09:56:39 2009 -0400
+++ b/includes/pageutils.php	Tue Sep 15 14:37:03 2009 -0400
@@ -998,21 +998,50 @@
     {
       return $lang->get('etc_access_denied_need_reauth');
     }
-    $e = $db->sql_query('DELETE FROM ' . table_prefix.'logs WHERE page_id=\'' . $db->escape($page_id) . '\' AND namespace=\'' . $db->escape($namespace) . '\';');
-    if(!$e) $db->_die('The log entries could not be deleted.');
+    
+    $page_id_db = $db->escape($page_id);
+    $namespace_db = $db->escape($namespace);
+    
+    // If we're flushing a file, also clear all revisions before the current
+    if ( $namespace == 'File' )
+    {
+      $q = $db->sql_query('SELECT file_id FROM ' . table_prefix . "files WHERE page_id='$page_id_db' ORDER BY time_id DESC;");
+      if ( !$q )
+        $db->_die();
+      // discard first row (current revision)
+      $db->fetchrow();
+      $id_list = array();
+      while ( $row = $db->fetchrow() )
+        $id_list[] = $row['file_id'];
+      
+      require_once(ENANO_ROOT . '/includes/namespaces/file.php');
+      
+      // clear out each file
+      foreach ( $id_list as $id )
+        Namespace_File::delete_file($id);
+    }
+    
+    $q = $db->sql_query('DELETE FROM ' . table_prefix . "logs WHERE page_id='$page_id_db' AND namespace='$namespace';");
+    if ( !$q )
+      $db->_die('The log entries could not be deleted.');
     
     // If the page exists, make a backup of it in case it gets spammed/vandalized
     // If not, the admin's probably deleting a trash page
     if ( isPage($paths->get_pathskey($page_id, $namespace)) )
     {
-      $e = $db->sql_query('SELECT page_text,char_tag FROM ' . table_prefix.'page_text WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';');
-      if(!$e) $db->_die('The current page text could not be selected; as a result, creating the backup of the page failed. Please make a backup copy of the page by clicking Edit this page and then clicking Save Changes.');
+      $q = $db->sql_query('SELECT page_text,char_tag FROM ' . table_prefix . "page_text WHERE page_id='$page_id_db' AND namespace='$namespace_db';");
+      if ( !$q )
+        $db->_die('The current page text could not be selected; as a result, creating the backup of the page failed. Please make a backup copy of the page by clicking Edit this page and then clicking Save Changes.');
       $row = $db->fetchrow();
       $db->free_result();
       $minor_edit = ( ENANO_DBLAYER == 'MYSQL' ) ? 'false' : '0';
-      $q='INSERT INTO ' . table_prefix.'logs(log_type,action,time_id,date_string,page_id,namespace,page_text,char_tag,author,edit_summary,minor_edit) VALUES(\'page\', \'edit\', '.time().', \''.enano_date(ED_DATE | ED_TIME).'\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $db->escape($row['page_text']) . '\', \'' . $row['char_tag'] . '\', \'' . $session->username . '\', \''."Automatic backup created when logs were purged".'\', '.$minor_edit.');';
-      if(!$db->sql_query($q)) $db->_die('The history (log) entry could not be inserted into the logs table.');
+      $username = $db->escape($session->username);
+      $q = 'INSERT INTO ' . table_prefix . "logs ( log_type, action, time_id, date_string, page_id, namespace, page_text, char_tag, author, edit_summary, minor_edit ) VALUES\n"
+         . "  ('page', 'edit', " . time() . ", 'DEPRECATED', '$page_id', '$namespace', '" . $db->escape($row['page_text']) . "', '', '{$username}', '" . $lang->get('page_flushlogs_backup_summary') . "', $minor_edit);";
+      if ( !$db->sql_query($q) )
+        $db->_die('The history (log) entry could not be inserted into the logs table.');
     }
+    
     return $lang->get('ajax_clearlogs_success');
   }
   
--- a/language/english/core.json	Sat Sep 12 09:56:39 2009 -0400
+++ b/language/english/core.json	Tue Sep 15 14:37:03 2009 -0400
@@ -79,6 +79,7 @@
       
       flushlogs_warning_stern: '<h3>You are about to <span style="color: red;">destroy</span> all logged edits and actions on this page.</h3><p>Unlike deleting or editing this page, this action is <u>not reversible</u>! You should only do this if you are desparate for database space.</p><p>Do you really want to continue?</p>',
       flushlogs_btn_submit: 'Flush logs',
+      flushlogs_backup_summary: 'Automatic backup created when logs were purged',
       
       delvote_warning_stern: '<h3>Your vote counts.</h3><p>If you think that this page is not relavent to the content on this site, or if it looks like this page was only created in an attempt to spam the site, you can request that this page be deleted by an administrator.</p><p>After you vote, you should leave a comment explaining the reason for your vote, especially if you are the first person to vote against this page.</p>',