plugins/ajim/ajim.php
changeset 0 902822492a68
equal deleted inserted replaced
-1:000000000000 0:902822492a68
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * AjIM - the Asynchronous Javascript Instant Messenger
       
     5  * A shoutbox/chatbox framework that uses PHP, AJAX, MySQL, and Javascript
       
     6  * Version: 1.0 RC 1
       
     7  * Copyright (C) 2006-2007 Dan Fuhry
       
     8  *
       
     9  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
       
    10  * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
       
    11  *
       
    12  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
       
    13  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. 
       
    14  */
       
    15 
       
    16 error_reporting(E_ALL);
       
    17 class ajim {
       
    18   var $table_prefix, $conn, $id, $admin, $iface, $prune, $formatfunc, $config, $bad_words;
       
    19   /**
       
    20    * Die and be friendly about it.
       
    21    * @param string $text - should be the text to show to the user, include mysql_error() value if applicable
       
    22    */
       
    23   function kill($text) {
       
    24     die('AjIM: Database error<br />'.$text);
       
    25   }
       
    26   /**
       
    27    * Make a SQL query. This function contains some error correction that performs automatic database upgrades if needed.
       
    28    * @param string $q - The query text to send to MySQL.
       
    29    * @return resource - or, kills the connection and bails out if the query failed
       
    30    */
       
    31   function sql($q) {
       
    32     $r = mysql_query($q, $this->conn);
       
    33     if(!$r)
       
    34     {
       
    35       if(strstr(mysql_error(), 'Unknown column \'time_id\''))
       
    36       {
       
    37         $this->sql('ALTER TABLE '.$this->table_prefix.'ajim ADD COLUMN time_id int(11) NOT NULL DEFAULT 0;');
       
    38         $r = mysql_query($q, $this->conn);
       
    39       }
       
    40       elseif(strstr(mysql_error(), 'Unknown column \'sid\''))
       
    41       {
       
    42         $this->sql('ALTER TABLE '.$this->table_prefix.'ajim ADD COLUMN sid varchar(40) NOT NULL DEFAULT \'\';');
       
    43         $r = mysql_query($q, $this->conn);
       
    44       }
       
    45       elseif(strstr(mysql_error(), 'Unknown column \'ip_addr\''))
       
    46       {
       
    47         $this->sql('ALTER TABLE '.$this->table_prefix.'ajim ADD COLUMN ip_addr varchar(15) NOT NULL DEFAULT \'\';');
       
    48         $r = mysql_query($q, $this->conn);
       
    49       }
       
    50       $this->kill('Error during query:<br /><pre>'.htmlspecialchars($q).'</pre><br />MySQL said: '.mysql_error().'<br /><br />Depending on the error, AjIM may be able to automatically repair it. Just hang tight for about ten seconds. Whatever you do, don\'t close this browser window!');
       
    51     }
       
    52     return $r;
       
    53   }
       
    54   /**
       
    55    * Get the user's SID (unique ID used for editing authorization) or generate a new one.
       
    56    * @return string
       
    57    */
       
    58   function get_sid()
       
    59   {
       
    60     // Tag the user with a unique ID that can be used to edit posts
       
    61     // This is used to essentially track users, but only for the purpose of letting them edit posts
       
    62     if(!isset($_COOKIE['ajim_sid']))
       
    63     {
       
    64       $hash = sha1(microtime());
       
    65       setcookie('ajim_sid', $hash, time()+60*60*24*365); // Cookies last for one year
       
    66     }
       
    67     else
       
    68       $hash = $_COOKIE['ajim_sid'];
       
    69       
       
    70     return $hash;
       
    71   }
       
    72   /**
       
    73    * Set the default value for a configuration field.
       
    74    * @param string $key - name of the configuration key
       
    75    * @param string $value - the default value
       
    76    * @param array $confarray - needs to be the array passed as the first param on the constructor
       
    77    */
       
    78   function config_default($key, $value, &$confarray)
       
    79   {
       
    80     if(!isset($confarray[$key]))
       
    81       $confarray[$key] = $value;
       
    82   }
       
    83   /**
       
    84    * Set up some basic vars and a database connection
       
    85    * @param array $config - a configuration array, with either the key db_connection_handle (a valid MySQL connection resource) or the keys dbhost, dbname, dbuser, and dbpass
       
    86    * @param string $table_prefix - the text prepended to the "ajim" table, should match ^([A-z0-9_]+)$
       
    87    * @param string $handler - URL to the backend script, for example in Enano this would be the plugin file plugins/ajim.php
       
    88    * @param string $admin - string containing the MD5 hash of the user's password, IF AND ONLY IF the user should be allowed to use the moderation function. In all other cases this should be false.
       
    89    * @param string $id - used to carry over the randomly generated instance ID between requests. Should be false if the class is being initialized for displaying the inital HTML, in all other cases should be the value of the class variable AjIM::$id
       
    90    * @param bool $can_post - true if the user is allowed to post, false otherwise. Defaults to true.
       
    91    * @param mixed $formatfunc - a string containing the name of a function that can be called to format text before posts are sent to the user. If you need to call a class method, this should be an array with key 0 being the class name and key 1 being the method name.
       
    92    */
       
    93   function __construct($config, $table_prefix, $handler, $admin = false, $id = false, $can_post = true, $formatfunc = false) {
       
    94     // CONFIGURATION
       
    95     // $this->prune: a limit on the number of posts in the chat box. Usually this should be set to 40 or 50. Default is 40.
       
    96     // Set to -1 to disable pruning.
       
    97     $this->prune = -1;
       
    98     
       
    99     $this->get_sid();
       
   100     
       
   101     if(!is_array($config))
       
   102       $this->kill('$config passed to the AjIM constructor should be an associative array with either the keys dbhost, dbname, dbuser, and dbpass, or the key db_connection_handle.');
       
   103     if(isset($config['db_connection_handle']))
       
   104     {
       
   105       if(!is_resource($config['db_connection_handle'])) $this->kill('$config[\'db_connection_handle\'] is not a valid resource');
       
   106       $this->conn = $config['db_connection_handle'];
       
   107       if(!$this->conn) $this->kill('Error verifying database connection: '.mysql_error());
       
   108     } elseif(isset($config['dbhost']) && isset($config['dbname']) && isset($config['dbuser']) && isset($config['dbpass'])) {
       
   109       $this->conn = mysql_connect($config['dbhost'], $config['dbuser'], $config['dbpass']);
       
   110       if(!$this->conn) $this->kill('Error connecting to the database: '.mysql_error());
       
   111       $this->sql('USE '.$config['dbname']);
       
   112     }
       
   113     
       
   114     $this->bad_words = Array('viagra', 'phentermine', 'pharma', 'rolex', 'genital', 'penis', 'ranitidine', 'prozac', 'acetaminophen', 'acyclovir', 'ionamin', 'denavir', 'nizoral', 'zoloft', 'estradiol', 'didrex', 'aciphex', 'seasonale', 'allegra', 'lexapro', 'famvir', 'propecia', 'nasacort');
       
   115     if(isset($config['bad_words']) && is_array($config['bad_words']))
       
   116     {
       
   117       $this->bad_words = array_values(array_merge($this->bad_words, $config['bad_words']));
       
   118     }
       
   119     
       
   120     // Don't change these values here - change them by passing values to the config array in this constructor's params!
       
   121     $this->config_default('sb_color_background', '#FFFFFF', $config);
       
   122     $this->config_default('sb_color_foreground', '#000000', $config);
       
   123     $this->config_default('sb_color_editlink',   '#00C000', $config);
       
   124     $this->config_default('sb_color_deletelink', '#FF0000', $config);
       
   125     $this->config_default('sb_color_userlink',   '#0000FF', $config);
       
   126     
       
   127     $this->config = $config;
       
   128     
       
   129     if($id) $this->id = $id;
       
   130     else    $this->id = 'ajim_'.time();
       
   131     $this->admin = $admin;
       
   132     $this->formatfunc = $formatfunc;
       
   133     $this->can_post = $can_post;
       
   134     $this->table_prefix = $table_prefix;
       
   135     $this->sql('CREATE TABLE IF NOT EXISTS '.$this->table_prefix.'ajim(
       
   136         post_id mediumint(8) NOT NULL auto_increment,
       
   137         name text,
       
   138         website text,
       
   139         post text,
       
   140         time_id int(11) NOT NULL DEFAULT 0,
       
   141         PRIMARY KEY ( post_id )
       
   142       );');
       
   143     $this->iface = $handler;
       
   144     if(isset($_GET['ajimmode'])) $this->handler();
       
   145   }
       
   146   /**
       
   147    * A dummy function used for PHP4 compatibility.
       
   148    * @see AjIM::__construct()
       
   149    */
       
   150   function ajim($config, $table_prefix, $handler, $admin = false, $id = false, $can_post = true, $formatfunc = false) {
       
   151     $this->__construct($config, $table_prefix, $handler, $admin, $id, $can_post, $formatfunc);
       
   152   }
       
   153   /**
       
   154    * Generates the initial HTML UI to be sent to the user, used internally.
       
   155    * @access private
       
   156    * @param string $ajimPath - path to the AjIM connector (not this file), relative to document root, with initial slash.
       
   157    */
       
   158   function html($ajimPath) {
       
   159     
       
   160     $enstr = $this->can_post ? '' : ' disabled="disabled"';
       
   161     $html = '';
       
   162     $html .= '<script type="text/javascript" src="'.$ajimPath.'/ajim.php?js&amp;id='.$this->id.'&amp;path='.urlencode($this->iface).'&amp;pfx='.$this->table_prefix.'"></script>';
       
   163     if($this->admin) {
       
   164     $html.= '<script type="text/javascript" src="'.$ajimPath.'/ajim.php?jsadmin&amp;id='.$this->id.'&amp;path='.urlencode($this->iface).'&amp;pfx='.$this->table_prefix.'"></script>';
       
   165     }
       
   166     $html .= '<div id="'.$this->id.'_master" style="padding: 5%; width: 90%;">
       
   167              <div id="'.$this->id.'_c" style="text-align: center; color: '.$this->config['sb_color_foreground'].';
       
   168              font-family: arial, sans-serif; font-size: 7pt; background-color: '.$this->config['sb_color_background'].';
       
   169              text-align: left; border: 1px solid #000000; border-bottom: none; margin-bottom: 0; padding: 5%; width: 90%;
       
   170              height: 200px; clip: rect(0px,auto,200px,0px); overflow: auto;"><noscript><p>You need to have JavaScript support to use this shoutbox.</p></noscript></div>';
       
   171       // This is the post form div
       
   172     if($this->can_post)
       
   173     {
       
   174     $html .= '<div style="font-family: arial; font-size: 7pt; margin-top: 0; border: 1px solid #000000; border-top-width: 0; width: 100%;">
       
   175             <form action="#" onsubmit="'.$this->id.'_form(); return false;" method="get">
       
   176              <table border="0" style="margin: 0; padding: 0; width: 90%;">
       
   177               <tr><td><span style="font-family: arial; font-size: 7pt; ">Name:</span></td>   <td><input style="font-family: arial; font-size: 7pt; border: 1px solid #000; height: 15px; width: 65px; padding: 1px;" id="'.$this->id.'_name" name="name"'.$enstr.' /></td></tr>
       
   178               <tr><td><span style="font-family: arial; font-size: 7pt; ">Website:</span></td><td><input style="font-family: arial; font-size: 7pt; border: 1px solid #000; height: 15px; width: 65px; padding: 1px;" id="'.$this->id.'_website" name="website"'.$enstr.' /></td></tr>
       
   179               <tr><td colspan="2"><span style="font-family: arial; font-size: 7pt; ">Message:</span></td></tr>
       
   180               <tr><td colspan="2"><textarea'.$enstr.' rows="2" cols="16" style="width: auto; margin: 0 auto;" id="'.$this->id.'_post" name="post" onkeyup="'.$this->id.'_keyhandler();"></textarea></td></tr>
       
   181               <tr><td colspan="2" align="center"><input'.$enstr.' type="submit" value="Submit post" /><br />
       
   182               <span style="font-family: arial; font-size: 6pt; color: #000000;">AjIM powered</span></td></tr>
       
   183               ';
       
   184     $html .= '</table>
       
   185             </form>';
       
   186     if($this->admin) {
       
   187       $html .= '<table border="0" style="margin: 0; padding: 0; width: 90%;" align="center"><tr><td colspan="2" align="center"><span id="'.$this->id.'_admin"><a href="#" onclick="'.$this->id.'_prompt(); return false;">Administration</a></span></td></tr></table>';
       
   188     }
       
   189     $html.='</div></div>';
       
   190     } else {
       
   191       $html .= '<div style="font-family: arial; font-size: 7pt; margin: 5px; margin-top: 0; border: 1px solid #000000; border-top: none;">';
       
   192       if(isset($this->config['cant_post_notice'])) {
       
   193         $html .= '<div style="margin: 0; padding: 5px;">'.$this->config['cant_post_notice'].'</div>';
       
   194       }
       
   195       $html .= '</div></div>';
       
   196     }
       
   197     $html.='<script type="text/javascript">
       
   198     document.getElementById(\''.$this->id.'_c\').innerHTML = unescape(\'%3Cdiv align="center" style="width:95%;"%3EInitializing...%3C\/div%3E\');';
       
   199     if($this->can_post) $html .= 'if('.$this->id.'readCookie("ajim_password") && ( typeof "'.$this->id.'_login_bin" == "string" || typeof "'.$this->id.'_login_bin" == "function" )) {
       
   200       '.$this->id.'_login_bin('.$this->id.'readCookie("ajim_password"));
       
   201     }
       
   202     if('.$this->id.'readCookie("ajim_name")) document.getElementById("'.$this->id.'_name").value = '.$this->id.'readCookie("ajim_name");
       
   203     if('.$this->id.'readCookie("ajim_website")) document.getElementById("'.$this->id.'_website").value = '.$this->id.'readCookie("ajim_website");';
       
   204     $html .= ''.$this->id.'_refresh();
       
   205     </script>';
       
   206     
       
   207     return $html;
       
   208   }
       
   209   /**
       
   210    * Kills the database connection
       
   211    */
       
   212   function destroy() {
       
   213     mysql_close($this->conn);
       
   214   }
       
   215   /**
       
   216    * Strips all traces of HTML, XML, and PHP from text, and prepares it for being inserted into a MySQL database.
       
   217    * @access private
       
   218    * @param string $text - the text to sanitize
       
   219    * @return string
       
   220    */
       
   221   function sanitize($text) {
       
   222     $text = rawurldecode($text);
       
   223     $text = preg_replace('#<(.*?)>#is', '&lt;\\1&gt;', $text);
       
   224     $text = str_replace("\n", '<br />', $text);
       
   225     $text = mysql_real_escape_string($text);
       
   226     return $text;
       
   227   }
       
   228   /**
       
   229    * Scrutinizes a string $text for any traces of the word $word, returns true if the text is clean.
       
   230    * For example, if $word is "viagra" and the text contains "\/|@6r/\" this returns false, else you would get true.
       
   231    * @access private
       
   232    * @param string $text - the text to check
       
   233    * @param string $word - word to look for.
       
   234    * @return bool
       
   235    */
       
   236   function spamcheck($text, $word)
       
   237   {
       
   238     // build an array, with each key containing one letter (equiv. to str_split() in PHP 5)
       
   239     $chars = Array();
       
   240     for($i=0;$i<strlen($word);$i++)
       
   241     {
       
   242       $chars[] = substr($word, $i, 1);
       
   243     }
       
   244     // This is our rule list - all the known substitutions for a given letter (e.g. "\/" in place of "V", etc.), needs to be escaped for regex use
       
   245     $subs = Array(
       
   246       'a'=>'a|\/\\\\|@',
       
   247       'b'=>'b|\|o',
       
   248       'c'=>'c|\(|',
       
   249       'd'=>'d|o\|',
       
   250       'e'=>'e|3',
       
   251       'f'=>'f',
       
   252       'g'=>'g|6|9',
       
   253       'h'=>'h|\|n',
       
   254       'i'=>'i|\!|1|\|',
       
   255       'j'=>'j|\!|1|\|',
       
   256       'k'=>'k|\|<|\|&lt;',
       
   257       'l'=>'l|\!|1|\|',
       
   258       'm'=>'m|nn|rn',
       
   259       'n'=>'n|h|u\\|\\\\\|',
       
   260       'o'=>'o|\(\)|0|@',
       
   261       'p'=>'p',
       
   262       'q'=>'q',
       
   263       'r'=>'r|\|\^',
       
   264       's'=>'s',
       
   265       't'=>'t|\+',
       
   266       'u'=>'u|n',
       
   267       'v'=>'v|\\\\\/', // "\/"
       
   268       'w'=>'w|vv|\\\\\/\\\\\/', // allows for "\/\/"
       
   269       'x'=>'x|><|&gt;<|>&lt;|&gt;&lt;',
       
   270       'y'=>'y',
       
   271       'z'=>'z|\|\\\\\|' // |\|
       
   272       );
       
   273     $regex = '#([\s]){0,1}';
       
   274     foreach($chars as $c)
       
   275     {
       
   276       $lc = strtolower($c);
       
   277       if(isset($subs[$lc]))
       
   278       {
       
   279         $regex .= '('.$subs[$lc].')';
       
   280       } else {
       
   281         die('0 $subs['.$lc.'] is not set');
       
   282         $regex .= preg_quote($c);
       
   283       }
       
   284       $regex .= '(.|)';
       
   285     }
       
   286     $regex .= '([\s]){0,1}#is';
       
   287     //echo($word.': '.$regex.'<br />');
       
   288     if(preg_match($regex, $text)) return false;
       
   289     return true;
       
   290   }
       
   291   /**
       
   292    * Processes AJAX requests. Usually called if $_GET['ajimmode'] is set.
       
   293    * @access private
       
   294    */
       
   295   function handler() {
       
   296     if(isset($_GET['ajimmode'])) {
       
   297       switch($_GET['ajimmode']) {
       
   298       default:
       
   299         die('');
       
   300         break;
       
   301       case 'getsource':
       
   302       case 'getpost':
       
   303         if(!preg_match('#^([0-9]+)$#', $_GET['p'])) die('SQL injection attempt');
       
   304         $q = $this->sql('SELECT post,sid,ip_addr FROM '.$this->table_prefix.'ajim WHERE post_id='.$_GET['p']);
       
   305         $r = mysql_fetch_assoc($q);
       
   306         if( ( ( isset($_GET['ajim_auth']) && (!$this->admin || ($this->admin != $_GET['ajim_auth']) ) ) || !isset($_GET['ajim_auth']) ) && ( $this->get_sid() != $r['sid'] || $_SERVER['REMOTE_ADDR'] != $r['ip_addr'] ) ) die('Hacking attempt');
       
   307         if($_GET['ajimmode']=='getpost')
       
   308           if($this->formatfunc)
       
   309           {
       
   310             $p = @call_user_func($this->formatfunc, $r['post']);
       
   311             if($p) $r['post'] = $p;
       
   312             unset($p); // Free some memory
       
   313           }
       
   314         echo $r['post'];
       
   315         break;
       
   316       case "savepost":
       
   317         if(!preg_match('#^([0-9]+)$#', $_POST['p'])) die('SQL injection attempt');
       
   318         $q = $this->sql('SELECT sid,ip_addr FROM '.$this->table_prefix.'ajim WHERE post_id='.$_POST['p']);
       
   319         $r = mysql_fetch_assoc($q);
       
   320         if( ( ( isset($_POST['ajim_auth']) && (!$this->admin || ($this->admin != $_POST['ajim_auth']) ) ) || !isset($_POST['ajim_auth']) ) && ( $this->get_sid() != $r['sid'] || $_SERVER['REMOTE_ADDR'] != $r['ip_addr'] ) ) die('Hacking attempt');
       
   321         $post = $this->sanitize($_POST['post']);
       
   322         $post = $this->make_clickable($post);
       
   323         $post = preg_replace('#_(.*?)_#is', '<i>\\1</i>', $post);
       
   324         $post = preg_replace('#\*(.*?)\*#is', '<b>\\1</b>', $post);
       
   325         $bad_words = Array('viagra', 'phentermine', 'pharma');
       
   326         foreach($bad_words as $w)
       
   327         {
       
   328           if(!$this->spamcheck($post, $w)) die('<span style="color: red">The word "'.$w.'" has been detected in your message and as a result your post has been blocked.</span> Don\'t argue, that will only get you banned.');
       
   329         }
       
   330         if(!$this->can_post) die('Access to posting messages has been denied because the administrator has set that you must be logged into this website in order to post.');
       
   331         
       
   332         $this->sql('UPDATE '.$this->table_prefix.'ajim SET post=\''.$post.'\' WHERE post_id='.$_POST['p'].';');
       
   333         
       
   334         if($this->formatfunc)
       
   335         {
       
   336           $p = @call_user_func($this->formatfunc, $post);
       
   337           if($p) $post = $p;
       
   338           unset($p); // Free some memory
       
   339         }    
       
   340         die($post);
       
   341         break;
       
   342       case 'delete':
       
   343         if(!preg_match('#^([0-9]+)$#', $_POST['p'])) die('SQL injection attempt');
       
   344         $q = $this->sql('SELECT sid,ip_addr FROM '.$this->table_prefix.'ajim WHERE post_id='.$_POST['p']);
       
   345         $r = mysql_fetch_assoc($q);
       
   346         if( ( ( isset($_POST['ajim_auth']) && (!$this->admin || ($this->admin != $_POST['ajim_auth']) ) ) || !isset($_POST['ajim_auth']) ) && ( $this->get_sid() != $r['sid'] || $_SERVER['REMOTE_ADDR'] != $r['ip_addr'] ) ) die('Hacking attempt'); 
       
   347         $this->sql('DELETE FROM '.$this->table_prefix.'ajim WHERE post_id='.$_POST['p']);
       
   348         die('good');
       
   349         break;
       
   350       case 'post':
       
   351         if(!preg_match('#(^|[\n ])([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)$#is', $_POST['website'])) $_POST['website']='';
       
   352         // Now for a clever anti-spam trick: blacklist the words "viagra" and "phentermine" using one wicked regex:
       
   353         // #([\s]){1}(v|\\\\\/)(.*){1}(i|\||l|1)(.*){1}(a|@|\/\\\\)(.*){1}(g|6)(.*){1}r(.*){1}(a|@|\/\\\\)(\s){1}#is
       
   354         $name    = $this->sanitize($_POST['name']);
       
   355         $website = $this->sanitize($_POST['website']);
       
   356         $post    = $this->sanitize($_POST['post']);
       
   357         foreach($this->bad_words as $w)
       
   358         {
       
   359           if(!$this->spamcheck($post, $w)) die('<span style="color: red">The word "'.$w.'" has been detected in your message and as a result your post has been blocked.</span> Don\'t argue, that will only get you banned.');
       
   360         }
       
   361         $post = $this->make_clickable($post);
       
   362         $post = preg_replace('#_(.*?)_#is', '<i>\\1</i>', $post);
       
   363         $post = preg_replace('#\*(.*?)\*#is', '<b>\\1</b>', $post);
       
   364         if(!$this->can_post) die('Access to posting messages has been denied because the administrator has set that you must be logged into this website in order to post.');
       
   365         $this->sql('INSERT INTO '.$this->table_prefix.'ajim ( name, website, post, time_id, sid, ip_addr ) VALUES(\''.$name.'\', \''.$website.'\', \''.$post.'\', '.time().', \''.mysql_real_escape_string($this->get_sid()).'\', \''.mysql_real_escape_string($_SERVER['REMOTE_ADDR']).'\');');
       
   366       case 'view':
       
   367         // if(isset($_GET['ajim_auth']))
       
   368         //   die('Auth: '.$_GET['ajim_auth']); // .'<br />Pw:   '.$this->admin);
       
   369         if(isset($_GET['latest']) && ( isset($this->config['allow_looping']) && $this->config['allow_looping'] == true ))
       
   370         {
       
   371           // Determine max execution time
       
   372           $max_exec = intval(@ini_get('max_execution_time'));
       
   373           if(!$max_exec) $max_exec = 30;
       
   374           $time_left = $max_exec - 1;
       
   375         }
       
   376         $q = $this->sql('SELECT name, website, post, post_id, time_id, sid, ip_addr FROM '.$this->table_prefix.'ajim ORDER BY post_id;');
       
   377         if(mysql_num_rows($q) < 1) echo '0 <span style="color: #666666">No posts.</span>';
       
   378         else {
       
   379           // Prune the table
       
   380           if($this->prune > 0) {
       
   381             $nr = mysql_num_rows($q);
       
   382             $nr = $nr - $this->prune;
       
   383             if($nr > 0) $this->sql('DELETE FROM '.$this->table_prefix.'ajim LIMIT '.$nr.';');
       
   384           }
       
   385           // Alright, what we want to do here is grab the entire table, load it into an array, and then display the posts in reverse order.
       
   386           for($i = 1; $i<=mysql_num_rows($q); $i++) {
       
   387             $t[$i] = mysql_fetch_object($q);
       
   388           }
       
   389           
       
   390           $s = sizeof($t);
       
   391           
       
   392           if(isset($_GET['latest']) && ( isset($this->config['allow_looping']) && $this->config['allow_looping'] == true ))
       
   393           {
       
   394             // When I was coding this, I immediately thought "use labels and goto!" Here's hoping, PHP6 :-)
       
   395             $latest_from_user = intval($_GET['latest']);
       
   396             $latest_from_db   = intval($t[$s]->time_id);
       
   397             while(true)
       
   398             {
       
   399               if($latest_from_user == $latest_from_db && $time_left > 5)
       
   400               {
       
   401                 $time_left = $time_left - 5;
       
   402                 sleep(5);
       
   403                 mysql_free_result($q);
       
   404                 $q = $this->sql('SELECT name, website, post, post_id, time_id, sid, ip_addr FROM '.$this->table_prefix.'ajim ORDER BY post_id;');
       
   405                 $t = Array();
       
   406                 for($i = 1; $i<=mysql_num_rows($q); $i++) {
       
   407                   $t[$i] = mysql_fetch_object($q);
       
   408                 }
       
   409                 $s = sizeof($t);
       
   410                 $latest_from_user = intval($_GET['latest']);
       
   411                 $latest_from_db   = intval($t[$s]->time_id);
       
   412                 //echo (string)$latest_from_db.'<br />';
       
   413                 //flush();
       
   414                 //exit;
       
   415                 if($latest_from_user != $latest_from_db)
       
   416                   break;
       
   417                 continue;
       
   418               }
       
   419               elseif($latest_from_user == $latest_from_db && $time_left < 5)
       
   420               {
       
   421                 die('[E] No new posts');
       
   422               }
       
   423               break;
       
   424             }
       
   425           }
       
   426           
       
   427           echo $t[$s]->time_id . ' ';
       
   428           
       
   429           // This is my favorite array trick - it baffles everyone who looks at it :-D
       
   430           // What it does is the same as for($i=0;$i<sizeof($t);$i++), but it processes the
       
   431           // array in reverse order.
       
   432           
       
   433           for($i = $s; $i > 0; $i--) {
       
   434             if($this->formatfunc)
       
   435             {
       
   436               $p = @call_user_func($this->formatfunc, $t[$i]->post);
       
   437               if($p) $t[$i]->post = $p;
       
   438               unset($p); // Free some memory
       
   439               $good_tags = Array('b', 'i', 'u', 'br');
       
   440               $gt = implode('|', $good_tags);
       
   441               
       
   442               // Override any modifications that may have been made to the HTML
       
   443               $t[$i]->post = preg_replace('#&lt;('.$gt.')&gt;([^.]+)&lt;/\\1&gt;#is', '<\\1>\\2</\\1>', $t[$i]->post);
       
   444               $t[$i]->post = preg_replace('#&lt;('.$gt.')([ ]*?)/&gt;#is', '<\\1 />', $t[$i]->post);
       
   445               $t[$i]->post = preg_replace('#&lt;('.$gt.')&gt;#is', '<\\1 />', $t[$i]->post);
       
   446             }
       
   447             echo '<div style="border-bottom: 1px solid #BBB; width: 98%;"><table border="0" cellspacing="0" cellpadding="0" width="100%"><tr><td><span style="font-weight: bold">';
       
   448             if($t[$i]->website != '') echo '<a href="'.$t[$i]->website.'" style="color: #0000FF">'.$t[$i]->name.'</a>';
       
   449             else echo ''.$t[$i]->name.'';
       
   450             echo '</span> ';
       
   451             if( $this->can_post && ($t[$i]->sid == $this->get_sid() && $t[$i]->ip_addr == $_SERVER['REMOTE_ADDR'] ) || ( isset($_GET['ajim_auth']) && $_GET['ajim_auth']==$this->admin ) )
       
   452             echo '</td><td style="text-align: right"><a href="#" onclick="void('.$this->id.'_delete_post(\''.$t[$i]->post_id.'\')); return false;" style="color: '.$this->config['sb_color_deletelink'].'">Delete</a> <a href="javascript:void('.$this->id.'_edit_post(\''.$t[$i]->post_id.'\'));" id="'.$this->id.'_editbtn_'.$t[$i]->post_id.'" style="color: '.$this->config['sb_color_editlink'].'">Edit</a>';
       
   453             echo '</td></tr></table><span style="color: #CCC; font-style: italic;">Posted on '.date('n/j, g:ia', $t[$i]->time_id).'</span></div>';
       
   454             echo '<div style="border-bottom: 1px solid #CCC; width: 98%;" id="'.$this->id.'_post_'.$t[$i]->post_id.'">'.$t[$i]->post.'</div>';
       
   455             echo '<br />';
       
   456           }
       
   457         }
       
   458         break;
       
   459       case 'auth':
       
   460         if($_POST['ajim_auth']==$this->admin) echo 'good';
       
   461         else echo 'The password you entered is invalid.';
       
   462         break;
       
   463       }
       
   464     }
       
   465   }
       
   466   
       
   467   /**
       
   468    * Replace URLs within a block of text with anchors
       
   469    * Written by Nathan Codding, copyright (C) phpBB Group
       
   470    * @param string $text - the text to process
       
   471    * @return string
       
   472    */
       
   473   function make_clickable($text)
       
   474   {
       
   475     $text = preg_replace('#(script|about|applet|activex|chrome):#is', "\\1&#058;", $text);
       
   476     $ret = ' ' . $text;
       
   477     $ret = preg_replace('#(^|[\n ])([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)#is', '\\1<a href="\\2" target="_blank">\\2</a>', $ret);
       
   478     $ret = preg_replace("#(^|[\ n ])((www|ftp)\.[\w\#$%&~/.\-;:=,?@\[\]+]*)#is", '\\1<a href="http://\\2" target="_blank">\\2</a>', $ret);
       
   479     $ret = preg_replace("#(^|[\n ])([a-z0-9&\-_.]+?)@([\w\-]+\.([\w\-\.]+\.)*[\w]+)#i", '\\1<a href="mailto:\\2@\\3">\\2@\\3</a>', $ret);
       
   480     $ret = substr($ret, 1);
       
   481     return($ret);
       
   482   }
       
   483 }
       
   484 
       
   485 // The client-side javascript and CSS code
       
   486 
       
   487 if(isset($_GET['js']) && isset($_GET['id']) && isset($_GET['path']) && isset($_GET['pfx'])) {
       
   488   header('Content-type: text/javascript');
       
   489   ?>
       
   490   // <script>
       
   491   var <?php echo $_GET['id']; ?>id='<?php echo $_GET['id']; ?>';
       
   492   var path='<?php echo $_GET['path']; ?>';
       
   493   var pfx='<?php echo $_GET['pfx']; ?>';
       
   494   var authed = false; // Don't even try to hack this var; it contains the MD5 of the password that *you* enter, setting it to true will just botch up all the requests
       
   495                       // authed is always set to false unless your password has been verified by the server, and it is sent to the server with every request.
       
   496   var shift;
       
   497   var <?php echo $_GET['id']; ?>editlist = new Array();
       
   498   var <?php echo $_GET['id']; ?>_latestpost = 0;
       
   499   var <?php echo $_GET['id']; ?>_allowrequest = true;
       
   500   
       
   501   var <?php echo $_GET['id']; ?>_refcount = 0;
       
   502   var <?php echo $_GET['id']; ?>_refcount_current = 0;
       
   503   
       
   504   var <?php echo $_GET['id']; ?>interval = setInterval('<?php echo $_GET['id']; ?>_refresh();', 5000);
       
   505   var ajim_editlevels = 0;
       
   506                       
       
   507   // Add the AjIM stylesheet to the HTML header
       
   508   var link = document.createElement('link');
       
   509   link.href = path+'?title=null&css&id='+<?php echo $_GET['id']; ?>id+'&path='+path+'&pfx='+pfx+'&ajimmode=';
       
   510   link.rel  = 'stylesheet';
       
   511   link.type = 'text/css';
       
   512   var head = document.getElementsByTagName('head');
       
   513   head = head[0];
       
   514   head.appendChild(link);
       
   515   
       
   516   if(typeof window.onload == 'function')
       
   517     var __ajim_oltemp = window.onload;
       
   518   else
       
   519     var __ajim_oltemp = function(e) { };
       
   520   window.onload = function(e)
       
   521   {
       
   522     if(document.getElementById('<?php echo $_GET['id']; ?>_post'))
       
   523     {
       
   524       document.getElementById('<?php echo $_GET['id']; ?>_post').onkeyup = function(e) { <?php echo $_GET['id']; ?>_keyhandler(e); };
       
   525     }
       
   526     __ajim_oltemp(e);
       
   527   }
       
   528   
       
   529   function <?php echo $_GET['id']; ?>readCookie(name) {var nameEQ = name + "=";var ca = document.cookie.split(';');for(var i=0;i < ca.length;i++){var c = ca[i];while (c.charAt(0)==' ') c = c.substring(1,c.length);if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);}return null;}
       
   530   function <?php echo $_GET['id']; ?>setCookie(name,value,days){if (days){var date = new Date();date.setTime(date.getTime()+(days*24*60*60*1000));var expires = "; expires="+date.toGMTString();}else var expires = "";document.cookie = name+"="+value+expires+"; path=/";}
       
   531   function <?php echo $_GET['id']; ?>eraseCookie(name) {createCookie(name,"",-1);}
       
   532   
       
   533   function strpos(haystack, needle)
       
   534   {
       
   535     if(typeof(haystack) != 'string') return false;
       
   536     if(typeof(needle) != 'string')   return false;
       
   537     len = needle.length;
       
   538     for(i=0;i<haystack.length;i++)
       
   539     {
       
   540       if ( haystack.substr(i, len) == needle )
       
   541         return i;
       
   542     }
       
   543     return 0;
       
   544   }
       
   545                       
       
   546   function <?php echo $_GET['id']; ?>_newReq(what2call) {
       
   547     if (window.XMLHttpRequest) {
       
   548       request = new XMLHttpRequest();
       
   549     } else {
       
   550       if (window.ActiveXObject) {           
       
   551         request = new ActiveXObject("Microsoft.XMLHTTP");
       
   552       } else {
       
   553         alert('Your browser does not support AJAX. Get Firefox 2.0!');
       
   554         return false;
       
   555       }
       
   556     }
       
   557     request.onreadystatechange = what2call;
       
   558     return request;
       
   559   }
       
   560   
       
   561   function <?php echo $_GET['id']; ?>_refresh(force) {
       
   562     <?php echo $_GET['id']; ?>_refcount++;
       
   563     <?php echo $_GET['id']; ?>_refcount_current = <?php echo $_GET['id']; ?>_refcount;
       
   564     if(!<?php echo $_GET['id']; ?>_allowrequest && !force)
       
   565       return false;
       
   566     <?php echo $_GET['id']; ?>_allowrequest = false;
       
   567     var r = <?php echo $_GET['id']; ?>_newReq(function() {
       
   568        if(r.readyState == 4)
       
   569        {
       
   570          // Prevent an old request from taking over a more recent one
       
   571          if(<?php echo $_GET['id']; ?>_refcount > <?php echo $_GET['id']; ?>_refcount_current)
       
   572            return;
       
   573          if(r.responseText != '[E] No new posts')
       
   574          {
       
   575            time = r.responseText.substr(0, strpos(r.responseText, ' '));
       
   576            <?php echo $_GET['id']; ?>_latestpost = parseInt(time);
       
   577            text = r.responseText.substr(strpos(r.responseText, ' ')+1, r.responseText.length);
       
   578            document.getElementById('<?php echo $_GET['id']; ?>_c').innerHTML = text;
       
   579          }
       
   580          <?php echo $_GET['id']; ?>_allowrequest = true;
       
   581        }
       
   582     });
       
   583     if(force)
       
   584       latest = '';
       
   585     else
       
   586       latest = '&latest='+<?php echo $_GET['id']; ?>_latestpost;
       
   587     if(authed) r.open('GET', path+'?title=null&ajimmode=view&id='+<?php echo $_GET['id']; ?>id+'&pfx='+pfx+latest+'&ajim_auth='+authed, true);
       
   588     else       r.open('GET', path+'?title=null&ajimmode=view&id='+<?php echo $_GET['id']; ?>id+'&pfx='+pfx+latest, true);
       
   589     r.send(null);
       
   590   }
       
   591   
       
   592   function <?php echo $_GET['id']; ?>_submit(name, website, post) {
       
   593     var r = <?php echo $_GET['id']; ?>_newReq(function() {
       
   594        if(r.readyState == 4)
       
   595        {
       
   596          if(r.responseText != '[E] No new posts')
       
   597          {
       
   598            if(parseInt(r.responseText.substr(0,1)) != 0)
       
   599            {
       
   600              time = r.responseText.substr(0, strpos(r.responseText, ' '));
       
   601              <?php echo $_GET['id']; ?>_latestpost = parseInt(time);
       
   602              text = r.responseText.substr(strpos(r.responseText, ' ')+1, r.responseText.length);
       
   603            }
       
   604            else
       
   605            {
       
   606              text = r.responseText;
       
   607            }
       
   608            document.getElementById('<?php echo $_GET['id']; ?>_c').innerHTML = text;
       
   609          }
       
   610        }
       
   611     })
       
   612     if(authed) var parms = 'name='+name+'&website='+website+'&post='+post+'&ajim_auth='+authed;
       
   613     else       var parms = 'name='+name+'&website='+website+'&post='+post;
       
   614     r.open('POST', path+'?title=null&ajimmode=post&id='+<?php echo $_GET['id']; ?>id+'', true);
       
   615     r.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
       
   616     r.setRequestHeader("Content-length", parms.length);
       
   617     r.setRequestHeader("Connection", "close");
       
   618     r.send(parms);
       
   619   }
       
   620   
       
   621   function <?php echo $_GET['id']; ?>_form() {
       
   622     var name = document.getElementById(<?php echo $_GET['id']; ?>id+'_name').value;
       
   623     var website = document.getElementById(<?php echo $_GET['id']; ?>id+'_website').value;
       
   624     var post = document.getElementById(<?php echo $_GET['id']; ?>id+'_post').value;
       
   625     if(name.length < 1) { alert('Please enter your name.'); return; }
       
   626     if(post.length < 1) { alert('Please enter a post.'); return; }
       
   627     <?php echo $_GET['id']; ?>setCookie('ajim_name', name, 60*60*24*365*10);
       
   628     <?php echo $_GET['id']; ?>setCookie('ajim_website', website, 60*60*24*365*10);
       
   629     <?php echo $_GET['id']; ?>_submit(name, website, post);
       
   630     document.getElementById(<?php echo $_GET['id']; ?>id+'_post').value = '';
       
   631   }
       
   632   
       
   633   
       
   634   function <?php echo $_GET['id']; ?>_keyhandler(e)
       
   635   {
       
   636     if(!e) e = window.event;
       
   637     if(e.keyCode == 13)
       
   638     {
       
   639       val = document.getElementById(<?php echo $_GET['id']; ?>id+'_post').value;
       
   640       if(!shift)
       
   641       {
       
   642         document.getElementById(<?php echo $_GET['id']; ?>id+'_post').value = val.substr(0, val.length - 1);
       
   643         <?php echo $_GET['id']; ?>_form();
       
   644       }
       
   645     }
       
   646   }
       
   647   
       
   648   function <?php echo $_GET['id']; ?>keysensor(event)
       
   649   {
       
   650     if (event.shiftKey==1)
       
   651     {
       
   652       shift = true;
       
   653     }
       
   654     else
       
   655     {
       
   656       shift = false;
       
   657     }
       
   658   }
       
   659   
       
   660   if(window.onkeydown)
       
   661   {
       
   662     var kttemp = window.onkeydown;
       
   663     window.onkeydown = function(e) { kttemp(e); <?php echo $_GET['id']; ?>keysensor(e); }
       
   664   } else {
       
   665     window.onkeydown = function(e) { <?php echo $_GET['id']; ?>keysensor(e); }
       
   666   }
       
   667   
       
   668   if(window.onkeyup)
       
   669   {
       
   670     var kttemp = window.onkeyup;
       
   671     window.onkeyup = function(e) { kttemp(e); <?php echo $_GET['id']; ?>keysensor(e); }
       
   672   } else {
       
   673     window.onkeyup = function(e) { <?php echo $_GET['id']; ?>keysensor(e); }
       
   674   }
       
   675   
       
   676   function <?php echo $_GET['id']; ?>_edit_post(pid)
       
   677   {
       
   678     if(<?php echo $_GET['id']; ?>editlist[pid])
       
   679     {
       
   680       var r = <?php echo $_GET['id']; ?>_newReq(function() {
       
   681         if(r.readyState == 4) {
       
   682            document.getElementById('<?php echo $_GET['id']; ?>_post_'+pid).innerHTML = r.responseText;
       
   683            document.getElementById('<?php echo $_GET['id']; ?>_editbtn_'+pid).innerHTML = 'Edit';
       
   684            ajim_editlevels--;
       
   685            <?php echo $_GET['id']; ?>editlist[pid] = false;
       
   686            if(ajim_editlevels < 1)
       
   687             {
       
   688               <?php echo $_GET['id']; ?>interval = setInterval('<?php echo $_GET['id']; ?>_refresh();', 5000);
       
   689             }
       
   690         }
       
   691       });
       
   692       if(authed) r.open('GET', path+'?title=null&ajimmode=getpost&id='+<?php echo $_GET['id']; ?>id+'&pfx='+pfx+'&p='+pid+'&ajim_auth='+authed, true);
       
   693       else       r.open('GET', path+'?title=null&ajimmode=getpost&id='+<?php echo $_GET['id']; ?>id+'&pfx='+pfx+'&p='+pid, true);
       
   694       r.send(null);
       
   695     } else {
       
   696       clearInterval(<?php echo $_GET['id']; ?>interval);
       
   697       var r = <?php echo $_GET['id']; ?>_newReq(function() {
       
   698         if(r.readyState == 4) {
       
   699            document.getElementById('<?php echo $_GET['id']; ?>_post_'+pid).innerHTML = '<textarea rows="4" cols="17" id="<?php echo $_GET['id']; ?>_editor_'+pid+'">'+r.responseText+'</textarea><br /><a href="#" onclick="<?php echo $_GET['id']; ?>_save_post(\''+pid+'\'); return false;" style="font-size: 7pt; color: #00C000;">save</a>';
       
   700            document.getElementById('<?php echo $_GET['id']; ?>_editbtn_'+pid).innerHTML = 'Cancel';
       
   701            ajim_editlevels++;
       
   702            <?php echo $_GET['id']; ?>editlist[pid] = true;
       
   703         }
       
   704       });
       
   705       if(authed) r.open('GET', path+'?title=null&ajimmode=getsource&id='+<?php echo $_GET['id']; ?>id+'&pfx='+pfx+'&p='+pid+'&ajim_auth='+authed, true);
       
   706       else       r.open('GET', path+'?title=null&ajimmode=getsource&id='+<?php echo $_GET['id']; ?>id+'&pfx='+pfx+'&p='+pid, true);
       
   707       r.send(null);
       
   708     }
       
   709   }
       
   710   
       
   711   var ajim_global_pid;
       
   712   function <?php echo $_GET['id']; ?>_save_post(pid) {
       
   713     ajim_global_pid = pid;
       
   714     if(!document.getElementById('<?php echo $_GET['id']; ?>_editor_'+pid))
       
   715     {
       
   716       alert('AjIM internal error: bad post ID '+pid+': editor is not open');
       
   717       return false;
       
   718     }
       
   719     var r = <?php echo $_GET['id']; ?>_newReq(function() {
       
   720       if(r.readyState == 4)
       
   721       {
       
   722         ajim_editlevels--;
       
   723         <?php echo $_GET['id']; ?>editlist[pid] = false;
       
   724         document.getElementById('<?php echo $_GET['id']; ?>_editbtn_'+ajim_global_pid).innerHTML = 'Edit';
       
   725         document.getElementById('<?php echo $_GET['id']; ?>_post_'+ajim_global_pid).innerHTML = r.responseText;
       
   726         if(ajim_editlevels < 1)
       
   727         {
       
   728           <?php echo $_GET['id']; ?>_refresh(true);
       
   729           <?php echo $_GET['id']; ?>interval = setInterval('<?php echo $_GET['id']; ?>_refresh();', 5000);
       
   730         }
       
   731       }
       
   732     });
       
   733     var parms = 'post='+escape(document.getElementById('<?php echo $_GET['id']; ?>_editor_'+pid).value.replace('+', '%2B'))+'&ajim_auth='+authed+'&p='+pid;
       
   734     r.open('POST', path+'?title=null&ajimmode=savepost&id='+<?php echo $_GET['id']; ?>id+'', true);
       
   735     r.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
       
   736     r.setRequestHeader("Content-length", parms.length);
       
   737     r.setRequestHeader("Connection", "close");
       
   738     r.send(parms);
       
   739     return null;
       
   740   }
       
   741   
       
   742   function <?php echo $_GET['id']; ?>_delete_post(pid) {
       
   743     //document.getElementById(<?php echo $_GET['id']; ?>id+'_admin').innerHTML = '<span style="font-family: arial; font-size: 7pt; ">Loading...</span>';
       
   744     var r = <?php echo $_GET['id']; ?>_newReq(function() {
       
   745        if(r.readyState == 4)
       
   746          if(r.responseText=="good") {
       
   747            <?php echo $_GET['id']; ?>_refresh(true);
       
   748          } else alert(r.responseText);
       
   749     });
       
   750     var parms = 'ajim_auth='+authed+'&p='+pid;
       
   751     r.open('POST', path+'?title=null&ajimmode=delete&id='+<?php echo $_GET['id']; ?>id+'', true);
       
   752     r.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
       
   753     r.setRequestHeader("Content-length", parms.length);
       
   754     r.setRequestHeader("Connection", "close");
       
   755     r.send(parms);
       
   756     return null;
       
   757   }
       
   758   
       
   759   <?php
       
   760 } elseif(isset($_GET['jsadmin']) && isset($_GET['id']) && isset($_GET['path'])) {
       
   761   header('Content-type: text/javascript');
       
   762   ?>
       
   763   
       
   764   var abuffer;
       
   765   function <?php echo $_GET['id']; ?>_prompt() {
       
   766     abuffer = document.getElementById(<?php echo $_GET['id']; ?>id+'_admin').innerHTML;
       
   767     document.getElementById(<?php echo $_GET['id']; ?>id+'_admin').innerHTML = '<form action="javascript:void(0)" onsubmit="'+<?php echo $_GET['id']; ?>id+'_login()" method="get"><span style="font-family: arial; font-size: 7pt; ">Password:</span>  <input style="font-family: arial; font-size: 7pt; border: 1px solid #000; height: 15px; width: 65px" id="'+<?php echo $_GET['id']; ?>id+'_passfield" name="pass" type="password" /> <input style="font-family: arial; font-size: 7pt; border: 1px solid #000; height: 15px; width: 65px" type="submit" value="OK" /></form>';
       
   768   }
       
   769   
       
   770   function <?php echo $_GET['id']; ?>_login() {
       
   771     pass = document.getElementById(<?php echo $_GET['id']; ?>id+'_passfield').value;
       
   772     pass = hex_md5(pass);
       
   773     <?php echo $_GET['id']; ?>_login_bin(pass);
       
   774   }
       
   775   function <?php echo $_GET['id']; ?>_login_bin(pass) {
       
   776     document.getElementById(<?php echo $_GET['id']; ?>id+'_admin').innerHTML = '<span style="font-family: arial; font-size: 7pt; ">Loading...</span>';
       
   777     var r = <?php echo $_GET['id']; ?>_newReq(function() {
       
   778        if(r.readyState == 4)
       
   779        {
       
   780          if(r.responseText=="good") {
       
   781            authed = pass;
       
   782            <?php echo $_GET['id']; ?>setCookie('ajim_password', authed, 60*60*24*365*10);
       
   783            <?php echo $_GET['id']; ?>_latestpost = 0;
       
   784            <?php echo $_GET['id']; ?>_refresh(true);
       
   785            document.getElementById(<?php echo $_GET['id']; ?>id+'_admin').innerHTML = '';
       
   786          }
       
   787          else
       
   788          {
       
   789            alert(r.responseText); 
       
   790            document.getElementById(<?php echo $_GET['id']; ?>id+'_admin').innerHTML = '<span style="font-family: arial; font-size: 7pt; color: #ff0000">Invalid password!</span><br />'+abuffer;
       
   791          }
       
   792        }
       
   793     })
       
   794     var parms = 'ajim_auth='+pass;
       
   795     r.open('POST', path+'?title=null&ajimmode=auth&id='+<?php echo $_GET['id']; ?>id+'', true);
       
   796     r.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
       
   797     r.setRequestHeader("Content-length", parms.length);
       
   798     r.setRequestHeader("Connection", "close");
       
   799     r.send(parms);
       
   800   }
       
   801   
       
   802   var hexcase = 0; var b64pad  = ""; var chrsz   = 8; function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}; function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}; function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}; function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }; function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }; function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }; function md5_vm_test() { return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; }; function core_md5(x, len) { x[len >> 5] |= 0x80 << ((len) % 32); x[(((len + 64) >>> 9) << 4) + 14] = len; var a =  1732584193; var b = -271733879; var c = -1732584194; var d =  271733878; for(var i = 0; i < x.length; i += 16) { var olda = a; var oldb = b; var oldc = c; var oldd = d; a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);c = md5_ff(c, d, a, b, x[i+10], 17, -42063);b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); a = safe_add(a, olda); b = safe_add(b, oldb); c = safe_add(c, oldc); d = safe_add(d, oldd); } return Array(a, b, c, d); }; function md5_cmn(q, a, b, x, s, t) { return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); }; function md5_ff(a, b, c, d, x, s, t) { return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); }; function md5_gg(a, b, c, d, x, s, t) { return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); }; function md5_hh(a, b, c, d, x, s, t) { return md5_cmn(b ^ c ^ d, a, b, x, s, t); }; function md5_ii(a, b, c, d, x, s, t) { return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); }; function core_hmac_md5(key, data) { var bkey = str2binl(key); if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz); var ipad = Array(16), opad = Array(16); for(var i = 0; i < 16; i++) { ipad[i] = bkey[i] ^ 0x36363636; opad[i] = bkey[i] ^ 0x5C5C5C5C; } var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz); return core_md5(opad.concat(hash), 512 + 128); }; function safe_add(x, y) {var lsw = (x & 0xFFFF) + (y & 0xFFFF);var msw = (x >> 16) + (y >> 16) + (lsw >> 16);return (msw << 16) | (lsw & 0xFFFF); }; function bit_rol(num, cnt) { return (num << cnt) | (num >>> (32 - cnt)); }; function str2binl(str) { var bin = Array(); var mask = (1 << chrsz) - 1; for(var i = 0; i < str.length * chrsz; i += chrsz) bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32); return bin; }; function binl2str(bin) { var str = ""; var mask = (1 << chrsz) - 1; for(var i = 0; i < bin.length * 32; i += chrsz) str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask); return str; }; function binl2hex(binarray) { var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var str = ""; for(var i = 0; i < binarray.length * 4; i++) { str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF); } return str; }; function binl2b64(binarray) { var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var str = ""; for(var i = 0; i < binarray.length * 4; i += 3) { var triplet = (((binarray[i >> 2] >> 8 * ( i   %4)) & 0xFF) << 16) | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 ) |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF); for(var j = 0; j < 4; j++) { if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); } } return str; };
       
   803   
       
   804   <?php
       
   805 } elseif(isset($_GET['css']) && isset($_GET['id']) && isset($_GET['path'])) {
       
   806   header('Content-type: text/css');
       
   807   ?>
       
   808   div#<?php echo $_GET['id']; ?>_master {
       
   809     margin: 0;
       
   810     padding: 0;
       
   811     /* background-color: #DDD; */
       
   812   }
       
   813   div#<?php echo $_GET['id']; ?>_master a {
       
   814     display: inline;
       
   815     color: #0000FF;
       
   816   }
       
   817   div#<?php echo $_GET['id']; ?>_master textarea {
       
   818     font-family: arial;
       
   819     font-size: 7pt;
       
   820     border: 1px solid #000;
       
   821     padding: 0;
       
   822   }
       
   823   <?php
       
   824 }
       
   825 ?>