Merging Nighthawk and Scribus branches
authorDan
Mon, 18 Feb 2008 16:14:22 -0500
changeset 427 e7ad98914d06
parent 425 fa51b1b5eae6 (current diff)
parent 426 f5718d7c2a6a (diff)
child 428 921bae9104b0
Merging Nighthawk and Scribus branches
--- a/includes/clientside/static/misc.js	Mon Feb 18 16:13:56 2008 -0500
+++ b/includes/clientside/static/misc.js	Mon Feb 18 16:14:22 2008 -0500
@@ -872,3 +872,80 @@
   }
   return myWidth;
 }
+
+/**
+ * Sanitizes a page URL string so that it can safely be stored in the database.
+ * @param string Page ID to sanitize
+ * @return string Cleaned text
+ */
+
+function sanitize_page_id(page_id)
+{
+  // Remove character escapes
+  page_id = dirtify_page_id(page_id);
+
+  var regex = new RegExp('[A-Za-z0-9\\[\\]\./:;\(\)@_-]', 'g');
+  pid_clean = page_id.replace(regex, 'X');
+  var pid_dirty = [];
+  for ( var i = 0; i < pid_clean.length; i++ )
+    pid_dirty[i] = pid_clean.substr(i, 1);
+
+  for ( var i = 0; i < pid_dirty.length; i++ )
+  {
+    var char = pid_dirty[i];
+    if ( char == 'X' )
+      continue;
+    var cid = char.charCodeAt(0);
+    cid = cid.toString(16).toUpperCase();
+    if ( cid.length < 2 )
+    {
+      cid = '0' + cid;
+    }
+    pid_dirty[i] = "." + cid;
+  }
+  
+  var pid_chars = [];
+  for ( var i = 0; i < page_id.length; i++ )
+    pid_chars[i] = page_id.substr(i, 1);
+  
+  var page_id_cleaned = '';
+
+  for ( var id in pid_chars )
+  {
+    var char = pid_chars[id];
+    if ( pid_dirty[id] == 'X' )
+      page_id_cleaned += char;
+    else
+      page_id_cleaned += pid_dirty[id];
+  }
+  
+  return page_id_cleaned;
+}
+
+/**
+ * Removes character escapes in a page ID string
+ * @param string Page ID string to dirty up
+ * @return string
+ */
+
+function dirtify_page_id(page_id)
+{
+  // First, replace spaces with underscores
+  page_id = page_id.replace(/ /g, '_');
+
+  var matches = page_id.match(/\.[A-Fa-f0-9][A-Fa-f0-9]/g);
+  
+  if ( matches != null )
+  {
+    for ( var i = 0; i < matches.length; i++ )
+    {
+      var match = matches[i];
+      var byt = (match.substr(1)).toUpperCase();
+      var code = eval("0x" + byt);
+      var regex = new RegExp('\\.' + byt, 'g');
+      page_id = page_id.replace(regex, String.fromCharCode(code));
+    }
+  }
+  
+  return page_id;
+}
--- a/includes/pageprocess.php	Mon Feb 18 16:13:56 2008 -0500
+++ b/includes/pageprocess.php	Mon Feb 18 16:14:22 2008 -0500
@@ -471,24 +471,26 @@
   
   /**
    * Creates the page if it doesn't already exist.
+   * @param string Optional page title.
    * @return bool True on success, false on failure.
    */
   
-  function create_page()
+  function create_page($title = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     
     // Do we have permission to create the page?
     if ( !$this->perms->get_permissions('create_page') )
     {
-      $this->raise_error('You do not have permission to create this page.');
+      $this->raise_error($lang->get('pagetools_create_err_no_permission'));
       return false;
     }
     
     // Does it already exist?
     if ( $this->page_exists )
     {
-      $this->raise_error('The page already exists.');
+      $this->raise_error($lang->get('pagetools_create_err_already_exists'));
       return false;
     }
     
@@ -497,17 +499,17 @@
     // We can't create special, admin, or external pages.
     if ( $this->namespace == 'Special' || $this->namespace == 'Admin' || $this->namespace == 'Anonymous' )
     {
-      $this->raise_error('You cannot create Special or Admin pages - they can\'t be stored in the database.');
+      $this->raise_error($lang->get('pagetools_create_err_nodb_namespace'));
       return false;
     }
     
     // Guess the proper title
-    $name = dirtify_page_id($this->page_id);
+    $name = ( !empty($title) ) ? $title : dirtify_page_id($this->page_id);
     
     // Check for the restricted Project: prefix
     if ( substr($this->page_id, 0, 8) == 'Project:' )
     {
-      $this->raise_error('The prefix "Project:" is reserved for internal links and can\'t be used on a page name.');
+      $this->raise_error($lang->get('pagetools_create_err_reserved_prefix'));
       return false;
     }
     
@@ -546,6 +548,13 @@
     if ( !$q )
       $db->_die('PageProcessor page creation - text stage');
     
+    // Query 3: Log entry
+    $db->sql_query('INSERT INTO ' . table_prefix."logs(time_id, date_string, log_type, action, author, page_id, namespace)\n"
+                   . "  VALUES ( " . time() . ", '" . enano_date('d M Y h:i a') . "', 'page', 'create', \n"
+                   . "          '" . $db->escape($session->username) . "', '" . $db->escape($this->page_id) . "', '" . $this->namespace . "');");
+    if ( !$q )
+      $db->_die('PageProcessor page creation - logging stage');
+    
     // Page created. We're good!
     return true;
   }
@@ -575,11 +584,13 @@
     }
     
     // Does the page "exist"?
+    $pathskey = $paths->nslist[$namespace] . $page_id_cleaned;
+    
     if ( $paths->page_id == $page_id && $paths->namespace == $namespace && !$paths->page_exists && ( $this->namespace != 'Admin' || ($this->namespace == 'Admin' && !function_exists($fname) ) ) )
     {
       $this->page_exists = false;
     }
-    else if ( !isset( $paths->pages[ $paths->nslist[$namespace] . $page_id ] ) && ( $this->namespace == 'Admin' && !function_exists($fname) ) )
+    else if ( !isset( $paths->pages[ $pathskey ] ) && ( ( $this->namespace == 'Admin' && !function_exists($fname) ) || ( $this->namespace != 'Admin' ) ) )
     {
       $this->page_exists = false;
     }
--- a/language/english/tools.json	Mon Feb 18 16:13:56 2008 -0500
+++ b/language/english/tools.json	Mon Feb 18 16:14:22 2008 -0500
@@ -88,14 +88,23 @@
     pagetools: {
       
       // Create a page
-      create_err_title: 'The page could not be created.',
-      create_err_name_invalid: 'The name "%page_name%" is invalid.',
-      create_err_project_shortcut: 'The page title can\'t start with "Project:" because this prefix is reserved for a parser shortcut.',
-      create_err_already_exist: 'The page already exists.',
+      create_err_invalid_namespace: 'You have selected an invalid page type.',
+      create_err_invalid_urlname: 'Please enter a title for your page and a custom URL if desired.',
+      create_err_already_exists: 'A page with that URL already exists. Please enter another title or enter a custom URL. (You can have two pages with the same name, but not two pages with the same URL.)',
+      create_err_no_permission: 'You don\'t have permission to create this page. Try another URL or title; if that does not work, please contact the site administration for permission to create pages.',
+      create_err_nodb_namespace: 'You cannot create Special or Admin pages - they can\'t be stored in the database.',
+      create_err_reserved_prefix: 'The prefix "Project:" is reserved for internal links and can\'t be used on a page name.',
       
-      create_blurb: 'Using the form below you can create a page.',
-      create_namespace_none: '[No prefix]',
-      create_btn_create: 'Create Page',
+      create_blurb: 'Add a new page to the site.',
+      create_field_title: 'Page title:',
+      create_field_namespace: 'Page type:',
+      create_group_advanced: 'Advanced options',
+      create_field_url_auto: 'Generate a URL based on the title',
+      create_field_url_manual: 'Enter a custom page URL',
+      create_field_url: 'Page ID:',
+      create_field_preview: 'Preview of URL:',
+      create_field_preview_hint: '(Requires Javascript support)',
+      create_btn_create: 'Create page',
       
       // All pages
       allpages_blurb: 'Below is a list of all of the pages on this website.',
--- a/plugins/SpecialPageFuncs.php	Mon Feb 18 16:13:56 2008 -0500
+++ b/plugins/SpecialPageFuncs.php	Mon Feb 18 16:14:22 2008 -0500
@@ -10,7 +10,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.1
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -74,6 +74,183 @@
   global $db, $session, $paths, $template, $plugins; // Common objects
   global $lang;
   
+  $whitelist_ns = array('Article', 'User', 'Help', 'Template', 'Category', 'Project');
+  $code = $plugins->setHook('page_create_ns_whitelist');
+  foreach ( $code as $cmd )
+  {
+    eval($cmd);
+  }
+  
+  $errors = array();
+  
+  switch ( isset($_POST['page_title']) )
+  {
+    case true:
+      // "Create page" was clicked
+      
+      //
+      // VALIDATION CODE
+      //
+      
+      // Check namespace
+      $namespace = ( isset($_POST['namespace']) ) ? $_POST['namespace'] : 'Article';
+      if ( !in_array($namespace, $whitelist_ns) )
+      {
+        $errors[] = $lang->get('pagetools_create_err_invalid_namespace');
+      }
+      
+      // Check title and figure out urlname
+      $title = $_POST['page_title'];
+      $urlname = $_POST['page_title'];
+      if ( @$_POST['custom_url'] === 'yes' && isset($_POST['urlname']) )
+      {
+        $urlname = $_POST['urlname'];
+      }
+      $urlname = sanitize_page_id($urlname);
+      if ( $urlname == '.00' || empty($urlname) )
+      {
+        $errors[] = $lang->get('pagetools_create_err_invalid_urlname');
+      }
+      
+      // Validate page existence
+      $pathskey = $paths->nslist[$namespace] . $urlname;
+      if ( isPage($pathskey) )
+      {
+        $errors[] = $lang->get('pagetools_create_err_already_exists');
+      }
+      
+      // Validate permissions
+      $perms = $session->fetch_page_acl($urlname, $namespace);
+      if ( !$perms->get_permissions('create_page') )
+      {
+        $errors[] = $lang->get('pagetools_create_err_no_permission');
+      }
+      
+      // Run hooks
+      $code = $plugins->setHook('page_create_request');
+      foreach ( $code as $cmd )
+      {
+        eval($cmd);
+      }
+      
+      // Create the page
+      if ( count($errors) < 1 )
+      {
+        $page = new PageProcessor($urlname, $namespace);
+        $page->create_page($title);
+        if ( $error = $page->pop_error() )
+        {
+          do
+          {
+            $errors[] = $error;
+          }
+          while ( $error = $page->pop_error() );
+        }
+        else
+        {
+          redirect(makeUrlNS($namespace, $urlname) . '#do:edit', '', '', 0);
+          return true;
+        }
+      }
+      
+      break;
+  }
+  
+  $template->header();
+  
+  echo $lang->get('pagetools_create_blurb');
+  
+  if ( count($errors) > 0 )
+  {
+    echo '<div class="error-box">' . implode("<br />\n        ", $errors) . '</div>';
+  }
+  
+  ?>
+  <enano:no-opt>
+  <script type="text/javascript">
+    function cpGenPreviewUrl()
+    {
+      var frm = document.forms['create_form'];
+      var radio_custom = frm.getElementsByTagName('input')[2];
+      var use_custom_url = radio_custom.checked;
+      if ( use_custom_url )
+      {
+        var title_src = frm.urlname.value;
+      }
+      else
+      {
+        var title_src = frm.page_title.value;
+      }
+      var url = window.location.protocol + '//' + window.location.hostname + contentPath + namespace_list[frm.namespace.value] + sanitize_page_id(title_src);
+      document.getElementById('createpage_url_preview').firstChild.nodeValue = url;
+    }
+  </script>
+  </enano:no-opt>
+  <?php
+  
+  echo '<form action="' . makeUrlNS('Special', 'CreatePage') . '" method="post" name="create_form">';
+  
+  echo '<p>';
+    echo $lang->get('pagetools_create_field_title');
+    echo ' <input onkeyup="cpGenPreviewUrl();" type="text" name="page_title" size="40" tabindex="1" />';
+    echo '</p>';
+    
+  echo '<p>';
+    echo $lang->get('pagetools_create_field_namespace');
+    echo ' <select onchange="cpGenPreviewUrl();" name="namespace" tabindex="2">';
+    foreach ( $paths->nslist as $ns => $ns_prefix )
+    {
+      if ( !in_array($ns, $whitelist_ns) )
+        continue;
+      $lang_string = 'onpage_lbl_page_' . strtolower($ns);
+      $str = $lang->get($lang_string);
+      if ( $str == $lang_string )
+        $str = $ns;
+      
+      echo '<option value="' . $ns . '">' . ucwords($str) . '</option>';
+    }
+    echo '</select>';
+    echo '</p>';
+    
+  echo '<fieldset>';
+  echo '<legend>' . $lang->get('pagetools_create_group_advanced') . '</legend>';
+  
+  echo '<p>';
+    echo '<label><input tabindex="3" type="radio" name="custom_url" value="no" checked="checked" onclick="cpGenPreviewUrl(); document.getElementById(\'createpage_custom_url\').style.display = \'none\';" /> ' . $lang->get('pagetools_create_field_url_auto') . '</label>';
+    echo '</p>';
+  
+  echo '<p>';
+    echo '<label><input tabindex="3" type="radio" name="custom_url" value="yes" onclick="cpGenPreviewUrl(); document.getElementById(\'createpage_custom_url\').style.display = \'block\';" /> ' . $lang->get('pagetools_create_field_url_manual') . '</label>';
+    echo '</p>';
+  
+  echo '<p id="createpage_custom_url" style="display: none; margin-left: 2em;">';
+    echo $lang->get('pagetools_create_field_url');
+    echo ' <input onkeyup="cpGenPreviewUrl();" tabindex="4" type="text" name="urlname" value="" size="40" />';
+    echo '</p>';
+    
+  echo '<p>';
+    echo $lang->get('pagetools_create_field_preview') . ' <tt id="createpage_url_preview"> </tt><br />';
+    echo '<small>' . $lang->get('pagetools_create_field_preview_hint') . '</small>';
+    echo '</p>';
+  
+  echo '</fieldset>';
+  
+  echo '<p>';
+    echo '<input tabindex="5" type="submit" value="' . $lang->get('pagetools_create_btn_create') . '" />';
+    echo '</p>';
+    
+  echo '</form>';
+  
+  echo '<script type="text/javascript">cpGenPreviewUrl();</script>';
+  
+  $template->footer();
+}
+
+function page_Special_CreatePage_Old()
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
   if ( isset($_POST['do']) )
   {
     $p = $_POST['pagename'];