index.php
changeset 1103 90225c988124
parent 1082 d1c41601ef39
child 1149 be4feea8872a
equal deleted inserted replaced
1102:faef5e62e1e0 1103:90225c988124
     1 <?php
     1 <?php
     2 
     2 
     3 /*
     3 /*
     4  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
     4  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
     5  * Version 1.1.6 (Caoineag beta 1)
     5  * Copyright (C) 2006-2009 Dan Fuhry
     6  * Copyright (C) 2006-2008 Dan Fuhry
       
     7  *
     6  *
     8  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
     7  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
     9  * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
     8  * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
    10  *
     9  *
    11  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
    10  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
    13  *
    12  *
    14  * @package Enano
    13  * @package Enano
    15  * @subpackage Frontend
    14  * @subpackage Frontend
    16  */
    15  */
    17  
    16  
    18   define('ENANO_INTERFACE_INDEX', '');
    17 define('ENANO_INTERFACE_INDEX', '');
    19   
    18 
    20   // start up Enano
    19 // start up Enano
    21   require('includes/common.php');
    20 require('includes/common.php');
    22   
    21 
    23   // decide on HTML compacting
    22 // decide on HTML compacting
    24   $aggressive_optimize_html = !defined('ENANO_DEBUG') && !isset($_GET['nocompress']);
    23 $aggressive_optimize_html = !defined('ENANO_DEBUG') && !isset($_GET['nocompress']);
    25   
    24 
    26   // Set up gzip encoding before any output is sent
    25 // Set up gzip encoding before any output is sent
    27   global $do_gzip;
    26 global $do_gzip;
    28   // FIXME: make this configurable
    27 // FIXME: make this configurable
    29   $do_gzip = !defined('ENANO_DEBUG');
    28 $do_gzip = !defined('ENANO_DEBUG');
    30   
    29 
    31   error_reporting(E_ALL);
    30 error_reporting(E_ALL);
    32   
    31 
    33   if($aggressive_optimize_html || $do_gzip)
    32 if($aggressive_optimize_html || $do_gzip)
    34   {
    33 {
       
    34   ob_start();
       
    35 }
       
    36 
       
    37 global $db, $session, $paths, $template, $plugins; // Common objects
       
    38 $page_timestamp = time();
       
    39 
       
    40 if ( !isset($_GET['do']) )
       
    41 {
       
    42   $_GET['do'] = 'view';
       
    43 }
       
    44 switch($_GET['do'])
       
    45 {
       
    46   default:
       
    47     $code = $plugins->setHook('page_action');
    35     ob_start();
    48     ob_start();
    36   }
    49     foreach ( $code as $cmd )
    37   
    50     {
    38   global $db, $session, $paths, $template, $plugins; // Common objects
    51       eval($cmd);
    39   $page_timestamp = time();
    52     }
    40   
    53     if ( $contents = ob_get_contents() )
    41   if ( !isset($_GET['do']) )
    54     {
    42   {
    55       ob_end_clean();
    43     $_GET['do'] = 'view';
    56       echo $contents;
    44   }
    57     }
    45   switch($_GET['do'])
    58     else
    46   {
    59     {
    47     default:
    60       die_friendly('Invalid action', '<p>The action "'.htmlspecialchars($_GET['do']).'" is not defined. Return to <a href="'.makeUrl($paths->page).'">viewing this page\'s text</a>.</p>');
    48       $code = $plugins->setHook('page_action');
    61     }
    49       ob_start();
    62     break;
    50       foreach ( $code as $cmd )
    63   case 'view':
    51       {
    64     // echo PageUtils::getpage($paths->page, true, ( (isset($_GET['oldid'])) ? $_GET['oldid'] : false ));
    52         eval($cmd);
    65     $rev_id = ( (isset($_GET['oldid'])) ? intval($_GET['oldid']) : 0 );
    53       }
    66     $page = new PageProcessor( $paths->page_id, $paths->namespace, $rev_id );
    54       if ( $contents = ob_get_contents() )
    67     // Feed this PageProcessor to the template processor. This prevents $template from starting another
    55       {
    68     // PageProcessor when we already have one going.
    56         ob_end_clean();
    69     $template->set_page($page);
    57         echo $contents;
    70     $page->send_headers = true;
    58       }
    71     $page->allow_redir = ( !isset($_GET['redirect']) || (isset($_GET['redirect']) && $_GET['redirect'] !== 'no') );
    59       else
    72     $pagepass = ( isset($_REQUEST['pagepass']) ) ? sha1($_REQUEST['pagepass']) : '';
    60       {
    73     $page->password = $pagepass;
    61         die_friendly('Invalid action', '<p>The action "'.htmlspecialchars($_GET['do']).'" is not defined. Return to <a href="'.makeUrl($paths->page).'">viewing this page\'s text</a>.</p>');
    74     $page->send(true);
    62       }
    75     $page_timestamp = $page->revision_time;
    63       break;
    76     break;
    64     case 'view':
    77   case 'comments':
    65       // echo PageUtils::getpage($paths->page, true, ( (isset($_GET['oldid'])) ? $_GET['oldid'] : false ));
    78     $output->header();
    66       $rev_id = ( (isset($_GET['oldid'])) ? intval($_GET['oldid']) : 0 );
    79     require_once(ENANO_ROOT.'/includes/pageutils.php');
    67       $page = new PageProcessor( $paths->page_id, $paths->namespace, $rev_id );
    80     $sub = ( isset ($_GET['sub']) ) ? $_GET['sub'] : false;
    68       // Feed this PageProcessor to the template processor. This prevents $template from starting another
    81     switch($sub)
    69       // PageProcessor when we already have one going.
    82     {
    70       $template->set_page($page);
    83       case 'admin':
    71       $page->send_headers = true;
    84       default:
    72       $page->allow_redir = ( !isset($_GET['redirect']) || (isset($_GET['redirect']) && $_GET['redirect'] !== 'no') );
    85         $act = ( isset ($_GET['action']) ) ? $_GET['action'] : false;
    73       $pagepass = ( isset($_REQUEST['pagepass']) ) ? sha1($_REQUEST['pagepass']) : '';
    86         $id = ( isset ($_GET['id']) ) ? intval($_GET['id']) : -1;
    74       $page->password = $pagepass;
    87         echo PageUtils::comments_html($paths->page_id, $paths->namespace, $act, Array('id'=>$id));
    75       $page->send(true);
       
    76       $page_timestamp = $page->revision_time;
       
    77       break;
       
    78     case 'comments':
       
    79       $output->header();
       
    80       require_once(ENANO_ROOT.'/includes/pageutils.php');
       
    81       $sub = ( isset ($_GET['sub']) ) ? $_GET['sub'] : false;
       
    82       switch($sub)
       
    83       {
       
    84         case 'admin':
       
    85         default:
       
    86           $act = ( isset ($_GET['action']) ) ? $_GET['action'] : false;
       
    87           $id = ( isset ($_GET['id']) ) ? intval($_GET['id']) : -1;
       
    88           echo PageUtils::comments_html($paths->page_id, $paths->namespace, $act, Array('id'=>$id));
       
    89           break;
       
    90         case 'postcomment':
       
    91           if(empty($_POST['name']) ||
       
    92              empty($_POST['subj']) ||
       
    93              empty($_POST['text'])
       
    94              ) { echo 'Invalid request'; break; }
       
    95           $cid = ( isset($_POST['captcha_id']) ) ? $_POST['captcha_id'] : false;
       
    96           $cin = ( isset($_POST['captcha_input']) ) ? $_POST['captcha_input'] : false;
       
    97           
       
    98           require_once('includes/comment.php');
       
    99           $comments = new Comments($paths->page_id, $paths->namespace);
       
   100           
       
   101           $submission = array(
       
   102               'mode' => 'submit',
       
   103               'captcha_id' => $cid,
       
   104               'captcha_code' => $cin,
       
   105               'name' => $_POST['name'],
       
   106               'subj' => $_POST['subj'],
       
   107               'text' => $_POST['text'],
       
   108             );
       
   109           
       
   110           $result = $comments->process_json($submission);
       
   111           if ( $result['mode'] == 'error' )
       
   112           {
       
   113             echo '<div class="error-box">' . htmlspecialchars($result['error']) . '</div>';
       
   114           }
       
   115           else
       
   116           {
       
   117             echo '<div class="info-box">' . $lang->get('comment_msg_comment_posted') . '</div>';
       
   118           }
       
   119           
       
   120           echo PageUtils::comments_html($paths->page_id, $paths->namespace);
       
   121           break;
       
   122         case 'editcomment':
       
   123           if(!isset($_GET['id']) || ( isset($_GET['id']) && !preg_match('#^([0-9]+)$#', $_GET['id']) )) { echo '<p>Invalid comment ID</p>'; break; }
       
   124           $q = $db->sql_query('SELECT subject,comment_data,comment_id FROM '.table_prefix.'comments WHERE comment_id='.$_GET['id']);
       
   125           if(!$q) $db->_die('The comment data could not be selected.');
       
   126           $row = $db->fetchrow();
       
   127           $db->free_result();
       
   128           $row['subject'] = str_replace('\'', '&#039;', $row['subject']);
       
   129           echo '<form action="'.makeUrl($paths->page, 'do=comments&amp;sub=savecomment').'" method="post">';
       
   130           echo "<br /><div class='tblholder'><table border='0' width='100%' cellspacing='1' cellpadding='4'>
       
   131                   <tr><td class='row1'>" . $lang->get('comment_postform_field_subject') . "</td><td class='row1'><input type='text' name='subj' value='{$row['subject']}' /></td></tr>
       
   132                   <tr><td class='row2'>" . $lang->get('comment_postform_field_comment') . "</td><td class='row2'><textarea rows='10' cols='40' style='width: 98%;' name='text'>{$row['comment_data']}</textarea></td></tr>
       
   133                   <tr><td class='row1' colspan='2' class='row1' style='text-align: center;'><input type='hidden' name='id' value='{$row['comment_id']}' /><input type='submit' value='" . $lang->get('etc_save_changes') . "' /></td></tr>
       
   134                 </table></div>";
       
   135           echo '</form>';
       
   136           break;
       
   137         case 'savecomment':
       
   138           if(empty($_POST['subj']) || empty($_POST['text'])) { echo '<p>Invalid request</p>'; break; }
       
   139           $r = PageUtils::savecomment_neater($paths->page_id, $paths->namespace, $_POST['subj'], $_POST['text'], (int)$_POST['id']);
       
   140           if($r != 'good') { echo "<pre>$r</pre>"; break; }
       
   141           echo PageUtils::comments_html($paths->page_id, $paths->namespace);
       
   142           break;
       
   143         case 'deletecomment':
       
   144           if(!empty($_GET['id']))
       
   145           {
       
   146             PageUtils::deletecomment_neater($paths->page_id, $paths->namespace, (int)$_GET['id']);
       
   147           }
       
   148           echo PageUtils::comments_html($paths->page_id, $paths->namespace);
       
   149           break;
       
   150       }
       
   151       $output->footer();
       
   152       break;
       
   153     case 'edit':
       
   154       if(isset($_POST['_cancel']))
       
   155       {
       
   156         redirect(makeUrl($paths->page), '', '', 0);
       
   157         break;
    88         break;
   158       }
    89       case 'postcomment':
   159       require_once(ENANO_ROOT.'/includes/pageutils.php');
    90         if(empty($_POST['name']) ||
   160       if(isset($_POST['_save']))
    91            empty($_POST['subj']) ||
   161       {
    92            empty($_POST['text'])
   162         $captcha_valid = true;
    93            ) { echo 'Invalid request'; break; }
   163         if ( !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' )
    94         $cid = ( isset($_POST['captcha_id']) ) ? $_POST['captcha_id'] : false;
       
    95         $cin = ( isset($_POST['captcha_input']) ) ? $_POST['captcha_input'] : false;
       
    96         
       
    97         require_once('includes/comment.php');
       
    98         $comments = new Comments($paths->page_id, $paths->namespace);
       
    99         
       
   100         $submission = array(
       
   101             'mode' => 'submit',
       
   102             'captcha_id' => $cid,
       
   103             'captcha_code' => $cin,
       
   104             'name' => $_POST['name'],
       
   105             'subj' => $_POST['subj'],
       
   106             'text' => $_POST['text'],
       
   107           );
       
   108         
       
   109         $result = $comments->process_json($submission);
       
   110         if ( $result['mode'] == 'error' )
   164         {
   111         {
   165           $captcha_valid = false;
   112           echo '<div class="error-box">' . htmlspecialchars($result['error']) . '</div>';
   166           if ( isset($_POST['captcha_id']) && isset($_POST['captcha_code']) )
       
   167           {
       
   168             $hash_correct = strtolower($session->get_captcha($_POST['captcha_id']));
       
   169             $hash_input   = strtolower($_POST['captcha_code']);
       
   170             if ( $hash_input === $hash_correct )
       
   171               $captcha_valid = true;
       
   172           }
       
   173         }
       
   174         if ( $captcha_valid )
       
   175         {
       
   176           $e = PageUtils::savepage($paths->page_id, $paths->namespace, $_POST['page_text'], $_POST['edit_summary'], isset($_POST['minor']));
       
   177           if ( $e == 'good' )
       
   178           {
       
   179             redirect(makeUrl($paths->page), $lang->get('editor_msg_save_success_title'), $lang->get('editor_msg_save_success_body'), 3);
       
   180           }
       
   181         }
       
   182       }
       
   183       $template->header();
       
   184       if ( isset($captcha_valid) )
       
   185       {
       
   186         echo '<div class="usermessage">' . $lang->get('editor_err_captcha_wrong') . '</div>';
       
   187       }
       
   188       if(isset($_POST['_preview']))
       
   189       {
       
   190         $text = $_POST['page_text'];
       
   191         $edsumm = $_POST['edit_summary'];
       
   192         echo PageUtils::genPreview($_POST['page_text']);
       
   193         $text = htmlspecialchars($text);
       
   194         $revid = 0;
       
   195       }
       
   196       else
       
   197       {
       
   198         $revid = ( isset($_GET['revid']) ) ? intval($_GET['revid']) : 0;
       
   199         $page = new PageProcessor($paths->page_id, $paths->namespace, $revid);
       
   200         $text = $page->fetch_source();
       
   201         $edsumm = '';
       
   202         // $text = RenderMan::getPage($paths->cpage['urlname_nons'], $paths->namespace, 0, false, false, false, false);
       
   203       }
       
   204       if ( $revid > 0 )
       
   205       {
       
   206         $time = $page->revision_time;
       
   207         // Retrieve information about this revision and the current one
       
   208         $q = $db->sql_query('SELECT l1.author AS currentrev_author, l2.author AS oldrev_author FROM ' . table_prefix . 'logs AS l1
       
   209   LEFT JOIN ' . table_prefix . 'logs AS l2
       
   210     ON ( l2.log_id = ' . $revid . '
       
   211          AND l2.log_type  = \'page\'
       
   212          AND l2.action    = \'edit\'
       
   213          AND l2.page_id   = \'' . $db->escape($paths->page_id) . '\'
       
   214          AND l2.namespace = \'' . $db->escape($paths->namespace) . '\'
       
   215          AND l1.is_draft != 1
       
   216         )
       
   217   WHERE l1.log_type  = \'page\'
       
   218     AND l1.action    = \'edit\'
       
   219     AND l1.page_id   = \'' . $db->escape($paths->page_id) . '\'
       
   220     AND l1.namespace = \'' . $db->escape($paths->namespace) . '\'
       
   221     AND l1.time_id > ' . $time . '
       
   222     AND l1.is_draft != 1
       
   223   ORDER BY l1.time_id DESC;');
       
   224         if ( !$q )
       
   225           $db->die_json();
       
   226         
       
   227         if ( $db->numrows() > 0 )
       
   228         {
       
   229           echo '<div class="usermessage">' . $lang->get('editor_msg_editing_old_revision') . '</div>';
       
   230           
       
   231           $rev_count = $db->numrows() - 2;
       
   232           $row = $db->fetchrow();
       
   233           $undo_info = array(
       
   234             'old_author'     => $row['oldrev_author'],
       
   235             'current_author' => $row['currentrev_author'],
       
   236             'undo_count'     => max($rev_count, 1),
       
   237             'last_rev_id'    => $revid
       
   238           );
       
   239         }
   113         }
   240         else
   114         else
   241         {
   115         {
   242           $revid = 0;
   116           echo '<div class="info-box">' . $lang->get('comment_msg_comment_posted') . '</div>';
   243         }
   117         }
       
   118         
       
   119         echo PageUtils::comments_html($paths->page_id, $paths->namespace);
       
   120         break;
       
   121       case 'editcomment':
       
   122         if(!isset($_GET['id']) || ( isset($_GET['id']) && !preg_match('#^([0-9]+)$#', $_GET['id']) )) { echo '<p>Invalid comment ID</p>'; break; }
       
   123         $q = $db->sql_query('SELECT subject,comment_data,comment_id FROM '.table_prefix.'comments WHERE comment_id='.$_GET['id']);
       
   124         if(!$q) $db->_die('The comment data could not be selected.');
       
   125         $row = $db->fetchrow();
   244         $db->free_result();
   126         $db->free_result();
   245       }
   127         $row['subject'] = str_replace('\'', '&#039;', $row['subject']);
   246       echo '
   128         echo '<form action="'.makeUrl($paths->page, 'do=comments&amp;sub=savecomment').'" method="post">';
   247         <form action="'.makeUrl($paths->page, 'do=edit').'" method="post" enctype="multipart/form-data">
   129         echo "<br /><div class='tblholder'><table border='0' width='100%' cellspacing='1' cellpadding='4'>
   248         <br />
   130                 <tr><td class='row1'>" . $lang->get('comment_postform_field_subject') . "</td><td class='row1'><input type='text' name='subj' value='{$row['subject']}' /></td></tr>
   249         <textarea name="page_text" rows="20" cols="60" style="width: 97%;">'.$text.'</textarea><br />
   131                 <tr><td class='row2'>" . $lang->get('comment_postform_field_comment') . "</td><td class='row2'><textarea rows='10' cols='40' style='width: 98%;' name='text'>{$row['comment_data']}</textarea></td></tr>
   250         <br />
   132                 <tr><td class='row1' colspan='2' class='row1' style='text-align: center;'><input type='hidden' name='id' value='{$row['comment_id']}' /><input type='submit' value='" . $lang->get('etc_save_changes') . "' /></td></tr>
   251         ';
   133               </table></div>";
   252       $edsumm = ( $revid > 0 ) ? $lang->get('editor_reversion_edit_summary', $undo_info) : $edsumm;
   134         echo '</form>';
   253       echo $lang->get('editor_lbl_edit_summary') . ' <input name="edit_summary" type="text" size="40" value="' . htmlspecialchars($edsumm) . '" /><br /><label><input type="checkbox" name="minor" /> ' . $lang->get('editor_lbl_minor_edit_field') . '</label><br />';
   135         break;
       
   136       case 'savecomment':
       
   137         if(empty($_POST['subj']) || empty($_POST['text'])) { echo '<p>Invalid request</p>'; break; }
       
   138         $r = PageUtils::savecomment_neater($paths->page_id, $paths->namespace, $_POST['subj'], $_POST['text'], (int)$_POST['id']);
       
   139         if($r != 'good') { echo "<pre>$r</pre>"; break; }
       
   140         echo PageUtils::comments_html($paths->page_id, $paths->namespace);
       
   141         break;
       
   142       case 'deletecomment':
       
   143         if(!empty($_GET['id']))
       
   144         {
       
   145           PageUtils::deletecomment_neater($paths->page_id, $paths->namespace, (int)$_GET['id']);
       
   146         }
       
   147         echo PageUtils::comments_html($paths->page_id, $paths->namespace);
       
   148         break;
       
   149     }
       
   150     $output->footer();
       
   151     break;
       
   152   case 'edit':
       
   153     if(isset($_POST['_cancel']))
       
   154     {
       
   155       redirect(makeUrl($paths->page), '', '', 0);
       
   156       break;
       
   157     }
       
   158     require_once(ENANO_ROOT.'/includes/pageutils.php');
       
   159     if(isset($_POST['_save']))
       
   160     {
       
   161       $captcha_valid = true;
   254       if ( !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' )
   162       if ( !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' )
   255       {
   163       {
   256         echo '<br /><table border="0"><tr><td>';
   164         $captcha_valid = false;
   257         echo '<b>' . $lang->get('editor_lbl_field_captcha') . '</b><br />'
   165         if ( isset($_POST['captcha_id']) && isset($_POST['captcha_code']) )
   258              . '<br />'
   166         {
   259              . $lang->get('editor_msg_captcha_pleaseenter') . '<br /><br />'
   167           $hash_correct = strtolower($session->get_captcha($_POST['captcha_id']));
   260              . $lang->get('editor_msg_captcha_blind');
   168           $hash_input   = strtolower($_POST['captcha_code']);
   261         echo '</td><td>';
   169           if ( $hash_input === $hash_correct )
   262         $hash = $session->make_captcha();
   170             $captcha_valid = true;
   263         echo '<img src="' . makeUrlNS('Special', "Captcha/$hash") . '" onclick="this.src+=\'/a\'" style="cursor: pointer;" /><br />';
   171         }
   264         echo '<input type="hidden" name="captcha_id" value="' . $hash . '" />';
   172       }
   265         echo $lang->get('editor_lbl_field_captcha_code') . ' <input type="text" name="captcha_code" value="" size="9" />';
   173       if ( $captcha_valid )
   266         echo '</td></tr></table>';
   174       {
   267       }
   175         $e = PageUtils::savepage($paths->page_id, $paths->namespace, $_POST['page_text'], $_POST['edit_summary'], isset($_POST['minor']));
   268       echo '<br />
   176         if ( $e == 'good' )
   269           <input type="submit" name="_save"    value="' . $lang->get('editor_btn_save') . '" style="font-weight: bold;" />
   177         {
   270           <input type="submit" name="_preview" value="' . $lang->get('editor_btn_preview') . '" />
   178           redirect(makeUrl($paths->page), $lang->get('editor_msg_save_success_title'), $lang->get('editor_msg_save_success_body'), 3);
   271           <input type="submit" name="_revert"  value="' . $lang->get('editor_btn_revert') . '" />
   179         }
   272           <input type="submit" name="_cancel"  value="' . $lang->get('editor_btn_cancel') . '" />
   180       }
   273         </form>
   181     }
       
   182     $template->header();
       
   183     if ( isset($captcha_valid) )
       
   184     {
       
   185       echo '<div class="usermessage">' . $lang->get('editor_err_captcha_wrong') . '</div>';
       
   186     }
       
   187     if(isset($_POST['_preview']))
       
   188     {
       
   189       $text = $_POST['page_text'];
       
   190       $edsumm = $_POST['edit_summary'];
       
   191       echo PageUtils::genPreview($_POST['page_text']);
       
   192       $text = htmlspecialchars($text);
       
   193       $revid = 0;
       
   194     }
       
   195     else
       
   196     {
       
   197       $revid = ( isset($_GET['revid']) ) ? intval($_GET['revid']) : 0;
       
   198       $page = new PageProcessor($paths->page_id, $paths->namespace, $revid);
       
   199       $text = $page->fetch_source();
       
   200       $edsumm = '';
       
   201       // $text = RenderMan::getPage($paths->cpage['urlname_nons'], $paths->namespace, 0, false, false, false, false);
       
   202     }
       
   203     if ( $revid > 0 )
       
   204     {
       
   205       $time = $page->revision_time;
       
   206       // Retrieve information about this revision and the current one
       
   207       $q = $db->sql_query('SELECT l1.author AS currentrev_author, l2.author AS oldrev_author FROM ' . table_prefix . 'logs AS l1
       
   208 LEFT JOIN ' . table_prefix . 'logs AS l2
       
   209   ON ( l2.log_id = ' . $revid . '
       
   210        AND l2.log_type  = \'page\'
       
   211        AND l2.action    = \'edit\'
       
   212        AND l2.page_id   = \'' . $db->escape($paths->page_id) . '\'
       
   213        AND l2.namespace = \'' . $db->escape($paths->namespace) . '\'
       
   214        AND l1.is_draft != 1
       
   215       )
       
   216 WHERE l1.log_type  = \'page\'
       
   217   AND l1.action    = \'edit\'
       
   218   AND l1.page_id   = \'' . $db->escape($paths->page_id) . '\'
       
   219   AND l1.namespace = \'' . $db->escape($paths->namespace) . '\'
       
   220   AND l1.time_id > ' . $time . '
       
   221   AND l1.is_draft != 1
       
   222 ORDER BY l1.time_id DESC;');
       
   223       if ( !$q )
       
   224         $db->die_json();
       
   225       
       
   226       if ( $db->numrows() > 0 )
       
   227       {
       
   228         echo '<div class="usermessage">' . $lang->get('editor_msg_editing_old_revision') . '</div>';
       
   229         
       
   230         $rev_count = $db->numrows() - 2;
       
   231         $row = $db->fetchrow();
       
   232         $undo_info = array(
       
   233           'old_author'     => $row['oldrev_author'],
       
   234           'current_author' => $row['currentrev_author'],
       
   235           'undo_count'     => max($rev_count, 1),
       
   236           'last_rev_id'    => $revid
       
   237         );
       
   238       }
       
   239       else
       
   240       {
       
   241         $revid = 0;
       
   242       }
       
   243       $db->free_result();
       
   244     }
       
   245     echo '
       
   246       <form action="'.makeUrl($paths->page, 'do=edit').'" method="post" enctype="multipart/form-data">
       
   247       <br />
       
   248       <textarea name="page_text" rows="20" cols="60" style="width: 97%;">'.$text.'</textarea><br />
       
   249       <br />
   274       ';
   250       ';
   275       if ( getConfig('wiki_edit_notice', '0') == '1' )
   251     $edsumm = ( $revid > 0 ) ? $lang->get('editor_reversion_edit_summary', $undo_info) : $edsumm;
   276       {
   252     echo $lang->get('editor_lbl_edit_summary') . ' <input name="edit_summary" type="text" size="40" value="' . htmlspecialchars($edsumm) . '" /><br /><label><input type="checkbox" name="minor" /> ' . $lang->get('editor_lbl_minor_edit_field') . '</label><br />';
   277         $notice = getConfig('wiki_edit_notice_text');
   253     if ( !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' )
   278         echo RenderMan::render($notice);
   254     {
   279       }
   255       echo '<br /><table border="0"><tr><td>';
       
   256       echo '<b>' . $lang->get('editor_lbl_field_captcha') . '</b><br />'
       
   257            . '<br />'
       
   258            . $lang->get('editor_msg_captcha_pleaseenter') . '<br /><br />'
       
   259            . $lang->get('editor_msg_captcha_blind');
       
   260       echo '</td><td>';
       
   261       $hash = $session->make_captcha();
       
   262       echo '<img src="' . makeUrlNS('Special', "Captcha/$hash") . '" onclick="this.src+=\'/a\'" style="cursor: pointer;" /><br />';
       
   263       echo '<input type="hidden" name="captcha_id" value="' . $hash . '" />';
       
   264       echo $lang->get('editor_lbl_field_captcha_code') . ' <input type="text" name="captcha_code" value="" size="9" />';
       
   265       echo '</td></tr></table>';
       
   266     }
       
   267     echo '<br />
       
   268         <input type="submit" name="_save"    value="' . $lang->get('editor_btn_save') . '" style="font-weight: bold;" />
       
   269         <input type="submit" name="_preview" value="' . $lang->get('editor_btn_preview') . '" />
       
   270         <input type="submit" name="_revert"  value="' . $lang->get('editor_btn_revert') . '" />
       
   271         <input type="submit" name="_cancel"  value="' . $lang->get('editor_btn_cancel') . '" />
       
   272       </form>
       
   273     ';
       
   274     if ( getConfig('wiki_edit_notice', '0') == '1' )
       
   275     {
       
   276       $notice = getConfig('wiki_edit_notice_text');
       
   277       echo RenderMan::render($notice);
       
   278     }
       
   279     $template->footer();
       
   280     break;
       
   281   case 'viewsource':
       
   282     $template->header();
       
   283     $text = RenderMan::getPage($paths->page_id, $paths->namespace, 0, false, false, false, false);
       
   284     $text = htmlspecialchars($text);
       
   285     echo '
       
   286       <form action="'.makeUrl($paths->page, 'do=edit').'" method="post">
       
   287       <br />
       
   288       <textarea readonly="readonly" name="page_text" rows="20" cols="60" style="width: 97%;">'.$text.'</textarea>';
       
   289     echo '<br />
       
   290         <input type="submit" name="_cancel" value="' . $lang->get('editor_btn_closeviewer') . '" />
       
   291       </form>
       
   292     ';
       
   293     $template->footer();
       
   294     break;
       
   295   case 'history':
       
   296     require_once(ENANO_ROOT.'/includes/pageutils.php');
       
   297     $hist = PageUtils::histlist($paths->page_id, $paths->namespace);
       
   298     $template->header();
       
   299     echo $hist;
       
   300     $template->footer();
       
   301     break;
       
   302   case 'rollback':
       
   303     $id = (isset($_GET['id'])) ? $_GET['id'] : false;
       
   304     if(!$id || !ctype_digit($id)) die_friendly('Invalid action ID', '<p>The URL parameter "id" is not an integer. Exiting to prevent nasties like SQL injection, etc.</p>');
       
   305     
       
   306     $id = intval($id);
       
   307     
       
   308     $page = new PageProcessor($paths->page_id, $paths->namespace);
       
   309     $result = $page->rollback_log_entry($id);
       
   310     
       
   311     if ( $result['success'] )
       
   312     {
       
   313       $result = $lang->get("page_msg_rb_success_{$result['action']}", array('dateline' => $result['dateline']));
       
   314     }
       
   315     else
       
   316     {
       
   317       $result = $lang->get("page_err_{$result['error']}", array('action' => @$result['action']));
       
   318     }
       
   319     
       
   320     $template->header();
       
   321     echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a></p>';
       
   322     $template->footer();
       
   323     break;
       
   324   case 'catedit':
       
   325     require_once(ENANO_ROOT.'/includes/pageutils.php');
       
   326     if(isset($_POST['__enanoSaveButton']))
       
   327     {
       
   328       unset($_POST['__enanoSaveButton']);
       
   329       $val = PageUtils::catsave($paths->page_id, $paths->namespace, $_POST);
       
   330       if($val == 'GOOD')
       
   331       {
       
   332         header('Location: '.makeUrl($paths->page)); echo '<html><head><title>Redirecting...</title></head><body>If you haven\'t been redirected yet, <a href="'.makeUrl($paths->page).'">click here</a>.'; break;
       
   333       } else {
       
   334         die_friendly('Error saving category information', '<p>'.$val.'</p>');
       
   335       }
       
   336     }
       
   337     elseif(isset($_POST['__enanoCatCancel']))
       
   338     {
       
   339       header('Location: '.makeUrl($paths->page)); echo '<html><head><title>Redirecting...</title></head><body>If you haven\'t been redirected yet, <a href="'.makeUrl($paths->page).'">click here</a>.'; break;
       
   340     }
       
   341     $template->header();
       
   342     $c = PageUtils::catedit_raw($paths->page_id, $paths->namespace);
       
   343     echo $c[1];
       
   344     $template->footer();
       
   345     break;
       
   346   case 'moreoptions':
       
   347     $template->header();
       
   348     echo '<div class="menu_nojs" style="width: 150px; padding: 0;"><ul style="display: block;"><li><div class="label">' . $lang->get('ajax_lbl_moreoptions_nojs') . '</div><div style="clear: both;"></div></li>'.$template->toolbar_menu.'</ul></div>';
       
   349     $template->footer();
       
   350     break;
       
   351   case 'protect':
       
   352     if ( !$session->sid_super )
       
   353     {
       
   354       redirect(makeUrlNS('Special', "Login/{$paths->page}", 'target_do=protect&level=' . $session->user_level, false), $lang->get('etc_access_denied_short'), $lang->get('etc_access_denied_need_reauth'), 0);
       
   355     }
       
   356     
       
   357     if ( isset($_POST['level']) && isset($_POST['reason']) )
       
   358     {
       
   359       $level = intval($_POST['level']);
       
   360       if ( !in_array($level, array(PROTECT_FULL, PROTECT_SEMI, PROTECT_NONE)) )
       
   361       {
       
   362         $errors[] = 'bad level';
       
   363       }
       
   364       $reason = trim($_POST['reason']);
       
   365       if ( empty($reason) )
       
   366       {
       
   367         $errors[] = $lang->get('onpage_protect_err_need_reason');
       
   368       }
       
   369       
       
   370       $page = new PageProcessor($paths->page_id, $paths->namespace);
       
   371       $result = $page->protect_page($level, $reason);
       
   372       if ( $result['success'] )
       
   373       {
       
   374         redirect(makeUrl($paths->page), $lang->get('page_protect_lbl_success_title'), $lang->get('page_protect_lbl_success_body', array('page_link' => makeUrl($paths->page, false, true))), 3);
       
   375       }
       
   376       else
       
   377       {
       
   378         $errors[] = $lang->get('page_err_' . $result['error']);
       
   379       }
       
   380     }
       
   381     $template->header();
       
   382     ?>
       
   383     <form action="<?php echo makeUrl($paths->page, 'do=protect'); ?>" method="post">
       
   384       <h3><?php echo $lang->get('onpage_protect_heading'); ?></h3>
       
   385       <p><?php echo $lang->get('onpage_protect_msg_select_level'); ?></p>
       
   386       
       
   387       <?php
       
   388       if ( !empty($errors) )
       
   389       {
       
   390         echo '<ul><li>' . implode('</li><li>', $errors) . '</li></ul>';
       
   391       }
       
   392       ?>
       
   393       
       
   394       <div class="protectlevel" style="line-height: 22px; margin-left: 17px;">
       
   395         <label>
       
   396           <input type="radio" name="level" value="<?php echo PROTECT_FULL; ?>" />
       
   397           <?php echo gen_sprite(cdnPath . '/images/protect-icons.png', 22, 22, 0, 0); ?>
       
   398           <?php echo $lang->get('onpage_protect_btn_full'); ?>
       
   399         </label>
       
   400       </div>
       
   401       <div class="protectlevel_hint" style="font-size: smaller; margin-left: 68px;">
       
   402         <?php echo $lang->get('onpage_protect_btn_full_hint'); ?>
       
   403       </div>
       
   404       
       
   405       <div class="protectlevel" style="line-height: 22px; margin-left: 17px;">
       
   406         <label>
       
   407           <input type="radio" name="level" value="<?php echo PROTECT_SEMI; ?>" />
       
   408           <?php echo gen_sprite(cdnPath . '/images/protect-icons.png', 22, 22, 22, 0); ?>
       
   409           <?php echo $lang->get('onpage_protect_btn_semi'); ?>
       
   410         </label>
       
   411       </div>
       
   412       <div class="protectlevel_hint" style="font-size: smaller; margin-left: 68px;">
       
   413         <?php echo $lang->get('onpage_protect_btn_semi_hint'); ?>
       
   414       </div>
       
   415       
       
   416       <div class="protectlevel" style="line-height: 22px; margin-left: 17px;">
       
   417         <label>
       
   418           <input type="radio" name="level" value="<?php echo PROTECT_NONE; ?>" />
       
   419           <?php echo gen_sprite(cdnPath . '/images/protect-icons.png', 22, 22, 44, 0); ?>
       
   420           <?php echo $lang->get('onpage_protect_btn_none'); ?>
       
   421         </label>
       
   422       </div>
       
   423       <div class="protectlevel_hint" style="font-size: smaller; margin-left: 68px;">
       
   424         <?php echo $lang->get('onpage_protect_btn_none_hint'); ?>
       
   425       </div>
       
   426       
       
   427       <table style="margin-left: 1em;" cellspacing="10">
       
   428         <tr>
       
   429           <td valign="top">
       
   430             <?php echo $lang->get('onpage_protect_lbl_reason'); ?>
       
   431           </td>
       
   432           <td>
       
   433             <input type="text" name="reason" size="40" /><br />
       
   434             <small><?php echo $lang->get('onpage_protect_lbl_reason_hint'); ?></small>
       
   435           </td>
       
   436         </tr>
       
   437       </table>
       
   438                             
       
   439       <p>
       
   440         <input type="submit" value="<?php echo htmlspecialchars($lang->get('page_protect_btn_submit')) ?>" style="font-weight: bold;" />
       
   441         <a class="abutton" href="<?php echo makeUrl($paths->page, false, true); ?>"><?php echo $lang->get('etc_cancel'); ?></a>
       
   442       </p> 
       
   443     </form>
       
   444     <?php
       
   445     $template->footer();
       
   446     break;
       
   447   case 'rename':
       
   448     require_once(ENANO_ROOT.'/includes/pageutils.php');
       
   449     if(!empty($_POST['newname']))
       
   450     {
       
   451       $r = PageUtils::rename($paths->page_id, $paths->namespace, $_POST['newname']);
       
   452       die_friendly($lang->get('page_rename_success_title'), '<p>'.nl2br($r).' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>');
       
   453     }
       
   454     $template->header();
       
   455     ?>
       
   456     <form action="<?php echo makeUrl($paths->page, 'do=rename'); ?>" method="post">
       
   457       <?php if(isset($_POST['newname'])) echo '<p style="color: red;">' . $lang->get('page_rename_err_need_name') . '</p>'; ?>
       
   458       <p><?php echo $lang->get('page_rename_lbl'); ?></p>
       
   459       <p><input type="text" name="newname" size="40" /></p>
       
   460       <p><input type="submit" value="<?php echo htmlspecialchars($lang->get('page_rename_btn_submit')); ?>" style="font-weight: bold;" /></p> 
       
   461     </form>
       
   462     <?php
       
   463     $template->footer();    
       
   464     break;
       
   465   case 'flushlogs':
       
   466     if(!$session->get_permissions('clear_logs'))
       
   467     {
       
   468       die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
       
   469     }
       
   470     if ( !$session->sid_super )
       
   471     {
       
   472       redirect(makeUrlNS('Special', "Login/{$paths->page}", 'target_do=flushlogs&level=' . $session->user_level, false), $lang->get('etc_access_denied_short'), $lang->get('etc_access_denied_need_reauth'), 0);
       
   473     }
       
   474     require_once(ENANO_ROOT.'/includes/pageutils.php');
       
   475     if(isset($_POST['_downthejohn']))
       
   476     {
       
   477       $template->header();
       
   478         $result = PageUtils::flushlogs($paths->page_id, $paths->namespace);
       
   479         echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>';
   280       $template->footer();
   480       $template->footer();
   281       break;
   481       break;
   282     case 'viewsource':
   482     }
       
   483     $template->header();
       
   484       ?>
       
   485       <form action="<?php echo makeUrl($paths->page, 'do=flushlogs'); ?>" method="post">
       
   486          <?php echo $lang->get('page_flushlogs_warning_stern'); ?>
       
   487          <p><input type="submit" name="_downthejohn" value="<?php echo htmlspecialchars($lang->get('page_flushlogs_btn_submit')); ?>" style="color: red; font-weight: bold;" /></p>
       
   488       </form>
       
   489       <?php
       
   490     $template->footer();
       
   491     break;
       
   492   case 'delvote':
       
   493     require_once(ENANO_ROOT.'/includes/pageutils.php');
       
   494     if(isset($_POST['_ballotbox']))
       
   495     {
   283       $template->header();
   496       $template->header();
   284       $text = RenderMan::getPage($paths->page_id, $paths->namespace, 0, false, false, false, false);
   497       $result = PageUtils::delvote($paths->page_id, $paths->namespace);
   285       $text = htmlspecialchars($text);
   498       echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>';
   286       echo '
       
   287         <form action="'.makeUrl($paths->page, 'do=edit').'" method="post">
       
   288         <br />
       
   289         <textarea readonly="readonly" name="page_text" rows="20" cols="60" style="width: 97%;">'.$text.'</textarea>';
       
   290       echo '<br />
       
   291           <input type="submit" name="_cancel" value="' . $lang->get('editor_btn_closeviewer') . '" />
       
   292         </form>
       
   293       ';
       
   294       $template->footer();
   499       $template->footer();
   295       break;
   500       break;
   296     case 'history':
   501     }
   297       require_once(ENANO_ROOT.'/includes/pageutils.php');
   502     $template->header();
   298       $hist = PageUtils::histlist($paths->page_id, $paths->namespace);
   503       ?>
       
   504       <form action="<?php echo makeUrl($paths->page, 'do=delvote'); ?>" method="post">
       
   505          <?php
       
   506            echo $lang->get('page_delvote_warning_stern');
       
   507            echo '<p>';
       
   508            switch($paths->cpage['delvotes'])
       
   509            {
       
   510              case 0:  echo $lang->get('page_delvote_count_zero'); break;
       
   511              case 1:  echo $lang->get('page_delvote_count_one'); break;
       
   512              default: echo $lang->get('page_delvote_count_plural', array('delvotes' => $paths->cpage['delvotes'])); break;
       
   513            }
       
   514            echo '</p>';
       
   515          ?>
       
   516          <p><input type="submit" name="_ballotbox" value="<?php echo htmlspecialchars($lang->get('page_delvote_btn_submit')); ?>" /></p>
       
   517       </form>
       
   518       <?php
       
   519     $template->footer();
       
   520     break;
       
   521   case 'resetvotes':
       
   522     require_once(ENANO_ROOT.'/includes/pageutils.php');
       
   523     if(!$session->get_permissions('vote_reset'))
       
   524     {
       
   525       die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
       
   526     }
       
   527     if(isset($_POST['_youmaylivealittlelonger']))
       
   528     {
   299       $template->header();
   529       $template->header();
   300       echo $hist;
   530         $result = PageUtils::resetdelvotes($paths->page_id, $paths->namespace);
       
   531         echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>';
   301       $template->footer();
   532       $template->footer();
   302       break;
   533       break;
   303     case 'rollback':
   534     }
   304       $id = (isset($_GET['id'])) ? $_GET['id'] : false;
   535     $template->header();
   305       if(!$id || !ctype_digit($id)) die_friendly('Invalid action ID', '<p>The URL parameter "id" is not an integer. Exiting to prevent nasties like SQL injection, etc.</p>');
       
   306       
       
   307       $id = intval($id);
       
   308       
       
   309       $page = new PageProcessor($paths->page_id, $paths->namespace);
       
   310       $result = $page->rollback_log_entry($id);
       
   311       
       
   312       if ( $result['success'] )
       
   313       {
       
   314         $result = $lang->get("page_msg_rb_success_{$result['action']}", array('dateline' => $result['dateline']));
       
   315       }
       
   316       else
       
   317       {
       
   318         $result = $lang->get("page_err_{$result['error']}", array('action' => @$result['action']));
       
   319       }
       
   320       
       
   321       $template->header();
       
   322       echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a></p>';
       
   323       $template->footer();
       
   324       break;
       
   325     case 'catedit':
       
   326       require_once(ENANO_ROOT.'/includes/pageutils.php');
       
   327       if(isset($_POST['__enanoSaveButton']))
       
   328       {
       
   329         unset($_POST['__enanoSaveButton']);
       
   330         $val = PageUtils::catsave($paths->page_id, $paths->namespace, $_POST);
       
   331         if($val == 'GOOD')
       
   332         {
       
   333           header('Location: '.makeUrl($paths->page)); echo '<html><head><title>Redirecting...</title></head><body>If you haven\'t been redirected yet, <a href="'.makeUrl($paths->page).'">click here</a>.'; break;
       
   334         } else {
       
   335           die_friendly('Error saving category information', '<p>'.$val.'</p>');
       
   336         }
       
   337       }
       
   338       elseif(isset($_POST['__enanoCatCancel']))
       
   339       {
       
   340         header('Location: '.makeUrl($paths->page)); echo '<html><head><title>Redirecting...</title></head><body>If you haven\'t been redirected yet, <a href="'.makeUrl($paths->page).'">click here</a>.'; break;
       
   341       }
       
   342       $template->header();
       
   343       $c = PageUtils::catedit_raw($paths->page_id, $paths->namespace);
       
   344       echo $c[1];
       
   345       $template->footer();
       
   346       break;
       
   347     case 'moreoptions':
       
   348       $template->header();
       
   349       echo '<div class="menu_nojs" style="width: 150px; padding: 0;"><ul style="display: block;"><li><div class="label">' . $lang->get('ajax_lbl_moreoptions_nojs') . '</div><div style="clear: both;"></div></li>'.$template->toolbar_menu.'</ul></div>';
       
   350       $template->footer();
       
   351       break;
       
   352     case 'protect':
       
   353       if ( !$session->sid_super )
       
   354       {
       
   355         redirect(makeUrlNS('Special', "Login/{$paths->page}", 'target_do=protect&level=' . $session->user_level, false), $lang->get('etc_access_denied_short'), $lang->get('etc_access_denied_need_reauth'), 0);
       
   356       }
       
   357       
       
   358       if ( isset($_POST['level']) && isset($_POST['reason']) )
       
   359       {
       
   360         $level = intval($_POST['level']);
       
   361         if ( !in_array($level, array(PROTECT_FULL, PROTECT_SEMI, PROTECT_NONE)) )
       
   362         {
       
   363           $errors[] = 'bad level';
       
   364         }
       
   365         $reason = trim($_POST['reason']);
       
   366         if ( empty($reason) )
       
   367         {
       
   368           $errors[] = $lang->get('onpage_protect_err_need_reason');
       
   369         }
       
   370         
       
   371         $page = new PageProcessor($paths->page_id, $paths->namespace);
       
   372         $result = $page->protect_page($level, $reason);
       
   373         if ( $result['success'] )
       
   374         {
       
   375           redirect(makeUrl($paths->page), $lang->get('page_protect_lbl_success_title'), $lang->get('page_protect_lbl_success_body', array('page_link' => makeUrl($paths->page, false, true))), 3);
       
   376         }
       
   377         else
       
   378         {
       
   379           $errors[] = $lang->get('page_err_' . $result['error']);
       
   380         }
       
   381       }
       
   382       $template->header();
       
   383       ?>
   536       ?>
   384       <form action="<?php echo makeUrl($paths->page, 'do=protect'); ?>" method="post">
   537       <form action="<?php echo makeUrl($paths->page, 'do=resetvotes'); ?>" method="post">
   385         <h3><?php echo $lang->get('onpage_protect_heading'); ?></h3>
   538         <p><?php echo $lang->get('ajax_delvote_reset_confirm'); ?></p>
   386         <p><?php echo $lang->get('onpage_protect_msg_select_level'); ?></p>
   539         <p><input type="submit" name="_youmaylivealittlelonger" value="<?php echo htmlspecialchars($lang->get('page_delvote_reset_btn_submit')); ?>" /></p>
   387         
       
   388         <?php
       
   389         if ( !empty($errors) )
       
   390         {
       
   391           echo '<ul><li>' . implode('</li><li>', $errors) . '</li></ul>';
       
   392         }
       
   393         ?>
       
   394         
       
   395         <div class="protectlevel" style="line-height: 22px; margin-left: 17px;">
       
   396           <label>
       
   397             <input type="radio" name="level" value="<?php echo PROTECT_FULL; ?>" />
       
   398             <?php echo gen_sprite(cdnPath . '/images/protect-icons.png', 22, 22, 0, 0); ?>
       
   399             <?php echo $lang->get('onpage_protect_btn_full'); ?>
       
   400           </label>
       
   401         </div>
       
   402         <div class="protectlevel_hint" style="font-size: smaller; margin-left: 68px;">
       
   403           <?php echo $lang->get('onpage_protect_btn_full_hint'); ?>
       
   404         </div>
       
   405         
       
   406         <div class="protectlevel" style="line-height: 22px; margin-left: 17px;">
       
   407           <label>
       
   408             <input type="radio" name="level" value="<?php echo PROTECT_SEMI; ?>" />
       
   409             <?php echo gen_sprite(cdnPath . '/images/protect-icons.png', 22, 22, 22, 0); ?>
       
   410             <?php echo $lang->get('onpage_protect_btn_semi'); ?>
       
   411           </label>
       
   412         </div>
       
   413         <div class="protectlevel_hint" style="font-size: smaller; margin-left: 68px;">
       
   414           <?php echo $lang->get('onpage_protect_btn_semi_hint'); ?>
       
   415         </div>
       
   416         
       
   417         <div class="protectlevel" style="line-height: 22px; margin-left: 17px;">
       
   418           <label>
       
   419             <input type="radio" name="level" value="<?php echo PROTECT_NONE; ?>" />
       
   420             <?php echo gen_sprite(cdnPath . '/images/protect-icons.png', 22, 22, 44, 0); ?>
       
   421             <?php echo $lang->get('onpage_protect_btn_none'); ?>
       
   422           </label>
       
   423         </div>
       
   424         <div class="protectlevel_hint" style="font-size: smaller; margin-left: 68px;">
       
   425           <?php echo $lang->get('onpage_protect_btn_none_hint'); ?>
       
   426         </div>
       
   427         
       
   428         <table style="margin-left: 1em;" cellspacing="10">
       
   429           <tr>
       
   430             <td valign="top">
       
   431               <?php echo $lang->get('onpage_protect_lbl_reason'); ?>
       
   432             </td>
       
   433             <td>
       
   434               <input type="text" name="reason" size="40" /><br />
       
   435               <small><?php echo $lang->get('onpage_protect_lbl_reason_hint'); ?></small>
       
   436             </td>
       
   437           </tr>
       
   438         </table>
       
   439                               
       
   440         <p>
       
   441           <input type="submit" value="<?php echo htmlspecialchars($lang->get('page_protect_btn_submit')) ?>" style="font-weight: bold;" />
       
   442           <a class="abutton" href="<?php echo makeUrl($paths->page, false, true); ?>"><?php echo $lang->get('etc_cancel'); ?></a>
       
   443         </p> 
       
   444       </form>
   540       </form>
   445       <?php
   541       <?php
   446       $template->footer();
   542     $template->footer();
   447       break;
   543     break;
   448     case 'rename':
   544   case 'deletepage':
   449       require_once(ENANO_ROOT.'/includes/pageutils.php');
   545     if(!$session->get_permissions('delete_page'))
   450       if(!empty($_POST['newname']))
   546     {
   451       {
   547       die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
   452         $r = PageUtils::rename($paths->page_id, $paths->namespace, $_POST['newname']);
   548     }
   453         die_friendly($lang->get('page_rename_success_title'), '<p>'.nl2br($r).' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>');
   549     if ( !$session->sid_super )
   454       }
   550     {
   455       $template->header();
   551       redirect(makeUrlNS('Special', "Login/{$paths->page}", 'target_do=deletepage&level=' . $session->user_level, false), $lang->get('etc_access_denied_short'), $lang->get('etc_access_denied_need_reauth'), 0);
   456       ?>
   552     }
   457       <form action="<?php echo makeUrl($paths->page, 'do=rename'); ?>" method="post">
   553     
   458         <?php if(isset($_POST['newname'])) echo '<p style="color: red;">' . $lang->get('page_rename_err_need_name') . '</p>'; ?>
   554     require_once(ENANO_ROOT.'/includes/pageutils.php');
   459         <p><?php echo $lang->get('page_rename_lbl'); ?></p>
   555     if(isset($_POST['_adiossucker']))
   460         <p><input type="text" name="newname" size="40" /></p>
   556     {
   461         <p><input type="submit" value="<?php echo htmlspecialchars($lang->get('page_rename_btn_submit')); ?>" style="font-weight: bold;" /></p> 
   557       $reason = ( isset($_POST['reason']) ) ? $_POST['reason'] : false;
   462       </form>
   558       if ( empty($reason) )
   463       <?php
   559         $error = $lang->get('ajax_delete_prompt_reason');
   464       $template->footer();    
   560       else
   465       break;
       
   466     case 'flushlogs':
       
   467       if(!$session->get_permissions('clear_logs'))
       
   468       {
       
   469         die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
       
   470       }
       
   471       if ( !$session->sid_super )
       
   472       {
       
   473         redirect(makeUrlNS('Special', "Login/{$paths->page}", 'target_do=flushlogs&level=' . $session->user_level, false), $lang->get('etc_access_denied_short'), $lang->get('etc_access_denied_need_reauth'), 0);
       
   474       }
       
   475       require_once(ENANO_ROOT.'/includes/pageutils.php');
       
   476       if(isset($_POST['_downthejohn']))
       
   477       {
   561       {
   478         $template->header();
   562         $template->header();
   479           $result = PageUtils::flushlogs($paths->page_id, $paths->namespace);
   563           $result = PageUtils::deletepage($paths->page_id, $paths->namespace, $reason);
   480           echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>';
   564           echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>';
   481         $template->footer();
   565         $template->footer();
   482         break;
   566         break;
   483       }
   567       }
       
   568     }
       
   569     $template->header();
       
   570       ?>
       
   571       <form action="<?php echo makeUrl($paths->page, 'do=deletepage'); ?>" method="post">
       
   572          <?php echo $lang->get('page_delete_warning_stern'); ?>
       
   573          <?php if ( isset($error) ) echo "<p>$error</p>"; ?>
       
   574          <p><?php echo $lang->get('page_delete_lbl_reason'); ?> <input type="text" name="reason" size="50" /></p>
       
   575          <p><input type="submit" name="_adiossucker" value="<?php echo htmlspecialchars($lang->get('page_delete_btn_submit')); ?>" style="color: red; font-weight: bold;" /></p>
       
   576       </form>
       
   577       <?php
       
   578     $template->footer();
       
   579     break;
       
   580   case 'setwikimode':
       
   581     if(!$session->get_permissions('set_wiki_mode'))
       
   582     {
       
   583       die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
       
   584     }
       
   585     if ( isset($_POST['finish']) )
       
   586     {
       
   587       $level = intval($_POST['level']);
       
   588       if ( !in_array($level, array(0, 1, 2) ) )
       
   589       {
       
   590         die_friendly('Invalid request', '<p>Level not specified</p>');
       
   591       }
       
   592       $q = $db->sql_query('UPDATE '.table_prefix.'pages SET wiki_mode=' . $level . ' WHERE urlname=\'' . $db->escape($paths->page_id) . '\' AND namespace=\'' . $paths->namespace . '\';');
       
   593       if ( !$q )
       
   594         $db->_die();
       
   595       redirect(makeUrl($paths->page), htmlspecialchars($paths->cpage['name']), $lang->get('page_wikimode_success_redirect'), 2);
       
   596     }
       
   597     else
       
   598     {
   484       $template->header();
   599       $template->header();
   485         ?>
   600       if(!isset($_GET['level']) || ( isset($_GET['level']) && !preg_match('#^([0-9])$#', $_GET['level']))) die_friendly('Invalid request', '<p>Level not specified</p>');
   486         <form action="<?php echo makeUrl($paths->page, 'do=flushlogs'); ?>" method="post">
   601         $level = intval($_GET['level']);
   487            <?php echo $lang->get('page_flushlogs_warning_stern'); ?>
       
   488            <p><input type="submit" name="_downthejohn" value="<?php echo htmlspecialchars($lang->get('page_flushlogs_btn_submit')); ?>" style="color: red; font-weight: bold;" /></p>
       
   489         </form>
       
   490         <?php
       
   491       $template->footer();
       
   492       break;
       
   493     case 'delvote':
       
   494       require_once(ENANO_ROOT.'/includes/pageutils.php');
       
   495       if(isset($_POST['_ballotbox']))
       
   496       {
       
   497         $template->header();
       
   498         $result = PageUtils::delvote($paths->page_id, $paths->namespace);
       
   499         echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>';
       
   500         $template->footer();
       
   501         break;
       
   502       }
       
   503       $template->header();
       
   504         ?>
       
   505         <form action="<?php echo makeUrl($paths->page, 'do=delvote'); ?>" method="post">
       
   506            <?php
       
   507              echo $lang->get('page_delvote_warning_stern');
       
   508              echo '<p>';
       
   509              switch($paths->cpage['delvotes'])
       
   510              {
       
   511                case 0:  echo $lang->get('page_delvote_count_zero'); break;
       
   512                case 1:  echo $lang->get('page_delvote_count_one'); break;
       
   513                default: echo $lang->get('page_delvote_count_plural', array('delvotes' => $paths->cpage['delvotes'])); break;
       
   514              }
       
   515              echo '</p>';
       
   516            ?>
       
   517            <p><input type="submit" name="_ballotbox" value="<?php echo htmlspecialchars($lang->get('page_delvote_btn_submit')); ?>" /></p>
       
   518         </form>
       
   519         <?php
       
   520       $template->footer();
       
   521       break;
       
   522     case 'resetvotes':
       
   523       require_once(ENANO_ROOT.'/includes/pageutils.php');
       
   524       if(!$session->get_permissions('vote_reset'))
       
   525       {
       
   526         die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
       
   527       }
       
   528       if(isset($_POST['_youmaylivealittlelonger']))
       
   529       {
       
   530         $template->header();
       
   531           $result = PageUtils::resetdelvotes($paths->page_id, $paths->namespace);
       
   532           echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>';
       
   533         $template->footer();
       
   534         break;
       
   535       }
       
   536       $template->header();
       
   537         ?>
       
   538         <form action="<?php echo makeUrl($paths->page, 'do=resetvotes'); ?>" method="post">
       
   539           <p><?php echo $lang->get('ajax_delvote_reset_confirm'); ?></p>
       
   540           <p><input type="submit" name="_youmaylivealittlelonger" value="<?php echo htmlspecialchars($lang->get('page_delvote_reset_btn_submit')); ?>" /></p>
       
   541         </form>
       
   542         <?php
       
   543       $template->footer();
       
   544       break;
       
   545     case 'deletepage':
       
   546       if(!$session->get_permissions('delete_page'))
       
   547       {
       
   548         die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
       
   549       }
       
   550       if ( !$session->sid_super )
       
   551       {
       
   552         redirect(makeUrlNS('Special', "Login/{$paths->page}", 'target_do=deletepage&level=' . $session->user_level, false), $lang->get('etc_access_denied_short'), $lang->get('etc_access_denied_need_reauth'), 0);
       
   553       }
       
   554       
       
   555       require_once(ENANO_ROOT.'/includes/pageutils.php');
       
   556       if(isset($_POST['_adiossucker']))
       
   557       {
       
   558         $reason = ( isset($_POST['reason']) ) ? $_POST['reason'] : false;
       
   559         if ( empty($reason) )
       
   560           $error = $lang->get('ajax_delete_prompt_reason');
       
   561         else
       
   562         {
       
   563           $template->header();
       
   564             $result = PageUtils::deletepage($paths->page_id, $paths->namespace, $reason);
       
   565             echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>';
       
   566           $template->footer();
       
   567           break;
       
   568         }
       
   569       }
       
   570       $template->header();
       
   571         ?>
       
   572         <form action="<?php echo makeUrl($paths->page, 'do=deletepage'); ?>" method="post">
       
   573            <?php echo $lang->get('page_delete_warning_stern'); ?>
       
   574            <?php if ( isset($error) ) echo "<p>$error</p>"; ?>
       
   575            <p><?php echo $lang->get('page_delete_lbl_reason'); ?> <input type="text" name="reason" size="50" /></p>
       
   576            <p><input type="submit" name="_adiossucker" value="<?php echo htmlspecialchars($lang->get('page_delete_btn_submit')); ?>" style="color: red; font-weight: bold;" /></p>
       
   577         </form>
       
   578         <?php
       
   579       $template->footer();
       
   580       break;
       
   581     case 'setwikimode':
       
   582       if(!$session->get_permissions('set_wiki_mode'))
       
   583       {
       
   584         die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
       
   585       }
       
   586       if ( isset($_POST['finish']) )
       
   587       {
       
   588         $level = intval($_POST['level']);
       
   589         if ( !in_array($level, array(0, 1, 2) ) )
   602         if ( !in_array($level, array(0, 1, 2) ) )
   590         {
   603         {
   591           die_friendly('Invalid request', '<p>Level not specified</p>');
   604           die_friendly('Invalid request', '<p>Level not specified</p>');
   592         }
   605         }
   593         $q = $db->sql_query('UPDATE '.table_prefix.'pages SET wiki_mode=' . $level . ' WHERE urlname=\'' . $db->escape($paths->page_id) . '\' AND namespace=\'' . $paths->namespace . '\';');
   606       echo '<form action="' . makeUrl($paths->page, 'do=setwikimode', true) . '" method="post">';
   594         if ( !$q )
   607       echo '<input type="hidden" name="finish" value="foo" />';
   595           $db->_die();
   608       echo '<input type="hidden" name="level" value="' . $level . '" />';
   596         redirect(makeUrl($paths->page), htmlspecialchars($paths->cpage['name']), $lang->get('page_wikimode_success_redirect'), 2);
   609       $level_txt = ( $level == 0 ) ? 'page_wikimode_level_off' : ( ( $level == 1 ) ? 'page_wikimode_level_on' : 'page_wikimode_level_global' );
   597       }
   610       $blurb = ( $level == 0 || ( $level == 2 && getConfig('wiki_mode') != '1' ) ) ? 'page_wikimode_blurb_disable' : 'page_wikimode_blurb_enable';
   598       else
   611       ?>
   599       {
   612       <h3><?php echo $lang->get('page_wikimode_heading'); ?></h3>
   600         $template->header();
   613       <p><?php echo $lang->get($level_txt) . ' ' . $lang->get($blurb); ?></p>
   601         if(!isset($_GET['level']) || ( isset($_GET['level']) && !preg_match('#^([0-9])$#', $_GET['level']))) die_friendly('Invalid request', '<p>Level not specified</p>');
   614       <p><?php echo $lang->get('page_wikimode_warning'); ?></p>
   602           $level = intval($_GET['level']);
   615       <p><input type="submit" value="<?php echo htmlspecialchars($lang->get('page_wikimode_btn_submit')); ?>" /></p>
   603           if ( !in_array($level, array(0, 1, 2) ) )
   616       <?php
   604           {
   617       echo '</form>';
   605             die_friendly('Invalid request', '<p>Level not specified</p>');
   618       $template->footer();
   606           }
   619     }
   607         echo '<form action="' . makeUrl($paths->page, 'do=setwikimode', true) . '" method="post">';
   620     break;
   608         echo '<input type="hidden" name="finish" value="foo" />';
   621   case 'diff':
   609         echo '<input type="hidden" name="level" value="' . $level . '" />';
   622     require_once(ENANO_ROOT.'/includes/pageutils.php');
   610         $level_txt = ( $level == 0 ) ? 'page_wikimode_level_off' : ( ( $level == 1 ) ? 'page_wikimode_level_on' : 'page_wikimode_level_global' );
   623     require_once(ENANO_ROOT.'/includes/diff.php');
   611         $blurb = ( $level == 0 || ( $level == 2 && getConfig('wiki_mode') != '1' ) ) ? 'page_wikimode_blurb_disable' : 'page_wikimode_blurb_enable';
   624     $template->header();
   612         ?>
   625     $id1 = ( isset($_GET['diff1']) ) ? (int)$_GET['diff1'] : false;
   613         <h3><?php echo $lang->get('page_wikimode_heading'); ?></h3>
   626     $id2 = ( isset($_GET['diff2']) ) ? (int)$_GET['diff2'] : false;
   614         <p><?php echo $lang->get($level_txt) . ' ' . $lang->get($blurb); ?></p>
   627     if ( !$id1 || !$id2 )
   615         <p><?php echo $lang->get('page_wikimode_warning'); ?></p>
   628     {
   616         <p><input type="submit" value="<?php echo htmlspecialchars($lang->get('page_wikimode_btn_submit')); ?>" /></p>
   629       echo '<p>Invalid request.</p>';
   617         <?php
       
   618         echo '</form>';
       
   619         $template->footer();
       
   620       }
       
   621       break;
       
   622     case 'diff':
       
   623       require_once(ENANO_ROOT.'/includes/pageutils.php');
       
   624       require_once(ENANO_ROOT.'/includes/diff.php');
       
   625       $template->header();
       
   626       $id1 = ( isset($_GET['diff1']) ) ? (int)$_GET['diff1'] : false;
       
   627       $id2 = ( isset($_GET['diff2']) ) ? (int)$_GET['diff2'] : false;
       
   628       if ( !$id1 || !$id2 )
       
   629       {
       
   630         echo '<p>Invalid request.</p>';
       
   631         $template->footer();
       
   632         break;
       
   633       }
       
   634       if ( !ctype_digit($_GET['diff1']) || !ctype_digit($_GET['diff1']) )
       
   635       {
       
   636         echo '<p>SQL injection attempt</p>';
       
   637         $template->footer();
       
   638         break;
       
   639       }
       
   640       echo PageUtils::pagediff($paths->page_id, $paths->namespace, $id1, $id2);
       
   641       $template->footer();
   630       $template->footer();
   642       break;
   631       break;
   643     case 'detag':
   632     }
   644       if ( $session->user_level < USER_LEVEL_ADMIN )
   633     if ( !ctype_digit($_GET['diff1']) || !ctype_digit($_GET['diff1']) )
   645       {
   634     {
   646         die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
   635       echo '<p>SQL injection attempt</p>';
   647       }
   636       $template->footer();
   648       if ( $paths->page_exists )
       
   649       {
       
   650         die_friendly($lang->get('etc_invalid_request_short'), '<p>' . $lang->get('page_detag_err_page_exists') . '</p>');
       
   651       }
       
   652       $q = $db->sql_query('DELETE FROM '.table_prefix.'tags WHERE page_id=\'' . $db->escape($paths->page_id) . '\' AND namespace=\'' . $paths->namespace . '\';');
       
   653       if ( !$q )
       
   654         $db->_die('Detag query, index.php:'.__LINE__);
       
   655       die_friendly($lang->get('page_detag_success_title'), '<p>' . $lang->get('page_detag_success_body') . '</p>');
       
   656       break;
   637       break;
   657     case 'aclmanager':
   638     }
   658       if ( !$session->sid_super )
   639     echo PageUtils::pagediff($paths->page_id, $paths->namespace, $id1, $id2);
   659       {
   640     $template->footer();
   660         redirect(makeUrlNS('Special', "Login/{$paths->page}", 'target_do=aclmanager&level=' . $session->user_level, false), $lang->get('etc_access_denied_short'), $lang->get('etc_access_denied_need_reauth'), 0);
   641     break;
   661       }
   642   case 'detag':
   662       
   643     if ( $session->user_level < USER_LEVEL_ADMIN )
   663       require_once(ENANO_ROOT.'/includes/pageutils.php');
   644     {
   664       $data = ( isset($_POST['data']) ) ? $_POST['data'] : Array('mode' => 'listgroups');
   645       die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
   665       PageUtils::aclmanager($data);
   646     }
   666       break;
   647     if ( $paths->page_exists )
   667     case 'sql_report':
   648     {
   668       $rev_id = ( (isset($_GET['oldid'])) ? intval($_GET['oldid']) : 0 );
   649       die_friendly($lang->get('etc_invalid_request_short'), '<p>' . $lang->get('page_detag_err_page_exists') . '</p>');
   669       $page = new PageProcessor( $paths->page_id, $paths->namespace, $rev_id );
   650     }
   670       $page->send_headers = true;
   651     $q = $db->sql_query('DELETE FROM '.table_prefix.'tags WHERE page_id=\'' . $db->escape($paths->page_id) . '\' AND namespace=\'' . $paths->namespace . '\';');
   671       $pagepass = ( isset($_REQUEST['pagepass']) ) ? sha1($_REQUEST['pagepass']) : '';
   652     if ( !$q )
   672       $page->password = $pagepass;
   653       $db->_die('Detag query, index.php:'.__LINE__);
   673       $page->send(true);
   654     die_friendly($lang->get('page_detag_success_title'), '<p>' . $lang->get('page_detag_success_body') . '</p>');
   674       ob_end_clean();
   655     break;
   675       ob_start();
   656   case 'aclmanager':
   676       $db->sql_report();
   657     if ( !$session->sid_super )
   677       break;
   658     {
       
   659       redirect(makeUrlNS('Special', "Login/{$paths->page}", 'target_do=aclmanager&level=' . $session->user_level, false), $lang->get('etc_access_denied_short'), $lang->get('etc_access_denied_need_reauth'), 0);
       
   660     }
       
   661     
       
   662     require_once(ENANO_ROOT.'/includes/pageutils.php');
       
   663     $data = ( isset($_POST['data']) ) ? $_POST['data'] : Array('mode' => 'listgroups');
       
   664     PageUtils::aclmanager($data);
       
   665     break;
       
   666   case 'sql_report':
       
   667     $rev_id = ( (isset($_GET['oldid'])) ? intval($_GET['oldid']) : 0 );
       
   668     $page = new PageProcessor( $paths->page_id, $paths->namespace, $rev_id );
       
   669     $page->send_headers = true;
       
   670     $pagepass = ( isset($_REQUEST['pagepass']) ) ? sha1($_REQUEST['pagepass']) : '';
       
   671     $page->password = $pagepass;
       
   672     $page->send(true);
       
   673     ob_end_clean();
       
   674     ob_start();
       
   675     $db->sql_report();
       
   676     break;
       
   677 }
       
   678 
       
   679 // Generate an ETag
       
   680 /*
       
   681 // format: first 10 digits of SHA1 of page name, user id in hex, user and auth levels, page timestamp in hex
       
   682 $etag = substr(sha1($paths->namespace . ':' . $paths->page_id), 0, 10) . '-' .
       
   683         "u{$session->user_id}l{$session->user_level}a{$session->auth_level}-" .
       
   684         dechex($page_timestamp);
       
   685         
       
   686 if ( isset($_SERVER['HTTP_IF_NONE_MATCH']) )
       
   687 {
       
   688   if ( "\"$etag\"" == $_SERVER['HTTP_IF_NONE_MATCH'] )
       
   689   {
       
   690     header('HTTP/1.1 304 Not Modified');
       
   691     exit();
   678   }
   692   }
   679   
   693 }
   680   // Generate an ETag
       
   681   /*
       
   682   // format: first 10 digits of SHA1 of page name, user id in hex, user and auth levels, page timestamp in hex
       
   683   $etag = substr(sha1($paths->namespace . ':' . $paths->page_id), 0, 10) . '-' .
       
   684           "u{$session->user_id}l{$session->user_level}a{$session->auth_level}-" .
       
   685           dechex($page_timestamp);
       
   686           
   694           
   687   if ( isset($_SERVER['HTTP_IF_NONE_MATCH']) )
   695 header("ETag: \"$etag\"");
   688   {
   696 */
   689     if ( "\"$etag\"" == $_SERVER['HTTP_IF_NONE_MATCH'] )
   697 
   690     {
   698 $db->close();  
   691       header('HTTP/1.1 304 Not Modified');
   699 gzip_output();
   692       exit();
   700 
   693     }
   701 @ob_end_flush();
   694   }
       
   695             
       
   696   header("ETag: \"$etag\"");
       
   697   */
       
   698   
       
   699   $db->close();  
       
   700   gzip_output();
       
   701   
       
   702   @ob_end_flush();
       
   703   
   702   
   704 ?>
   703 ?>