root > WikiSense-trunk > web > CommonSense.php

CommonSense.php

application/x-php, 63368 bytes (load raw)
<?
if (@$argv[1]==='--test=CommonSense' && !@$_SERVER['REQUEST_URI'] && !defined('WS_WEB')) {
    define('WS_CONSOLE',1);
    define('WS_TEST_COMMON_SENSE',1);
}
else {
    define("WS_WEB",true);
}

require_once( "common/WebInit.php" );
require_once( "common/FilterCats.php" );

require_once("WikiAccess.php");
require_once("WikiSenseLocalizer.php");

define('COMMONS_LINK_PATTERN','/\[\[ *:?commons:([^\|\:\]]+:)*([^\]\|]+)(\|[^\]]*)? *\]\]|\{\{ *(Commons[12]?|Commons? ?Cat|Commons ?Category|Commons-inline|Catlst commons|Cms-catlist-up) *\| *([^\|\:\}]+:)*([^\|\}]+)( *\| *([^\}]*))? *\}\}/smi');

define('CATEGORY_REDIRECT_PATTERN','/\{\{ *(seecat|catred|category_redirect|category redirect) *\| *(.*?) *\}\}/is');

$commonsLicenseCategories= array(
  'GFDL',
  'GPL',
  'LGPL',
  'Public_domain',
  'PD',
  'PD-self',
  'PD-user',
  'PD_Old',
  'PD_Art',
  'PD_US',
  'PD_US_Government',
  'PD_NASA',
  'PD_US_Military',
  'Patents',
  'Russian_official_symbols',
  'PD_Soviet',
  'CC-BY-SA-2.5',
  'CC-BY-SA-2.1',
  'CC-BY-SA-2.0',
  'CC-BY-SA-1.0',
  'CC-SA-1.0',
  'CC-BY-1.0',
  'CC-BY-2.0',
  'CC-BY-2.5',
  'BSD_images',
  'Copyrighted_free_use',
  'Copyrighted_free_use_provided_that',
  'Self-published_work',
  'Unknown',
  'Own_work',
  'Incomplete_license',
  'Unknown',
  #much much more....
);

class CommonSensePage {
        var $enwiki;
        var $commons;
       
        var $projects;
        var $wikis;
        var $mainWiki;
       
        var $imageUses;
        var $usedWikis;
        var $keywordWikis;
       
        var $hashCounter;
        var $verbosity;
       
        var $image;
        var $imageInfo;
        var $keywords;
        var $keywordlang;
       
        var $pageTitle;
        var $pageInfo;
        var $processed;
       
        var $categoryBlacklist;
        var $stripRedundant;
       
        var $sqlDebug;
        var $errors;
       
        var $messages;

        function CommonSensePage ( $lang, $image, $keywords = NULL, $keywordlang = NULL ) {
                global $wsgCommonSenseText;
                $this->messages= $wsgCommonSenseText;
       
                $this->image= $image;
                $this->imageInfo= NULL;
               
                $this->hashCounter= 0;
                $this->verbosity= 1;
               
                $this->stripRedundant= true;

                $this->connections = array();
               
                if ($keywords) {
                  if (!is_array($keywords)) {
                      $keywords= preg_replace('/"(.*?)"/e','str_replace(" ","_",\'\1\')',$keywords);
                     
                      $k= preg_split('/[\r\n]+/',$keywords);
                      $keywords= preg_split('"[/\.!\?:#,;|/\s]+"',$keywords);
                     
                      if (sizeof($keywords>1)) {
                          foreach ($k as $s) {
                              if (preg_match('"[/\.!\?:#,;|/]+"',$s)) continue;
                              $keywords[]= str_replace(' ','_',$s);
                          }
                      }
                     
                      $keywords= array_unique($keywords);
                  }
                 
                  $this->keywords= $keywords;
                  $this->keywordlang= $keywordlang;
                }
       
                $this->enwiki=& WikiAccess::newInstance( 'en.wikipedia.org' );
                $this->commons=& WikiAccess::newInstance( 'commons.wikimedia.org' );
               
                #$this->commonsInfo= getWikiInfoFromDomain( 'commons.wikimedia.org' );
               
                if (!$this->enwiki->wikiDB) {
                  $this->error($this->msg('db_connect_error_1','en.wikipedia.org'));
                  die();
                }
               
                if (!$this->commons->wikiDB) {
                  $this->error($this->msg('db_connect_error_1','commons.wikimedia.org'));
                  die();
                }

                $this->putDbConnection($this->enwiki);
                $this->putDbConnection($this->commons);
               
                $lang= strtolower($lang);
                $this->projects= $lang;

                $this->trace(2,"using projects $lang");
               
                $ll= preg_split('!\s*[\s,;/|]\s*!smi',$lang);
           
                $this->wikis= array();
                $this->mainWiki= NULL;
                $this->usedWikis= NULL;
                $this->keywordWikis= NULL;
                $this->imageUses= NULL;
                $this->errors= array();
               
                foreach ($ll as $l) {
                  if (!$l) continue;
               
                  $inf= getWikiInfoFromDomain( $l );
                  if ($inf && $inf->domain) {
                      $db = $this->getDbConnection( $inf );
                      $this->wikis[$inf->domain]= WikiAccess::newInstance( $inf, $db );
                  }
                  else $this->error($this->msg('unknown_project_error_1',$l));
                }
               
                if ( sizeof($this->wikis) === 1 )  {
                  $k= array_keys($this->wikis);
                  $this->mainWiki= $this->wikis[$k[0]];
                }
               
                #print_r($this->wikis);
                #print_r($this->commons);
                #print_r($this->enwiki);
                               
                $this->pageTitle= array();
                $this->pageInfo= array();
                $this->processed= array();
               
                $this->sqlDebug= false;
               
                $this->categoryBlacklist= array(
                  "Fundamental",
                  "Reference",
                  "ArticleType",
                  "CommonsRoot",
                  "Copyright_statuses",
                  "Image_sources",
                  "MediaType",
                  "Disambiguation",
                  "User",
                  "Other",
                  "Objects",
                  "Wikipedia_bots",
                  "Commons",
                  "Commons_maintenance",
                  "Images",
                  "Movies",
                  "Sound",
                  "Videdo",
                  "Unknown",
                  "Flickr",
                  "Animation",
                  "Illustrations",
                  "Image format",
                  "Images by text",
                  "Photos",
                  "Pictures_of_the_day",
                  "SVG",
                  "Featured pictures",
                  "Drawings",
                  "Audio",
                  "Spoken_wikipedia",
                  "Multi-channel_sound",
                  "Meyers_Blitz-Lexikon",
                 
                  "Languages",
                 
                  #THis list would be huge... find a better solution
                  "Commons-en",
                  "Commons-de",
                  "Commons-fr",
                  "Commons-es",
                  "Commons-pl",
                  "Commons-jp",
                  "Commons-zh",
                  "Commons-ru",
                  "Commons-nl",
                 
                  #That'S OK on the commons, but often used differntly in WPs (pl "album" pages, etc)
                  "Photography",
                 
                  #FIXME: this sucks - used for meta-stuff on most 'pedias, but not on commons :(
                  "Wikipedia", "Wikimedia", "Logos", "Stubs", "Lists",
                 
                  #FIXME: a ton more of the below, in all the languages...
                  "Deletion requests", "Candidates for speedy deletion",
                );
               
                #TODO: filter out all the "main pages" (all languages)
               
                global $commonsLicenseCategories;
                $this->categoryBlacklist= array_merge($this->categoryBlacklist,$commonsLicenseCategories);
        }

        function putDbConnection($wiki) {
                if (@$this->connections[$wiki->dbServerId]) return; //XXX: ping?

                if (!@$wiki->wikiDB) throw new Exception("no wiki db");
                if (!@$wiki->dbServerId) throw new Exception("no server id");
                $this->connections[$wiki->dbServerId] = $wiki->wikiDB;
        }
       
        function getDbConnection($wiki) {
                if (!$wiki) throw new Exception("no wiki specified");
                if (isset($wiki->wikiDB)) return $wiki->wikiDB;

                $server = isset($wiki->dbServerId) ? $wiki->dbServerId : $wiki->server;

                if (!isset($this->connections[$server])) {
                        $w =& WikiAccess::newInstance($wiki); //HACK: don't really need a WikIAccess instance here...
                        $this->putDbConnection($w);
                }

                if (!isset($this->connections[$server])) throw new Exception("failed to get connection for server #"+$server);
                return $this->connections[$server];
        }
       
        function msg($key) {
            $args= func_get_args();
            return call_user_func_array ( array(&$this->messages, 'msg'), $args );
        }
       
        function close() {
          foreach ($this->connections as $id => $db) {
              $db->close();
          }

          #$this->commons->close();
          #$this->enwiki->close();
        }
       
        function stringValue($data) {
          if (is_null($data)) $data= "<null>";
          else if ($data===false) $data= "<false>";
          else if ($data===true) $data= "<true>";
          else if (is_object($data)) $data= get_object_vars($data);
         
          if (is_array($data)) {
            $s= "{";
            foreach ( $data as $k => $v ) {
              $s.= "$k => ".CommonSensePage::stringValue($v).", ";
            }
           
            $s.= "}";
            $data= $s;
          }
         
          return $data;
        }
       
        function sqlTrace($sql) {
            if (!$this->sqlDebug) return;
           
            print "\n<p style='fount-size:72%'>".escapeHtml($sql)."</p>\n";
        }
       
        function trace($level, $msg, $data='@dummy@') {
          if (!headers_sent()) return;
         
          if ( $level <= $this->verbosity ) {
              if ($data==='@dummy@') $data= '';
              else $data= " (".CommonSensePage::stringValue($data).")";
             
              if ( $this->hashCounter > 0 ) {
                print "<br/>\n";
                $this->hashCounter= 0;
              }
             
              print " ".str_repeat("&ndash;",$level)." ".escapeHtml($msg . $data) . "<br/>\n";
          }
          else if ( ( $level - 2 ) <= $this->verbosity ) {
            print ". ";
            $this->hashCounter+= 1;
          }
         
          flush();
        }
       
        function error($msg, $die = false) {
          if ($die) die($msg);
         
          if (!headers_sent()) $this->errors[]= $msg;
          else {
            print "\n<p class='error'>".escapeHtml($msg)."<p>\n";
          }
         
          flush();
        }
       
        function findCategories() {
          $gals= array();
          $cats= array();
         
          $pages= array();
         
          if ($this->keywords) {
              $p= $this->findKeywordPages();
              if ($p) $pages= array_merge($pages,$p);
          }
         
          if ($this->image) {
              $p= $this->findImageUses();
              if ($p) $pages= array_merge($pages,$p);
          }
         
          #print_r($pages);
          $this->trace(1,"searching fro commons categories...");

          foreach ( $pages as $p ) {
            if (sizeof($cats)>10 || sizeof($gals)>10) {
              $this->trace(2,"found enough entries, aborting search");
              break;
            }
           
            if ($p['domain']=='commons.wikimedia.org') {
                $this->trace(3,"direct match on commons: ".$p['title']."(".$p['namespace'].")");
               
                if ($p['namespace']==NS_CATEGORY) $cats[]= $p['title'];
                else $gals[]= $p['title'];
            }
            else {
              $wiki=& $this->wikis[$p['domain']];
             
              $this->processPage($wiki, $p['title'], $p['namespace'], $gals, $cats, 4 );
            }
          }
         
          $this->trace(1,"post-processing");
         
          $gals= array_unique($gals);
         
          foreach ($gals as $g) {
            $info= $this->loadPageInfo( $this->commons, $g, NS_MAIN );
            if ($info && $info['categories']) {
              $this->trace(2,"adding categories from gallery page $g",$info['categories']);
              $cats= array_merge($cats,$info['categories']);
            }
          }
         
          $cats= array_unique($cats);
          $cats= array_diff($cats,$this->categoryBlacklist);

          if ($this->stripRedundant) {
            foreach ($cats as $c) {
              $this->stripRedundantCategories($c,$cats,3);
            }
          }
         
          return array(
            'galleries' => $gals,
            'categories' => $cats
          );
        }
       
        function stripRedundantCategories( $root, &$cats, $depth ) {
          if ($depth==0) return;

          global $wsgFilterCatDB;

          if ($wsgFilterCatDB && isset($wsgFilterCatDB['commons.wikimedia.org'])) {
              $db = $wsgFilterCatDB['commons.wikimedia.org'];
              $r = filter_categories($cats, $db);

              foreach ($cats as $k => $c) {
                  if (!in_array($c, $r['new'])) unset($cats[$k]);
              }
              return;
          }
         
          $info= $this->loadPageInfo($this->commons,$root,NS_CATEGORY);
         
          if (!@$info['categories']) return;
         
          $this->trace(2,"stripping categories (parents of $root):",$info['categories']);
          $info['categories']= array_diff($info['categories'], array($root)); //ugly - should not be needed.
          $cats= array_diff($cats, $info['categories']);
         
          #FIXME: this *may* strip *all* categories, if the structure contains loops.
          foreach ( $info['categories'] as $c ) {
            $this->stripRedundantCategories( $c, $cats, $depth -1 );
          }
        }
       
        function findKeywordPages() {
            $pages= array();
         
            $this->keywordWikis= array();
           
            $wikis= array();
            $wikis['commons.wikimedia.org']= @$this->commons;
            $wikis= array_merge($wikis,$this->wikis);
         
            foreach ($wikis as $domain => $wiki) {
                $this->trace(1,"looking for keywords on ".$wiki->domain." wiki");
               
                $found= false;
               
                foreach ($this->keywords as $ttl) {
                    $ttl= trim($ttl);
                    if (!$ttl) continue;
               
                    if ( $t= $this->getPageTitle( $wiki, $ttl, NS_MAIN ) ) {
                      unset($p);
                      $p= array(
                        'domain' => $domain,
                        'title' => $t,
                        'namespace' => NS_MAIN,
                      );
                     
                      $pages[]=& $p;
                     
                      if (!isset($this->keywordWikis[$wiki->domain])) $this->keywordWikis[$wiki->domain]= array();
                      $this->keywordWikis[$wiki->domain][]= $p;
                     
                      $this->trace(3,"keyword ".$t." found on ".$wiki->domain);
                    }
                   
                    if ( $t= $this->getPageTitle( $wiki, $ttl, NS_CATEGORY ) ) {
                      unset($p);
                      $p= array(
                        'domain' => $domain,
                        'title' => $t,
                        'namespace' => NS_CATEGORY,
                      );
                     
                      $pages[]=& $p;
                     
                      if (!isset($this->keywordWikis[$wiki->domain])) $this->keywordWikis[$wiki->domain]= array();
                      $this->keywordWikis[$wiki->domain][]= $p;
                     
                      $this->trace(3,"keyword ".$t." found as category on ".$wiki->domain);
                    }
             
                    if (sizeof($pages)>10) {
                      $this->trace(2,"found enough keyword uses, stopping search");
                      break;
                    }
                }
               
                if (sizeof($pages)>10) break;
            }
           
            #print_r($pages);
           
            return $pages;
        }
       
        function findImageUses() {
          if (!is_null($this->imageUses)) return $this->imageUses;
       
          $pages= array();
          $this->usedWikis= array();
             
          #print_r($this->wikis);
       
          foreach (array_keys($this->wikis) as $l) {
              $wiki=& $this->wikis[$l];
              $db = $this->getDbConnection($wiki);
             
              if ($this->imageInfo) {
                  $info= $this->loadImageInfo($wiki,$this->image);
                 
                  if ($info) {
                      if ( $info->img_size != $this->imageInfo->img_size
                              || $info->img_width != $this->imageInfo->img_width
                              || $info->img_height != $this->imageInfo->img_height
                              || $info->img_minor_mime != $this->imageInfo->img_minor_mime
                              || $info->img_metadata  != $this->imageInfo->img_metadata ) {
                             
                              $this->trace(2,"image is shadowed locally on ".$wiki->domain.", skipping");
                              continue;
                      }
                  }
              }
             
              $this->trace(1,"looking for usage on ".$wiki->domain." wiki");
             
              #print "findImageUses:W: $wiki ;";
              #print "findImageUses:DB: ".$db." ;";
             
              $img= $wiki->asDBKey($this->image);
         
              $sql= "SELECT il_from, page_title, page_namespace
                    FROM "
.$wiki->dbname.".imagelinks
                    JOIN "
.$wiki->dbname.".page ON page_id = il_from
                    WHERE page_namespace = 0
                    AND il_to = "
. $db->addQuotes( $img )."
                    LIMIT 16"
; #16 should be enough for categoprization.
         
              $this->sqlTrace($sql);
              $res= $db->query( $sql, 'findImageUses' );
             
              while ( $row = $db->fetchRow($res) ) {
                unset($p);
                $p= array(
                  'domain' => $wiki->domain,
                  'id' => $row['il_from'],
                  'title' => $row['page_title'],
                  'namespace' => $row['page_namespace']
                );
               
                $pages[]=& $p;
               
                if (!isset($this->usedWikis[$wiki->domain])) $this->usedWikis[$wiki->domain]= array();
                $this->usedWikis[$wiki->domain][]= $p;
               
                $this->trace(3,"image ".$this->image." used on ".$wiki->domain.":".$row['page_title']);
              }
             
              $db->freeResult( $res );
             
              if (sizeof($pages)>10) {
                $this->trace(2,"found enough image uses, stopping search");
                break;
              }
          }
         
          $this->imageUses= $pages;
          return $pages;
        }
       
        function randomImage() {
          #print_r($this->wikis);
       
          $l= array_rand($this->wikis,1);
          $wiki=& $this->wikis[$l];
          $db = $this->getDbConnection($wiki);
         
          if (!$wiki) return NULL;
         
          $sql= 'select img_name
                 from '
.$wiki->dbname.'.image
                 join page use index(page_random) on page_title = img_name
                 where page_random > '
.(rand()/getrandmax()).' order by page_random limit 1';
                 
          #print "W: $wiki ;";
          #print "DB: ".$db." ;";
       
          $this->sqlTrace($sql);
          $res= $db->query( $sql, 'randomImage' );
         
          if ( $row = $db->fetchRow($res) ) {
            $this->image= $row['img_name'];
          }
         
          $db->freeResult( $res );
         
          $this->mainWiki= $wiki;
         
          return $this->image;
        }
       
        function randomUncategorizedCommonsImage() {
          $db = $this->getDbConnection($this->commons);
          extract( $db->tableNames( 'page', 'image', 'imagelinks', 'categorylinks' ) );
         
          global $commonsLicenseCategories;
         
          $ignoreCats= '';
          foreach ($commonsLicenseCategories as $c) {
            if ($ignoreCats) $ignoreCats.= ', ';
            $ignoreCats.= $db->addQuotes($c);
          }
   
          $sql'SELECT I.page_title as title
                  FROM page AS I USE INDEX(page_random)
                  LEFT JOIN categorylinks AS L ON (I.page_id = L.cl_from AND L.cl_to NOT IN ('
.$ignoreCats.')) 
                  LEFT JOIN ( imagelinks AS P JOIN page as A ON A.page_id = P.il_from AND A.page_namespace = 0 ) ON I.page_title = P.il_to
                  WHERE I.page_namespace = '
.NS_IMAGE.' AND L.cl_from IS NULL AND P.il_to IS NULL
                  AND I.page_random > '
.(rand()/getrandmax()).' ORDER BY I.page_random LIMIT 1
                  '
;

          /*           
          $sql=  'SELECT img_name as title, img_user, img_user_text, img_timestamp as value, img_description
                  FROM '.$page.' AS I USE INDEX(page_random)
                       LEFT JOIN '.$categorylinks.' AS L ON I.page_id = L.cl_from AND L.cl_to NOT IN ('.$ignoreCats.')
                       LEFT JOIN '.$imagelinks.' AS P ON I.page_title = P.il_to AND I.page_namespace = 0
                       INNER JOIN '.$image.' AS G ON I.page_title = G.img_name
                  WHERE I.page_namespace = '.NS_IMAGE.' AND L.cl_from IS NULL AND P.il_to IS NULL
                    AND I.page_random > '.(rand()/getrandmax()).' ORDER BY I.page_random LIMIT 1';
          */

          $this->sqlTrace($sql);
          $res= $db->query( $sql, 'randomImage' );
         
          if ( $row = $db->fetchRow($res) ) {
            $this->image= $row['title'];
          }
         
          $db->freeResult( $res );
         
          $this->mainWiki= $this->commons;
         
          return $this->image;
        }
       
        function processPage( &$wiki, $title, $ns, &$gals, &$cats, $depth ) {
          $info= NULL;
         
          $k= $wiki->domain.":$ns:$title";
          list($d, $r)= @$this->processed[$k];
         
          if ($d>=$depth) {
            //$this->trace(1,"SKIPPING processing ".$wiki->domain.": ($ns) $title  (depth: $depth): CACHED: ".$this->stringValue($r));
            return $r;
          }
         
          $this->processed[$k]= array($depth, true); //FIXME: may be misleading (self-fulfilling) if loops are encountered
         
          $this->trace(1,"processing ".$wiki->domain.": ($ns) $title  (depth: $depth)");
         
          $info= $this->loadPageInfo($wiki, $title, $ns);
          if (!$info) {
            $this->processed[$k]= array($depth, false);
            return false;
          }
         
          if ( $wiki->domain != 'en' && $wiki->domain != 'en.wikipedia.org' ) {
            if ( isset($info['english']) && !is_null($info['english']) &&  $this->processPage( $this->enwiki, $info['english'], $ns, $gals, $cats, 1 ) ) {
              if ( ! @$info['commons'] ) return true; #note: keep going for direct commons links
            }
          }
         
          $titles= array( $title );
          if ( @$info['commons'] ) {
            $this->trace(2,"found commons links",$info['commons']);
            $titles= array_merge($titles,$info['commons']);
          }
         
          $found= false;
         
          foreach ($titles as $ttl) {
              if ( $t= $this->getCommonsTitle( $ttl, NS_MAIN ) ) {
                $gals[]= $t;
                $found= true;
              }
             
              if ( $t= $this->getCommonsTitle( $ttl, NS_CATEGORY ) ) {
                $cats[]= $t;
                $this->processed[$k]= array($depth, true);
                $found= true;
              }
          }
         
          if ($found) {
            $this->processed[$k]= array($depth, true);
            return true;
          }
         
          if ( $depth <= 1 ) {
            $this->processed[$k]= array($depth, false);
            return false;
          }
         
          if ( @$info['categories'] ) {
            foreach ( $info['categories'] as $c ) {
              if ( $this->processPage( $wiki, $c, NS_CATEGORY, $gals, $cats, $depth-1 ) )
                  $found= true;
            }
          }
         
          if ($found) {
            $this->processed[$k]= array($depth, true);
            return true;
          }

          #if nothing was found, deep-scan english version (FIXME: root level only?!)         
          if ( !$found && isset($info['english']) && !is_null($info['english']) && $wiki->domain != 'en.wikipedia.org') {
            if ( $this->processPage( $this->enwiki, $info['english'], $ns, $gals, $cats, $depth ) ) {
              $this->processed[$k]= array($depth, true);
              return true;
            }
          }
         
          $this->processed[$k]= array($depth, $found);
          return $found;
        }
       
        function getCommonsTitle( $title, $ns ) {
            return $this->getPageTitle( $this->commons, $title, $ns );
        }
       
        function getPageTitle( &$wiki, $title, $ns ) {
          $title= $this->commons->asDBKey($title); #FIXME: use which connection? ucfirst?
          $k= "{$wiki->dbname}:$ns:$title";
         
          if (array_key_exists($k, $this->pageTitle)) return $this->pageTitle[$k];
         
          $db = $this->getDbConnection($wiki);

          $tries= 3;
         
          while ($tries) {
            $sql= "SELECT page_id, page_title, page_is_redirect
                  FROM "
.$wiki->dbname.".page
                  WHERE page_namespace = $ns
                  AND page_title = "
. $db->addQuotes( $this->commons->asDBKey($title) );
           
            $this->sqlTrace($sql);
            $res= $db->query( $sql, 'getPageTitle' );
           
            if ( ! ($row = $db->fetchRow($res)) ) {
              $this->trace(3,"NOT found on ".$wiki->domain.": ($ns) $title");
              $title= NULL;
              $tries= 0;
            }
            else if (!$row['page_is_redirect']) {
              #TODO: category-redirects: {{Categoryredirect|xxx}}, {{seecat|xxx}}, etc
               
              if ( $ns == NS_CATEGORY ) {
                  $info= $this->loadPageInfo($wiki, $title, $ns);
                 
                  #TODO: use wiki-specific cat-redirect pattern
                  $match= array();
                  if (preg_match(CATEGORY_REDIRECT_PATTERN,$info['text'],$match)) {
                      $tries-= 1;
                      if (!$tries) $title= NULL;
                      else {
                          $t= $match[2];
                          $this->trace(3,"FOUND CATEGORY REDIRECT on ".$wiki->domain.": ($ns) $title  ->  $t");
                         
                          $title= $t;
                      }
                  }
                  else {
                      $this->trace(3,"FOUND on ".$wiki->domain.": ($ns) $title");
                      $tries= 0;
                  }
              }
              else {
                  $this->trace(3,"FOUND on ".$wiki->domain.": ($ns) $title");
                  $tries= 0;
              }
            }
            else {
              $tries-= 1;
              if (!$tries) $title= NULL;
              else {
                $info= $this->loadPageInfo($wiki, $title, $ns);
                if (!$info) {
                  $this->trace(3,"found BAD on ".$wiki->domain.": ($ns) $title");
                  $title= NULL;
                  $tries= 0;
                }
                else {
                  $match= array();
                  if (!preg_match(REDIRECT_PATTERN,$info['text'],$match)) {
                    $this->trace(3,"found BAD redirect on ".$wiki->domain.": ($ns) $title; {$info['text']}");
                    $title= NULL;
                    $tries= 0;
                  }
                  else {
                    $t= $match[1];
                    $this->trace(3,"FOUND REDIRECT on ".$wiki->domain.": ($ns) $title  ->  $t");
                   
                    $title= $t;
                  }
                }
              }
            }
         
            $db->freeResult( $res );
          }
         
          $this->pageTitle[$k]= $title;
         
          #$this->trace(3,"TITLE on commons: ($ns) $title");
          return $title;
        }
       
        function loadImageInfo( &$wiki, $title ) {
          $title= $this->commons->asDBKey($title);
          $db = $this->getDbConnection($wiki);
       
          $this->trace(4,"loading image info for $title from [".$wiki->domain."]...");
         
          $sql= "SELECT * 
                FROM "
.$wiki->dbname.".image
                WHERE img_name = "
. $db->addQuotes( $title );
               
          $res= $db->query($sql);
         
          if ( ! $res ) {
            $this->trace(1,"failed to load image info for $title from [".$wiki->domain."]", $sql);
            $info= false;
          }

          if ( ! ($info = $db->fetchObject($res)) ) {
            $this->trace(4,"no image info for $title from [".$wiki->domain."]");
            #print "*** $sql ***";
            $info= false;
          }
         
          $db->freeResult($res);
          return $info;
        }
       
        function loadPageInfo( &$wiki, $title, $ns ) {
          $k= $wiki->domain.":$ns:$title";
          if (array_key_exists($k, $this->pageInfo)) return $this->pageInfo[$k];
         
          $fulltitle= $ns==0 ? $title : MWNamespace::getCanonicalName( $ns ) . ':' . $title; #fixme: ucfirst!
         
          $this->trace(4,"loading $fulltitle from [".$wiki->domain."]...");
         
          $db = $this->getDbConnection($wiki);

          #FIXME: ugly hack...
          global $wgLoadBalancer;
          $wgLoadBalancer= new PseudoLoadBalancer( $db );
         
          $info= $wiki->loadInfoFromDB( $title, $ns ); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
         
          if ( !$info ) {
            $this->trace(4,"failed to load $fulltitle from [".$wiki->domain."]");
            $this->pageInfo[$k]= false;
            return false;
          }
         
          $info['title']= $title;
          $info['namespace']= $ns;
          $info['fulltitle']= $fulltitle;
         
          if ( $wiki->domain != 'en.wikipedia.org') {
            $info['english']= $this->extractTranslation($info['text'], 'en');
          }
         
          #$this->trace(4,"loaded $fulltitle from [".$wiki->domain."]");
         
          $info['categories']= $this->getCategories( $wiki, $title, $ns );
          $info['commons']= $this->getCommonsLinks( $wiki, $info['text'] );
         
          if (@$info['english']) $this->trace(5,"english",$info['english']);
          if (@$info['commons']) $this->trace(5,"commons",$info['commons']);
          if (@$info['categories']) $this->trace(5,"categories",$info['categories']);
         
          $this->pageInfo[$k]= $info;
          return $info;
        }
       
        function extractTranslation( $text, $lang ) {
          $match= array();
         
          if (!preg_match('/\[\['.$lang.':([^\|\:\]]+:)*([^\]\|]+)(\|[^\]]*)?\]\]/smi',$text,$match)) {
            return NULL;
          }
          else {
            #$this->trace(4,"TRANSLATION: matched ".@$match[0]."  -> ".$match[1]." || ".$match[2]." || ".@$match[3]);
            return $match[2];
          }
        }
       
        function getCommonsLinks( &$wiki, $text ) {
            $match= array();
           
            $num= preg_match_all(COMMONS_LINK_PATTERN,$text,$match,PREG_PATTERN_ORDER);
            if (!$num) return NULL;
           
            $links= array();
            for ($i=0; $i<$num; $i+=1) {
              if ($match[2][$i]) $links[]= $match[2][$i];
              else {
                  #NOTE: try first and second template-arg! (de and en use different order for {{Commons2}})
                  if ($match[6][$i]) $links[]= $match[6][$i];
                  if ($match[8][$i]) $links[]= $match[8][$i];
              }
            }
           
            return $links;
        }
       
        function getCategories( &$wiki, $title, $ns ) {
          $db = $this->getDbConnection($wiki);

          $sql= "SELECT cl_to
                 FROM "
.$wiki->dbname.".categorylinks
                 JOIN "
.$wiki->dbname.".page ON page_id = cl_from
                 WHERE page_namespace = $ns
                 AND page_title = "
. $db->addQuotes( $title );
         
          $this->sqlTrace($sql);
          $res= $db->query( $sql, 'getCategories' );
         
          $cats= array();
         
          while ( $row = $db->fetchRow($res) ) {
            $cats[]= $row[0];
          }
         
          $db->freeResult( $res );
         
          #$this->trace(5,"categories for ($ns) $title from [".$wiki->domain."]:",$cats);
          return $cats;
        }
       
        function extractKeywords( $text, $title = false ) {
            $kw= array();
           
            if ($title) {           
                $text= preg_replace('/\.[\w\d]+$/si','',$text);
            }
            else if (strpos($text,'[')!==false && isset($this)) {
                $links= $this->commons->extractLinks( $text );
                foreach ($links as $lnk) {
                    if (sizeof($kw)>=10) break;
                   
                    $s= $lnk['link'];
                    if (strpos($s,':')!==false) continue;
   
                    $kw[]= str_replace(' ', '_', $s);               
                }
            }
           
            if ( sizeof($kw) < 10 ) {
                $text= str_replace(array('_','(',')','.',';',',','-','/','"','*',':','#',"'",'='),' ',$text);

                $text= stripMarkup($text);
                $text= preg_replace('!\[\[.*?\]\]|\{\{.*?\}\}|\[\w+://[^\]]+\]|\w+://[^\s]+!smi','',$text);
           
                $words= preg_split('/\s+/smi',$text);
               
                foreach ($words as $w) {
                    if (sizeof($kw)>=10) break;
                    if (strlen($w)<4) continue;
                   
                    $w= preg_replace('/^[,;.:!\/$%"()?\']|[,;.:!\/$%"()?\']$/smi','',$w);
                    $w= trim($w);
                   
                    if (strlen($w)<4) continue;
                    if (preg_match('/^[\d.:,;\/\']+$/',$w)) continue;
                   
                    if (preg_match('!^(GFDL|GNU-FDL|GPL|\w+://[^\w]+)$!i',$w)) continue;
                   
                    $kw[]= $w;
                }
            }           
           
            $kw= array_unique($kw);
           
            return $kw;
        }
       
        function prepareOutput() {
          if ($this->image && $this->mainWiki) {
              $this->imageInfo= $this->loadImageInfo($this->mainWiki,$this->image);
              if (!$this->imageInfo) {
                  $this->error($this->msg('image_not_found_error_1',$this->mainWiki->domain));
                  return false;
              }
          }
         
          return true;
        }
       
        function generateTxtOutput() {
            if (!$this->prepareOutput()) return false;
       
            $this->verbosity= -100;
            $res= $this->findCategories();
           
            $cats= @$res['categories'];
            $gals= @$res['galleries'];
             
            print "#COMMONSENSE\n";           
            print "projects: ".$this->projects."\n";           
            print "image: ".$this->image."\n";           
           
            print "\n";           
            print "#USAGE (".sizeof($this->usedWikis).")\n";           
            $this->printUsageTxt($this->usedWikis);
           
            print "\n";           
            print "#KEYWORDS (".($this->keywordWikis ? sizeof($this->keywordWikis) : 0).")\n";           
            if ($this->keywordWikis) $this->printUsageTxt($this->keywordWikis);
           
            print "\n";           
            print "#CATEGORIES (".sizeof($cats).")\n";           
            foreach ($cats as $c) {
              print $c."\n";
            }
           
            print "\n";           
            print "#GALLERIES (".sizeof($gals).")\n";           
            foreach ($gals as $g) {
              print $g."\n";
            }

            print "\n";           
            print "#EOF\n";           
        }
       
        function printUsageTxt( &$usage ) {
              if (!$usage) return;
       
              foreach ($usage as $domain => $pages) {
                  #if ($domain=='commons.wikimedia.org') $wiki=& $this->commons;
                  #else $wiki=& $this->wikis[$domain];
                 
                  print "$domain: ";
                 
                  foreach ($pages as $page) {
                    $t= $page['title'];
                    if ($page['namespace']) $t= MWNamespace::getCanonicalName( $page['namespace'] ) . ':' . $t;
                   
                    print "$t ";
                  }
                 
                  print "\n";
              }
        }
       
        function printUsageHTML( &$usage, $linkImage = NULL ) {
              if (!$usage) return;
       
              foreach ($usage as $domain => $pages) {
                  if ($domain=='commons.wikimedia.org') $wiki=& $this->commons;
                  else $wiki=& $this->wikis[$domain];
                 
                  if ( $linkImage ) {
                      $lnk= $wiki->baseURL . "?title=Image:" . urlencode( $this->commons->asDBKey($linkImage) );
                      print "<b><a href='$lnk'>".escapeHtml($domain)."</a>:</b> ";
                  }
                  else {
                      print "<b>".escapeHtml($domain).":</b> ";
                  }
                 
                  foreach ($pages as $page) {
                    $t= $page['title'];
                    if ($page['namespace']) $t= MWNamespace::getCanonicalName( $page['namespace'] ) . ':' . $t;
                   
                    $lnk= $wiki->baseURL . "?title=" . urlencode( $t );
                    print " <a href='$lnk'>".escapeHtml($t)."</a>, ";
                  }
                 
                  print "<br/>\n";
              }
        }
       
        function generateHtmlOutput() {
              if (!$this->prepareOutput()) return false;
       
              $title= "Image:".$this->image;
             
              if ($this->mainWiki) {
                print "\n\t\t<div class='thumb'>";
                print $this->mainWiki->getThumbnailHTML($this->image, 120);
                print "</div>\n";
              }

              /*if ($this->mainWiki && $this->imageInfo && preg_match('/\.(jpe?g|gif|png|svg)$/i',$this->image)) {
                $thumbwidth= 180;
               
                #FIXME: ugly hack: thumb.php refuses to give full size images!
                if ($this->imageInfo->img_width<$thumbwidth) $thumbwidth= $this->imageInfo->img_width -1;
               
                $u= "http://{$this->mainWiki->domain}/w/thumb.php?f=".urlencode($this->image)."&amp;w=$thumbwidth";
               
                if ( !preg_match('/\.(jpe?g|gif|png)$/i',$this->image) ) {
                    $u.= "&amp;r=1";
                }
               
                $lnk= $this->mainWiki->baseURL . "?title=" . urlencode( $title );
               
                print "\n\t\t<div class='thumb'>";
                print "<a href='$lnk'><img src='$u' border='0' alt='".escapeHtml($title)."'/></a>";
                print "</div>\n";
              }*/

             
              $tkw= array();
              $tkw+= $this->extractKeywords($this->image,true);
             
              if ($this->imageInfo && $this->mainWiki) {
                  $info= $this->loadPageInfo( $this->mainWiki, $this->image, NS_IMAGE );
                  $text= $info ? $info['text'] : false;
                 
                  if ($text !== false) {
                      $text= escapeHtml( $text );
                      $text= str_replace("\r\n",'<br/>',$text);
                      $text= str_replace("\r",'<br/>',$text);
                      $text= str_replace("\n",'<br/>',$text);
                     
                      $lnk= $this->mainWiki->baseURL . "?title=" . urlencode( $title );
                     
                      print "<h4>".$this->msg('image_description_2',$lnk,escapeHtml($title))."</h4>\n";
                      print "<div class='wikitext'>$text</div>\n";

                      if ($this->mainWiki->domain=='commons.wikimedia.org') {
                          print "<p><b>[<i><a href='$lnk&amp;action=edit'>".$this->msg('edit_description')."</a></i>]</b></p>\n";
                      }
                     
                      if ($text) {
                          $tkw+= $this->extractKeywords($text,false);
                      }
                  }
                  else {
                      $this->error($this->msg('image_load_error_2',$title,$this->mainWiki->domain));
                  }
              }
                         
              print  "\n<h4>".$this->msg('searching_for_categories')."</h4>\n";
     
              print  "\n<div style='font-size:80%; padding:0; padding-left:3ex;'>\n";
             
              $res= $this->findCategories();
              print  "\n</div>\n";
             
              $cats= @$res['categories'];
              $gals= @$res['galleries'];
             
              if ( !$this->usedWikis && !$this->keywordWikis) {
                $this->error($this->msg('no_matches_error'));
              }
              else {
                  if ( $this->usedWikis ) {
                    print  "\n<p>".$this->msg('image_used_on_pages_1',escapeHtml($title))."<br/>";
                   
                    $this->printUsageHTML( $this->usedWikis, $this->image);
                   
                    print "</p>\n";
                  } 
                  else if ($this->image) {
                    ?>
                      <p style='font-weight:bold;'><?= $this->msg('image_not_used')?></p>
                    <?
                  }
                 
                  if ( $this->keywordWikis ) {
                    print  "\n<p>".$this->msg('keywords_match_pages')."<br/>";
                   
                    $this->printUsageHTML( $this->keywordWikis, NULL);
                   
                    print "</p>\n";
                  } 
                  else if ( $this->keywords ) {
                    ?>
                      <p style='font-weight:bold;'><?=$this->msg('keywords_not_found')?></p>
                    <?
                  }
              }
             
              if ($tkw) {
                  global $projrq, $customlang, $scanwiki, $mode; #ugly
                  $u= $_SERVER['PHP_SELF']."?i=".urlencode($this->image)."&amp;p=".urlencode($projrq)."&amp;cl=".urlencode($customlang)."&amp;u=".urlencode($this->messages->language)."&amp;v=".urlencode($this->verbosity)."&amp;w=".urlencode($scanwiki)."&amp;m=".urlencode($mode)."&amp;";
                 
                  if ($this->keywords) $kw= array_unique( array_merge( $this->keywords, $tkw ) );
                  else $kw= $tkw;
                 
                  $u.= "kw=".urlencode( implode(', ',$kw) );
                 
                  print "<p><i>".$this->msg('use_keywords_from_description_2',$u,escapeHtml(implode(', ',$kw)))."</i></p>\n";
              }
             
              if ( $this->usedWikis || $this->keywordWikis ) {
                  if ( !$cats && !$gals ) {
                  ?>
                    <p><?=$this->error($this->msg('nothing_found'))?></p>
                  <?
                  }                       
                  else { 
                    print "\n<div class='box' style='clear:both; margin-top:1ex;'>";
                   
                    if ($cats) {
                    ?>
                      <h3><?=$this->msg('suggested_categories')?></h3>
                      <div style='display:table-row;'>
                          <div style='display:table-cell; padding-right:1em; text-align:left; width:60%'>
                            <ul style='vertical-align:top; text-align:left; margin:0;'>
                          <?
                            foreach ($cats as $c) {
                                print $this->commons->makeExpandableCategoryItemHTML($c);
                            }
                          ?>
                            </ul>
                          </div>
                         
                          <div style='display:table-cell; vertical-align:top; width:40%;' class='wikitext'>
                          <?
                            foreach ($cats as $c) {
                              $c= str_replace('_',' ',$c);
                              print "[[Category:".escapeHtml($c)."]]<br/>";
                            }
                          ?>
                          </div>
                      </div>
                     
                      <p style="font-size:80%"> <?= $this->msg('verify_cats_text') ?>
                      </p>
                    <?
                    }
                   
                    if ($gals) {
                    ?>
                      <h3><?= $this->msg('suggested_galleries') ?></h3>
                      <ul>
                      <?
                        foreach ($gals as $g) {
                          print "<li><a href='http://commons.wikimedia.org/wiki/".urlencode(str_replace(' ','_',$g))."'>".escapeHtml($g)."</a></li>";
                        }
                      ?>
                      </ul>
                    <?
                    }
               
                    print "\n</div>";
                  }
                 
                  print "\n<a name='result'></a>";
                 
                  global $wsgBrowser;
                  if ($wsgBrowser && !$wsgBrowser['opera'] && !$wsgBrowser['khtml']) {
                      print "\n<script type='text/javascript'>window.location.hash='#result'</script>";
                  }
              }
        }
}

if (defined('WS_TEST_COMMON_SENSE')) {
    $txt= implode(' ',$args);
    $kw= CommonSensePage::extractKeywords($txt);
   
    print_r($kw);
   
    exit;
}

#$wsgLogLevel= LL_VERBOSE;

$knownLanguages= array('ar', 'ca', 'cs', 'da', 'de', 'el', 'en', 'es', 'fr', 'it', 'ja', 'km', 'nl', 'pl', 'pt', 'ru', 'sk', 'th', 'vi', 'wa', 'wo', 'zh', 'zh-hans', 'zh-hant');
$wsgCommonSenseText=& WikiSenseLocalizer::initialize('CommonSense', $knownLanguages, $wgRequest->getVal('go-u'), 'u', 'ws-interface-lang');

$img= $wgRequest->getVal("i");
$keywords= $wgRequest->getVal("kw");
$lang= $wgRequest->getVal("l");
$projrq= $wgRequest->getVal("p","_20");
$scanwiki= $wgRequest->getVal("w");
$customlang= $wgRequest->getVal("cl");
$verb= $wgRequest->getVal("v",0);
$raw= $wgRequest->getVal("r",0);
$keepRedundant= $wgRequest->getVal("k",0);

$errors= array();

if ( !is_null($projrq) ) $projrq= trim($projrq);
if ( empty($projrq) ) $projrq= NULL;

#if ($wgRequest->getVal('go-move')) $mode= 'move';
#if ($wgRequest->getVal('go-clean')) $mode= 'clean';
#if (!$projrq) $mode= NULL;

if ( !is_null($img) ) $img= trim($img);
if ( empty($img) ) $img= NULL;

if ( $img ) {
  $match= array();
  if (preg_match('/^\w+:(.*)$/',$img,$match)) {
    $img= $match[1];
  }
}

$mode= NULL;

if ($wgRequest->getVal("random") || $wgRequest->getVal("go-move")) {
  $mode= 'move';
}

if ($wgRequest->getVal("uncategorized") || $wgRequest->getVal("go-clean")) {
  $mode= 'clean';
}

if (!$mode) {
  $mode= $wgRequest->getVal("m");
}

if (!$mode && $lang) {
  $mode= 'move';
}

if (!$mode && !$scanwiki) {
  $scanwiki= WikiSenseLocalizer::detectUserLanguage( $wsgLanguages, '', $wsgCommonSenseText->language );
}

if (!$lang) {
  if ($mode=='clean') {
    $lang= $projrq;
 
    $lang= strtolower($lang);
    $m= array();

    $fam= 'wikipedia';
   
    if ($lang == "major") $lang= '_15';
    else if ($lang == "wps") $lang= '_1000000';
    else if ($lang == "all") {
        $lang= '_1000000';
        $fam= NULL;
    }
   
    if (preg_match('/^_(\d+)/',$lang,$m)) {
      $n= $m[1];
      $w= getLargestWikis($n,$fam);
     
      $lang= implode(', ',array_keys($w));
    }
   
    if ($customlang) {
      if (!$lang) $lang= $customlang;
      else $lang.= ',' . $customlang;
    }
  }
 
  if ($mode=='move') {
    $lang= $scanwiki;
  }
}

$page= NULL;

if ( $lang) {
    if ( $wgRequest->getVal("random") ) {
            $keywords= NULL;
            $page= new CommonSensePage( $lang, NULL );
            $img= $page->randomImage();
            $page->stripRedundant= !$keepRedundant;
    }
    else if ( $wgRequest->getVal("uncategorized") ) {
            $keywords= NULL;
            $page= new CommonSensePage( $lang, NULL );
            $img= $page->randomUncategorizedCommonsImage();
            $page->stripRedundant= !$keepRedundant;
    }
    else if ($img || $keywords) {
            $page= new CommonSensePage( $lang, $img, $keywords );
            $page->stripRedundant= !$keepRedundant;
    }
}

if ( $page ) {
    if ($mode=='clean') {
        $page->mainWiki= $page->commons;
    }
   
    #$lang= implode(', ',array_keys($page->wikis));

    if ($wgRequest->getVal("debug") ) {
          $page->sqlDebug= true;
    }
   
    if ($page->errors ) {
        $errors= $page->errors;
    }
   
    if (!$page->wikis ) {
        $page->close();
        $page= NULL;
        $projrq= NULL;
        $lang= NULL;
        #$mode= NULL;
    }
}

if ( $page && $raw && ($img || $keywords)) {
      header("Content-Type: text/plain; charset=UTF-8");
     
      $page->generateTxtOutput();
      $page->close();
     
      exit();
}

header("Content-Type: text/html; charset=UTF-8");

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='<?=$wsgCommonSenseText->language?>' lang='<?=$wsgCommonSenseText->language?>'>
        <head>
                <title>CommonSense</title>
                <meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
               
                <?
                if ($img || $keywords) print '<meta name="robots" content="noindex, nofollow"/>';
                else print '<meta name="robots" content="nofollow"/>';
                ?>

                <link rel="stylesheet" href="wikisense.css" type="text/css">
               
                <style type='text/css'>
                        body { font-family: sans-serif; font-size:14px; }
                       
                        .error { font-weight:bold; color:red; }
                       
                        div.term { border:1px solid #AAAAAA; background-color: #F8F8FF; margin:1ex; }
                        .term p { margin-left: 1ex; margin-right: 1ex;  }
                       
                        .section { border:1px solid #AAAAAA; border-width:0 0 1px 0; background-color: #F0F0FF; padding:1ex; }
                        h3.section { margin:0; }
                       
                        .wikitext {  margin-left:2.5ex; padding:0.7ex;
                                        font-family:monospace;
                                        background-color:#F0F0F0;
                                        border:1px dashed gray; }
                                       
                        div.thumb {
                            float:right;
                            margin: 1ex 0 1ex 1ex;
                            padding: 1ex;
                            background-color:#EEEEEE;
                            border:1px solid #AAAAAA;
                        }
                       
                        .box {
                            border:1px solid #AAAAAA;
                            background-color: #EEEEEE;
                            padding:0 1ex 1ex 1ex;
                            margin:0;
                            margin-bottom:1ex;
                        }
                       
                        .box h3 { margin-top:0; padding-top:0; }
                </style>
               
                <script type='text/javascript' src="Bonsai.js"></script>

                <script type='text/javascript'>
                  function submitOnEnter(event, button) {
                      if (event.keyCode != 13) return true;

                      if (!button) return false;
                     
                      button= document.getElementById(button);
                     
                      if (button) button.click();
                     
                      return false;
                  }
                </script>
        </head>
        <body>
          <? #wsfHackingInProgress() ?>
         
          <? #print "LANG: $lang; MODE: $mode; PAGE: $page; IMG: $img; KW: $keywords;"; ?>
         
          <? #if ($page) print_r($page->mainWiki); ?>
             
              <? wsfHeader(); ?>
              <div id='content' class='centerbox'>
               
                <form method="get" action="CommonSense.php">
                     <div style='float:right; clear:right;'>
                        <?
                          $lag= wsfGetReplagHTML();
                          if ($lag) print "<p class='replag'>$lag</p>";
                        ?>
                       
                        <? $wsgCommonSenseText->printLanguageSelector($knownLanguages); ?>
                        <input type="submit" name="go-u" value="<?= $wsgCommonSenseText->msg('set_language') ?>"/>
                        <br/><? $wsgCommonSenseText->printTranslationLink('CommonSense') ?>
                      </div>
                     
                    <h1>CommonSense</h1>
                     
                      <? wsfSubtitle('CommonSense'); ?>
                     
                      <p><?= $wsgCommonSenseText->msg('tag_line') ?> </p>
                      <!-- <p style="font-size:90%"> <?= $wsgCommonSenseText->msg('intro_text') ?> </p> -->
                     
                      <?
                      if ( $errors ) {
                          foreach ( $errors as $e ) {
                              CommonSensePage::error($e);
                          }
                      }
                      ?>
                     
                      <?
                      if ($lang && !$img && !$keywords) {
                          CommonSensePage::error($wsgCommonSenseText->msg('missing_image_or_keyords_error'));
                      }
                      ?>

                      <?
                      if ($mode && !$lang) {
                          CommonSensePage::error($wsgCommonSenseText->msg('missing_custom_project_error'));
                      }
                      ?>

                        <div class='box'>
                            <table>
                                <tr>
                                  <td valign='top'>&nbsp;</td>
                                  <td valign='top'>
                                    <small><?=$wsgCommonSenseText->msg('top_help')?></small>
                                  </td>
                                </tr>                           
                               
                                <tr>
                                  <td style='padding:0.5ex; white-space:nowrap;' valign='top'><?= $wsgCommonSenseText->msg('image_label') ?></td>
                                  <td style='padding:0.5ex;' valign='top'><input type="text" name="i"  style="width:56ex; font-family:verdana,helvetica,arial,sans-serif; font-size:80%;" value="<?= escapeHtml($img) ?>"  onkeypress="return submitOnEnter(event, null);"/></td>
                                  <td style='padding:0.5ex;' valign='top' rowspan="2"><small><?=$wsgCommonSenseText->msg('bot_output_label')?>: <input type="checkbox" name="r" onkeypress="return submitOnEnter(event,null);"/></small></td>
                                </tr>
                               
                                <tr>
                                  <td style='padding:0.5ex; white-space:nowrap;' valign='top'><?= $wsgCommonSenseText->msg('keywords_label') ?> </td>
                                  <td style='padding:0.5ex;' valign='top'><textarea name="kw" rows="3" style="width:56ex; font-family:verdana,helvetica,arial,sans-serif; font-size:80%;"><?=escapeHtml($keywords)?></textarea></td>
                                </tr>
   
                                <tr>
                                  <td colspan="2" valign='top'>
                                    <h4 style="margin:0; padding:0; padding-top:0.5ex; font-size:120%;"><?=$wsgCommonSenseText->msg('image_on_commons_header')?><br/></h4>
                                    <?#=$wsgCommonSenseText->msg('project_selector_header')?>
                                  </td>
                                </tr>                           
                               
                                <tr>
                                  <td style='padding:0.5ex; white-space:nowrap;' valign='top'><?=$wsgCommonSenseText->msg('project_selector_label')?></td>
                                  <td style='padding:0.5ex;' valign='top'>
                                    <? printRadioButton('p','_20',$projrq) ?> 20
                                    <? printRadioButton('p','_80',$projrq) ?> 80
                                    <? printRadioButton('p','wps',$projrq) ?> <?=$wsgCommonSenseText->msg('all_wikipedias')?>
                                   
                                    <!-- <? printRadioButton('p','all',$projrq) ?> <?=$wsgCommonSenseText->msg('all_projects')?> -->
                                  </td>
                                  <td style='padding:0.5ex;' align='right' valign='top'><input type="submit" id="go-clean" name="go-clean" value="<?=$wsgCommonSenseText->msg('find_categories')?>"/></td>
                                </tr>                           
                                   
                                <tr>
                                  <td style='padding:0.5ex; white-space:nowrap;' valign='top'><?=$wsgCommonSenseText->msg('custom_projects_label')?></td>
                                  <td valign='top'>
                                    <input type="text" name="cl"  style="width:56ex; font-family:verdana,helvetica,arial,sans-serif; font-size:80%;" value="<?= escapeHtml($customlang) ?>"  onkeypress="return submitOnEnter(event, 'go-clean');"/>
                                    <br/><small><?=$wsgCommonSenseText->msg('project_field_help')?></small>
                                    <br/><? printRadioButton('p','',$projrq) ?> <?=$wsgCommonSenseText->msg('custom_projects_only')?>
                                  </td>
                                  <td style='padding:0.5ex;' align='right' valign='top'><input type="submit" name="uncategorized" value="<?=$wsgCommonSenseText->msg('random_commons_orphan')?>"/> </td>
                                </tr>                           
                               
                                <tr>
                                  <td colspan="2" valign='top'>
                                    <h4 style="margin:0; padding:0; padding-top:0.5ex; font-size:120%;"><?=$wsgCommonSenseText->msg('image_in_wiki_header')?></h4>
                                  </td>
                                </tr>                           
                               
                                <tr>
                                  <td style='padding:0.5ex; white-space:nowrap;' valign='top'><?=$wsgCommonSenseText->msg('scan_wiki_label')?></td>
                                  <td style='padding:0.5ex;' valign='top'>
                                    <input name="w" style="width: 16ex; font-family: verdana,helvetica,arial,sans-serif; font-size: 80%;" value="<?= escapeHtml($scanwiki) ?>" type="text" onkeypress="return submitOnEnter(event, 'go-move');"/>
                                    <br/><small><?=$wsgCommonSenseText->msg('single_wiki_help')?></small>
                                  </td>
                                  <td style='padding:0.5ex;' align='right' valign='top'>
                                    <input type="submit" id="go-move" name="go-move" value="<?=$wsgCommonSenseText->msg('find_categories')?>"/>
                                    <div style='height:1ex; font-size:50%;'>&nbsp;<div/>
                                    <input type="submit" id="random" name="random" value="<?=$wsgCommonSenseText->msg('random_wiki_image')?>"/>
                                  </td>
                                </tr>                           
                            </table>
                           
                            <input type="hidden" name="v" value="<?= escapeHtml($verb) ?>"/>
                        </div>
                    <?
                        if ( $page && ($img || $keywords)) {
                                #if ($mode=='clean' && (!$page->mainWiki || $page->mainWiki->domain!='commons.wikimedia.org')) {
                                #      $page->mainWiki= $page->commons;
                                #}
                               
                                $page->verbosity= $verb;
                                $page->generateHtmlOutput();
                        }
                       
                    ?>
                       
                </form>
            </div>
            <? wsfFooter(false); ?>
        </body>
</html>

<?
if ($page) $page->close();
wfDebug( "Request ended normally\n" );

/*
[22:37] <Multichil> Duesentrieb : You around? Feel like trying a filter function?
[22:38] <Duesentrieb> Multichil: can you post it somewhere? I'll look at it in a bit.
[22:40] <Multichil> Duesentrieb /home/multichill/public_html/inc/filtercats_inc.php
[22:41] <Multichil> Just pass an array of categories and it will return two arrays. One with the new categories and one with the categories which were filtered out.
[22:44] <Duesentrieb> Multichil: thanks. i'm kind of tired, dunno if i'll look at it today... otherwise i'll do it tomorrow
[22:45] <Multichil> No rush. You should just be able to include the file and use the function. See /home/multichill/public_html/filtercats.php line 45-48 for an example.
*/

?>