[
  {
    "path": "README.md",
    "content": "Full-Text RSS\n=============\n\n### NOTE\n\nThis is a our public version of Full-Text RSS available to download for free from <http://code.fivefilters.org>.\n\nFor best extraction results, and to help us sustain the project, you can purchase the most up-to-date version at <http://fivefilters.org/content-only/#download> - so if you like this free version, please consider supporting us by purchasing the latest release. \n\nIf you have no need for the latest release, but would still like to contribute something, you can donate via [Gittip](https://www.gittip.com/fivefilters/) or [Flattr](https://flattr.com/profile/k1m).\n\n### About\n\nSee <http://fivefilters.org/content-only/> for a description of the code.\n\n### Installation\n\n1. Extract the files in this ZIP archive to a folder on your computer.\n\n2. FTP the files up to your server\n\n3. Access index.php through your browser. E.g. http://example.org/full-text-rss/index.php\n\n4. Enter a URL in the form field to test the code\n\n5. If you get an RSS feed with full-text content, all is working well. :)\n\n### Configuration (optional)\n\n1. Save a copy of config.php as custom_config.php and edit custom_config.php\n\n2. If you decide to enable caching, make sure the cache folder (and its 2 sub folders) is writable. (You might need to change the permissions of these folders to 777 through your FTP client.)\n\n### Site-specific extraction rules\n\nThis free version does not contain the site config files we include with purchased copies, but these are now all available [online](https://github.com/fivefilters/ftr-site-config). If you'd like to keep yours up to date using Git, follow the steps below:\n\n1. Change into the site_config/standard/ folder\n2. Delete everything in there\n3. Using the command line, enter: `git clone https://github.com/fivefilters/ftr-site-config.git .`\n4. Git should now download the latest site config files for you.\n5. To update the site config files again, you can simply run `git pull` from the directory.\n\n### Code example\n\nIf you're developing an application which requires content extraction, you can call Full-Text RSS as a web service from within your application. Here's how to do it in PHP:\n\n\t<?php\n\t// $ftr should be URL where you installed this application\n\t$ftr = 'http://example.org/full-text-rss/';\n\t$article = 'http://www.bbc.co.uk/news/world-europe-21936308';\n\n\t$request = $ftr.'makefulltextfeed.php?format=json&url='.urlencode($article);\n\n\t// Send HTTP request and get response\n\t$result = @file_get_contents($request);\n\n\tif (!$result) die('Failed to fetch content');\n\n\t$json = @json_decode($result);\n\n\tif (!$json) die('Failed to parse JSON');\n\n\t// What do we have?\n\t// var_dump($json);\n\t\n\t// Items?\n\t// var_dump($json->rss->channel->item);\n\n\t$title = $json->rss->channel->item->title;\n\t// Note: this works when you're processing an article.\n\t// If the input URL is a feed, ->item will be an array.\n\n\techo $title;\n\n### Different language?\n\nAlthough we don't have examples in other programming languages, the essential steps should be:\n\n1. Construct the request URL using URL where you installed Full-Text RSS and the article or feed URL (see $ftr, $article, $request in example above).\n\n2. Fetch the resulting URL using an HTTP GET request.\n\n3. Parse the HTTP response body as JSON and grab what you need."
  },
  {
    "path": "README.txt",
    "content": "Full-Text RSS\n=============\n\nAbout\n-----\n\nSee http://fivefilters.org/content-only/ for a description of the code.\n\n\nInstallation\n------------\n\n1. Extract the files in this ZIP archive to a folder on your computer.\n\n2. FTP the files up to your server\n\n3. Access index.php through your browser. E.g. http://example.org/full-text-rss/index.php\n\n4. Enter a URL in the form field to test the code\n\n5. If you get an RSS feed with full-text content, all is working well. :)\n\nConfiguration (optional)\n------------------------\n\n1. Save a copy of config.php as custom_config.php and edit custom_config.php\n\n2. If you decide to enable caching, make sure the cache folder (and its 2 sub folders) is writable.\n(You might need to change the permissions of these folders to 777 through your FTP client.)\n\n3. If you want to use the admin area to edit/update your site config files, make sure the\nsite_config folder (and its 2 sub folders) is writable. (You might need to change the permissions\nof these folders to 777 through your FTP client.)\n\nHelp\n----\n\nPlease visit http://help.fivefilters.org"
  },
  {
    "path": "UPDATING.txt",
    "content": "Updating Full-Text RSS\n======================\n\nTo update your copy of Full-Text RSS to ensure feeds continue to be processed as they were before, we suggest the following steps:\n\n1. Keep your current installation in place for now (we'll deal with it later)\n\n2. Extract this updated package to a new folder -- for example, if the last version is in a folder called 'full-text-rss', extract this version to a new folder called 'full-text-rss-updated'\n\n3. Upload the new folder to your server\n\n4. Access index.php in the new folder through your browser -- for example http://example.org/full-text-rss-updated/index.php\n\n5. Enter a URL in the form field to test the updated code\n\n6. If you'd configured the last version, copy custom_config.php from your old version to the new installation.\n\n7. If you'd added custom site config files (in site_config/custom/), copy those over to the new installation.\n\n8. If you'd enabled caching, make sure the cache folder (and its 2 sub folders) is writable. (You might need to change the permissions of these folders to 777 through your FTP client.)\n\n9. Test the new copy again to make sure the config values are now applied to the new version.\n\n10. Now simply rename the folder with your old copy to 'full-text-rss-old' and then rename the folder with the new copy to 'full-text-rss' (or whatever name you'd given the original folder).\n\nThat's all that's needed. Your feeds should continue to work as they did before. Let us know if you have any trouble: help@fivefilters.org.\n\nUpdating Site Patterns\n======================\n\nSite patterns are used by Full-Text RSS to improve extraction for certain sites. These are simple text files which are updated more frequently than the Full-Text RSS software itself. \n\nTo make sure your copy of Full-Text RSS is using the latest site patterns, We've created a simple tool to help you get the latest copy of these site patterns from FiveFilters.org. To use it, access the admin/ folder in your browser and follow the instructions.\n\nAlternatively, you can download the latest set of site config files via GitHub: https://github.com/fivefilters/ftr-site-config"
  },
  {
    "path": "admin/apc.php",
    "content": "<?php\n/*\n  +----------------------------------------------------------------------+\n  | APC (slightly modified for the Full-Text RSS admin panel)            |\n  +----------------------------------------------------------------------+\n  | Copyright (c) 2006-2011 The PHP Group                                |\n  +----------------------------------------------------------------------+\n  | This source file is subject to version 3.01 of the PHP license,      |\n  | that is bundled with this package in the file LICENSE, and is        |\n  | available through the world-wide-web at the following url:           |\n  | http://www.php.net/license/3_01.txt                                  |\n  | If you did not receive a copy of the PHP license and are unable to   |\n  | obtain it through the world-wide-web, please send a note to          |\n  | license@php.net so we can mail you a copy immediately.               |\n  +----------------------------------------------------------------------+\n  | Authors: Ralf Becker <beckerr@php.net>                               |\n  |          Rasmus Lerdorf <rasmus@php.net>                             |\n  |          Ilia Alshanetsky <ilia@prohost.org>                         |\n  +----------------------------------------------------------------------+\n\n   All other licensing and usage conditions are those of the PHP Group.\n\n */\n\n$VERSION='$Id: apc.php 307048 2011-01-03 23:53:17Z kalle $';\n\n////////// READ OPTIONAL CONFIGURATION FILE ////////////\nif (file_exists(\"apc.conf.php\")) include(\"apc.conf.php\");\n////////////////////////////////////////////////////////\n\n////////////////////////////////\n// Load config file\n////////////////////////////////\n$admin_page = 'apc';\nrequire_once('../config.php');\nrequire_once('require_login.php');\nrequire_once('template.php');\nif (!isset($_REQUEST['IMG'])) tpl_header('APC');\n\n////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////\ndefaults('USE_AUTHENTICATION',0);\t\t\t// Use (internal) authentication - best choice if \n\t\t\t\t\t\t\t\t\t\t\t// no other authentication is available\n\t\t\t\t\t\t\t\t\t\t\t// If set to 0:\n\t\t\t\t\t\t\t\t\t\t\t//  There will be no further authentication. You \n\t\t\t\t\t\t\t\t\t\t\t//  will have to handle this by yourself!\n\t\t\t\t\t\t\t\t\t\t\t// If set to 1:\n\t\t\t\t\t\t\t\t\t\t\t//  You need to change ADMIN_PASSWORD to make\n\t\t\t\t\t\t\t\t\t\t\t//  this work!\n//defaults('ADMIN_USERNAME','admin'); \t\t\t// Admin Username\n//defaults('ADMIN_PASSWORD','');  \t// Admin Password - CHANGE THIS TO ENABLE!!!\n\n// (beckerr) I'm using a clear text password here, because I've no good idea how to let \n//           users generate a md5 or crypt password in a easy way to fill it in above\n\n//defaults('DATE_FORMAT', \"d.m.Y H:i:s\");\t// German\ndefaults('DATE_FORMAT', 'Y/m/d H:i:s'); \t// US\n\ndefaults('GRAPH_SIZE',200);\t\t\t\t\t// Image size\n\n//defaults('PROXY', 'tcp://127.0.0.1:8080');\n\n////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////\n\n\n// \"define if not defined\"\nfunction defaults($d,$v) {\n\tif (!defined($d)) define($d,$v); // or just @define(...)\n}\n\n// rewrite $PHP_SELF to block XSS attacks\n//\n$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],''), ENT_QUOTES, 'UTF-8') : '';\n$time = time();\n$host = php_uname('n');\nif($host) { $host = '('.$host.')'; }\nif (isset($_SERVER['SERVER_ADDR'])) {\n  $host .= ' ('.$_SERVER['SERVER_ADDR'].')';\n}\n\n// operation constants\ndefine('OB_HOST_STATS',1);\ndefine('OB_SYS_CACHE',2);\ndefine('OB_USER_CACHE',3);\ndefine('OB_SYS_CACHE_DIR',4);\ndefine('OB_VERSION_CHECK',9);\n\n// check validity of input variables\n$vardom=array(\n\t'OB'\t=> '/^\\d+$/',\t\t\t// operational mode switch\n\t'CC'\t=> '/^[01]$/',\t\t\t// clear cache requested\n\t'DU'\t=> '/^.*$/',\t\t\t// Delete User Key\n\t'SH'\t=> '/^[a-z0-9]+$/',\t\t// shared object description\n\n\t'IMG'\t=> '/^[123]$/',\t\t\t// image to generate\n\t'LO'\t=> '/^1$/',\t\t\t\t// login requested\n\n\t'COUNT'\t=> '/^\\d+$/',\t\t\t// number of line displayed in list\n\t'SCOPE'\t=> '/^[AD]$/',\t\t\t// list view scope\n\t'SORT1'\t=> '/^[AHSMCDTZ]$/',\t// first sort key\n\t'SORT2'\t=> '/^[DA]$/',\t\t\t// second sort key\n\t'AGGR'\t=> '/^\\d+$/',\t\t\t// aggregation by dir level\n\t'SEARCH'\t=> '~^[a-zA-Z0-1/_.-]*$~'\t\t\t// aggregation by dir level\n);\n\n// default cache mode\n$cache_mode='opcode';\n\n// cache scope\n$scope_list=array(\n\t'A' => 'cache_list',\n\t'D' => 'deleted_list'\n);\n\n// handle POST and GET requests\nif (empty($_REQUEST)) {\n\tif (!empty($_GET) && !empty($_POST)) {\n\t\t$_REQUEST = array_merge($_GET, $_POST);\n\t} else if (!empty($_GET)) {\n\t\t$_REQUEST = $_GET;\n\t} else if (!empty($_POST)) {\n\t\t$_REQUEST = $_POST;\n\t} else {\n\t\t$_REQUEST = array();\n\t}\n}\n\n// check parameter syntax\nforeach($vardom as $var => $dom) {\n\tif (!isset($_REQUEST[$var])) {\n\t\t$MYREQUEST[$var]=NULL;\n\t} else if (!is_array($_REQUEST[$var]) && preg_match($dom.'D',$_REQUEST[$var])) {\n\t\t$MYREQUEST[$var]=$_REQUEST[$var];\n\t} else {\n\t\t$MYREQUEST[$var]=$_REQUEST[$var]=NULL;\n\t}\n}\n\n// check parameter sematics\nif (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']=\"A\";\nif (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']=\"H\";\nif (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']=\"D\";\nif (empty($MYREQUEST['OB']))\t$MYREQUEST['OB']=OB_HOST_STATS;\nif (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20;\nif (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A';\n\n$MY_SELF=\n\t\"$PHP_SELF\".\n\t\"?SCOPE=\".$MYREQUEST['SCOPE'].\n\t\"&SORT1=\".$MYREQUEST['SORT1'].\n\t\"&SORT2=\".$MYREQUEST['SORT2'].\n\t\"&COUNT=\".$MYREQUEST['COUNT'];\n$MY_SELF_WO_SORT=\n\t\"$PHP_SELF\".\n\t\"?SCOPE=\".$MYREQUEST['SCOPE'].\n\t\"&COUNT=\".$MYREQUEST['COUNT'];\n\n// authentication needed?\n//\nif (!USE_AUTHENTICATION) {\n\t$AUTHENTICATED=1;\n} else {\n\t$AUTHENTICATED=0;\n\tif (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {\n\n\t\tif (!isset($_SERVER['PHP_AUTH_USER']) ||\n\t\t\t!isset($_SERVER['PHP_AUTH_PW']) ||\n\t\t\t$_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||\n\t\t\t$_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {\n\t\t\tHeader(\"WWW-Authenticate: Basic realm=\\\"APC Login\\\"\");\n\t\t\tHeader(\"HTTP/1.0 401 Unauthorized\");\n\n\t\t\techo <<<EOB\n\t\t\t\t<html><body>\n\t\t\t\t<h1>Rejected!</h1>\n\t\t\t\t<big>Wrong Username or Password!</big><br/>&nbsp;<br/>&nbsp;\n\t\t\t\t<big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>\n\t\t\t\t</body></html>\nEOB;\n\t\t\texit;\n\t\t\t\n\t\t} else {\n\t\t\t$AUTHENTICATED=1;\n\t\t}\n\t}\n}\n\t\n// select cache mode\nif ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) {\n\t$cache_mode='user';\n}\n// clear cache\nif ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {\n\tapc_clear_cache($cache_mode);\n}\n\nif ($AUTHENTICATED && !empty($MYREQUEST['DU'])) {\n\tapc_delete($MYREQUEST['DU']);\n}\n\nif(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) {\n\techo \"No cache info available.  APC does not appear to be running.\";\n  exit;\n}\n\n$cache_user = apc_cache_info('user', 1);  \n$mem=apc_sma_info();\nif(!$cache['num_hits']) { $cache['num_hits']=1; $time++; }  // Avoid division by 0 errors on a cache clear\n\n// don't cache this page\n//\nheader(\"Cache-Control: no-store, no-cache, must-revalidate\");  // HTTP/1.1\nheader(\"Cache-Control: post-check=0, pre-check=0\", false);\nheader(\"Pragma: no-cache\");                                    // HTTP/1.0\n\nfunction duration($ts) {\n    global $time;\n    $years = (int)((($time - $ts)/(7*86400))/52.177457);\n    $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400));\n    $weeks = (int)(($rem)/(7*86400));\n    $days = (int)(($rem)/86400) - $weeks*7;\n    $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24;\n    $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60;\n    $str = '';\n    if($years==1) $str .= \"$years year, \";\n    if($years>1) $str .= \"$years years, \";\n    if($weeks==1) $str .= \"$weeks week, \";\n    if($weeks>1) $str .= \"$weeks weeks, \";\n    if($days==1) $str .= \"$days day,\";\n    if($days>1) $str .= \"$days days,\";\n    if($hours == 1) $str .= \" $hours hour and\";\n    if($hours>1) $str .= \" $hours hours and\";\n    if($mins == 1) $str .= \" 1 minute\";\n    else $str .= \" $mins minutes\";\n    return $str;\n}\n\n// create graphics\n//\nfunction graphics_avail() {\n\treturn extension_loaded('gd');\n}\nif (isset($MYREQUEST['IMG']))\n{\n\tif (!graphics_avail()) {\n\t\texit(0);\n\t}\n\n\tfunction fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {\n\t\t$r=$diameter/2;\n\t\t$w=deg2rad((360+$start+($end-$start)/2)%360);\n\n\t\t\n\t\tif (function_exists(\"imagefilledarc\")) {\n\t\t\t// exists only if GD 2.0.1 is avaliable\n\t\t\timagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);\n\t\t\timagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);\n\t\t\timagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);\n\t\t} else {\n\t\t\timagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);\n\t\t\timageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);\n\t\t\timageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);\n\t\t\timageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);\n\t\t\timageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);\n\t\t\timagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);\n\t\t}\n\t\tif ($text) {\n\t\t\tif ($placeindex>0) {\n\t\t\t\timageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);\n\t\t\t\timagestring($im,4,$diameter, $placeindex*12,$text,$color1);\t\n\t\t\t\t\n\t\t\t} else {\n\t\t\t\timagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);\n\t\t\t}\n\t\t}\n\t} \n\n\tfunction text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {\n\t\t$r=$diameter/2;\n\t\t$w=deg2rad((360+$start+($end-$start)/2)%360);\n\n\t\tif ($placeindex>0) {\n\t\t\timageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);\n\t\t\timagestring($im,4,$diameter, $placeindex*12,$text,$color1);\t\n\t\t\t\t\n\t\t} else {\n\t\t\timagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);\n\t\t}\n\t} \n\t\n\tfunction fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {\n\t\tglobal $col_black;\n\t\t$x1=$x+$w-1;\n\t\t$y1=$y+$h-1;\n\n\t\timagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);\n\t\tif($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);\n\t\telse imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);\n\t\timagerectangle($im, $x, $y1, $x1, $y, $color1);\n\t\tif ($text) {\n\t\t\tif ($placeindex>0) {\n\t\t\t\n\t\t\t\tif ($placeindex<16)\n\t\t\t\t{\n\t\t\t\t\t$px=5;\n\t\t\t\t\t$py=$placeindex*12+6;\n\t\t\t\t\timagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);\n\t\t\t\t\timageline($im,$x,$y+$h/2,$px+90,$py,$color2);\n\t\t\t\t\timagestring($im,2,$px,$py-6,$text,$color1);\t\n\t\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\tif ($placeindex<31) {\n\t\t\t\t\t\t$px=$x+40*2;\n\t\t\t\t\t\t$py=($placeindex-15)*12+6;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$px=$x+40*2+100*intval(($placeindex-15)/15);\n\t\t\t\t\t\t$py=($placeindex%15)*12+6;\n\t\t\t\t\t}\n\t\t\t\t\timagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);\n\t\t\t\t\timageline($im,$x+$w,$y+$h/2,$px,$py,$color2);\n\t\t\t\t\timagestring($im,2,$px+2,$py-6,$text,$color1);\t\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\timagestring($im,4,$x+5,$y1-16,$text,$color1);\n\t\t\t}\n\t\t}\n\t}\n\n\n\t$size = GRAPH_SIZE; // image size\n\tif ($MYREQUEST['IMG']==3)\n\t\t$image = imagecreate(2*$size+150, $size+10);\n\telse\n\t\t$image = imagecreate($size+50, $size+10);\n\n\t$col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);\n\t$col_red   = imagecolorallocate($image, 0xD0, 0x60,  0x30);\n\t$col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);\n\t$col_black = imagecolorallocate($image,   0,   0,   0);\n\timagecolortransparent($image,$col_white);\n\n\tswitch ($MYREQUEST['IMG']) {\n\t\n\tcase 1:\n\t\t$s=$mem['num_seg']*$mem['seg_size'];\n\t\t$a=$mem['avail_mem'];\n\t\t$x=$y=$size/2;\n\t\t$fuzz = 0.000001;\n\n\t\t// This block of code creates the pie chart.  It is a lot more complex than you\n\t\t// would expect because we try to visualize any memory fragmentation as well.\n\t\t$angle_from = 0;\n\t\t$string_placement=array();\n\t\tfor($i=0; $i<$mem['num_seg']; $i++) {\t\n\t\t\t$ptr = 0;\n\t\t\t$free = $mem['block_lists'][$i];\n\t\t\tuasort($free, 'block_sort');\n\t\t\tforeach($free as $block) {\n\t\t\t\tif($block['offset']!=$ptr) {       // Used block\n\t\t\t\t\t$angle_to = $angle_from+($block['offset']-$ptr)/$s;\n\t\t\t\t\tif(($angle_to+$fuzz)>1) $angle_to = 1;\n\t\t\t\t\tif( ($angle_to*360) - ($angle_from*360) >= 1) {\n\t\t\t\t\t\tfill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);\n\t\t\t\t\t\tif (($angle_to-$angle_from)>0.05) {\n\t\t\t\t\t\t\tarray_push($string_placement, array($angle_from,$angle_to));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t$angle_from = $angle_to;\n\t\t\t\t}\n\t\t\t\t$angle_to = $angle_from+($block['size'])/$s;\n\t\t\t\tif(($angle_to+$fuzz)>1) $angle_to = 1;\n\t\t\t\tif( ($angle_to*360) - ($angle_from*360) >= 1) {\n\t\t\t\t\tfill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green);\n\t\t\t\t\tif (($angle_to-$angle_from)>0.05) {\n\t\t\t\t\t\tarray_push($string_placement, array($angle_from,$angle_to));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$angle_from = $angle_to;\n\t\t\t\t$ptr = $block['offset']+$block['size'];\n\t\t\t}\n\t\t\tif ($ptr < $mem['seg_size']) { // memory at the end \n\t\t\t\t$angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s;\n\t\t\t\tif(($angle_to+$fuzz)>1) $angle_to = 1;\n\t\t\t\tfill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);\n\t\t\t\tif (($angle_to-$angle_from)>0.05) {\n\t\t\t\t\tarray_push($string_placement, array($angle_from,$angle_to));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tforeach ($string_placement as $angle) {\n\t\t\ttext_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0])));\n\t\t}\n\t\tbreak;\n\t\t\n\tcase 2: \n\t\t$s=$cache['num_hits']+$cache['num_misses'];\n\t\t$a=$cache['num_hits'];\n\t\t\n\t\tfill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf(\"%.1f%%\",$cache['num_hits']*100/$s));\n\t\tfill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf(\"%.1f%%\",$cache['num_misses']*100/$s));\n\t\tbreak;\n\t\t\n\tcase 3:\n\t\t$s=$mem['num_seg']*$mem['seg_size'];\n\t\t$a=$mem['avail_mem'];\n\t\t$x=130;\n\t\t$y=1;\n\t\t$j=1;\n\n\t\t// This block of code creates the bar chart.  It is a lot more complex than you\n\t\t// would expect because we try to visualize any memory fragmentation as well.\n\t\tfor($i=0; $i<$mem['num_seg']; $i++) {\t\n\t\t\t$ptr = 0;\n\t\t\t$free = $mem['block_lists'][$i];\n\t\t\tuasort($free, 'block_sort');\n\t\t\tforeach($free as $block) {\n\t\t\t\tif($block['offset']!=$ptr) {       // Used block\n\t\t\t\t\t$h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s;\n\t\t\t\t\tif ($h>0) {\n                                                $j++;\n\t\t\t\t\t\tif($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j);\n                                                else fill_box($image,$x,$y,50,$h,$col_black,$col_red);\n                                        }\n\t\t\t\t\t$y+=$h;\n\t\t\t\t}\n\t\t\t\t$h=(GRAPH_SIZE-5)*($block['size'])/$s;\n\t\t\t\tif ($h>0) {\n                                        $j++;\n\t\t\t\t\tif($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j);\n\t\t\t\t\telse fill_box($image,$x,$y,50,$h,$col_black,$col_green);\n                                }\n\t\t\t\t$y+=$h;\n\t\t\t\t$ptr = $block['offset']+$block['size'];\n\t\t\t}\n\t\t\tif ($ptr < $mem['seg_size']) { // memory at the end \n\t\t\t\t$h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;\n\t\t\t\tif ($h > 0) {\n\t\t\t\t\tfill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase 4: \n\t\t$s=$cache['num_hits']+$cache['num_misses'];\n\t\t$a=$cache['num_hits'];\n\t        \t\n\t\tfill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf(\"%.1f%%\",$cache['num_hits']*100/$s));\n\t\tfill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf(\"%.1f%%\",$cache['num_misses']*100/$s));\n\t\tbreak;\n\t\n\t}\n\theader(\"Content-type: image/png\");\n\timagepng($image);\n\texit;\n}\n\n// pretty printer for byte values\n//\nfunction bsize($s) {\n\tforeach (array('','K','M','G') as $i => $k) {\n\t\tif ($s < 1024) break;\n\t\t$s/=1024;\n\t}\n\treturn sprintf(\"%5.1f %sBytes\",$s,$k);\n}\n\n// sortable table header in \"scripts for this host\" view\nfunction sortheader($key,$name,$extra='') {\n\tglobal $MYREQUEST, $MY_SELF_WO_SORT;\n\t\n\tif ($MYREQUEST['SORT1']==$key) {\n\t\t$MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A';\n\t}\n\treturn \"<a class=sortable href=\\\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=\".$MYREQUEST['SORT2'].\"\\\">$name</a>\";\n\n}\n\n// create menu entry \nfunction menu_entry($ob,$title) {\n\tglobal $MYREQUEST,$MY_SELF;\n\tif ($MYREQUEST['OB']!=$ob) {\n\t\treturn \"<li><a href=\\\"$MY_SELF&OB=$ob\\\">$title</a></li>\";\n\t} else if (empty($MYREQUEST['SH'])) {\n\t\treturn \"<li><span class=active>$title</span></li>\";\n\t} else {\n\t\treturn \"<li><a class=\\\"child_active\\\" href=\\\"$MY_SELF&OB=$ob\\\">$title</a></li>\";\t\n\t}\n}\n\nfunction put_login_link($s=\"Login\")\n{\n\tglobal $MY_SELF,$MYREQUEST,$AUTHENTICATED;\n\t// needs ADMIN_PASSWORD to be changed!\n\t//\n\tif (!USE_AUTHENTICATION) {\n\t\treturn;\n\t} else if (ADMIN_PASSWORD=='password')\n\t{\n\t\tprint <<<EOB\n\t\t\t<a href=\"#\" onClick=\"javascript:alert('You need to set a password at the top of apc.php before this will work!');return false\";>$s</a>\nEOB;\n\t} else if ($AUTHENTICATED) {\n\t\tprint <<<EOB\n\t\t\t'{$_SERVER['PHP_AUTH_USER']}'&nbsp;logged&nbsp;in!\nEOB;\n\t} else{\n\t\tprint <<<EOB\n\t\t\t<a href=\"$MY_SELF&LO=1&OB={$MYREQUEST['OB']}\">$s</a>\nEOB;\n\t}\n}\n\nfunction block_sort($array1, $array2)\n{\n\tif ($array1['offset'] > $array2['offset']) {\n\t\treturn 1;\n\t} else {\n\t\treturn -1;\n\t}\n}\n\n\n?>\n<?php\n/*\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head><title>APC INFO <?php echo $host ?></title>\n*/\n?>\n<style><!--\nselect { width: auto; }\nbody { font-size:100.01%; margin:0; padding:0; }\nbody,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }\n* html body   {font-size:0.8em}\n* html p      {font-size:0.8em}\n* html td     {font-size:0.8em}\n* html th     {font-size:0.8em}\n* html input  {font-size:0.8em}\n* html submit {font-size:0.8em}\ntd { vertical-align:top }\na { color:black; font-weight:none; text-decoration:none; }\na:hover { text-decoration:underline; }\ndiv.content { padding:1em 1em 1em 1em; /*position:absolute;*/ width:97%; z-index:100; }\n\ndiv.head { display: none; }\ndiv.head div.login {\n\tposition:absolute;\n\tright: 1em;\n\ttop: 1.2em;\n\tcolor:white;\n\twidth:6em;\n\t}\ndiv.head div.login a {\n\tposition:absolute;\n\tright: 0em;\n\tbackground:rgb(119,123,180);\n\tborder:solid rgb(102,102,153) 2px;\n\tcolor:white;\n\tfont-weight:bold;\n\tpadding:0.1em 0.5em 0.1em 0.5em;\n\ttext-decoration:none;\n\t}\ndiv.head div.login a:hover {\n\tbackground:rgb(193,193,244);\n\t}\n\nh1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }\n* html h1.apc { margin-bottom:-7px; }\nh1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }\nh1.apc div.logo span.logo {\n\tbackground:rgb(119,123,180);\n\tcolor:black;\n\tborder-right: solid black 1px;\n\tborder-bottom: solid black 1px;\n\tfont-style:italic;\n\tfont-size:1em;\n\tpadding-left:1.2em;\n\tpadding-right:1.2em;\n\ttext-align:right;\n\t}\nh1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }\nh1.apc div.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }\nh1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }\nhr.apc {\n\tbackground:white;\n\tborder-bottom:solid rgb(102,102,153) 1px;\n\tborder-style:none;\n\tborder-top:solid rgb(102,102,153) 10px;\n\theight:12px;\n\tmargin:0;\n\tmargin-top:1px;\n\tpadding:0;\n}\n\nol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}\nol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}\n.menu a {\n\tbackground:rgb(153,153,204);\n\tborder:solid rgb(102,102,153) 2px;\n\tcolor:white;\n\tfont-weight:bold;\n\tmargin-right:0em;\n\tpadding:0.1em 0.5em 0.1em 0.5em;\n\ttext-decoration:none;\n\tmargin-left: 0;\n\t}\nol.menu a.child_active {\n\tbackground:rgb(153,153,204);\n\tborder:solid rgb(102,102,153) 2px;\n\tcolor:white;\n\tfont-weight:bold;\n\tmargin-right:0em;\n\tpadding:0.1em 0.5em 0.1em 0.5em;\n\ttext-decoration:none;\n\tborder-left: solid black 5px;\n\tmargin-left: 0px;\n\t}\nol.menu span.active {\n\tbackground:rgb(153,153,204);\n\tborder:solid rgb(102,102,153) 2px;\n\tcolor:black;\n\tfont-weight:bold;\n\tmargin-right:0em;\n\tpadding:0.1em 0.5em 0.1em 0.5em;\n\ttext-decoration:none;\n\tborder-left: solid black 5px;\n\t}\nol.menu span.inactive {\n\tbackground:rgb(193,193,244);\n\tborder:solid rgb(182,182,233) 2px;\n\tcolor:white;\n\tfont-weight:bold;\n\tmargin-right:0em;\n\tpadding:0.1em 0.5em 0.1em 0.5em;\n\ttext-decoration:none;\n\tmargin-left: 5px;\n\t}\nol.menu a:hover {\n\tbackground:rgb(193,193,244);\n\ttext-decoration:none;\n\t}\n\t\n\t\ndiv.info {\n\tbackground:rgb(204,204,204);\n\tborder:solid rgb(204,204,204) 1px;\n\tmargin-bottom:1em;\n\t}\ndiv.info h2 {\n\tbackground:rgb(204,204,204);\n\tcolor:black;\n\tfont-size:1em;\n\tmargin:0;\n\tpadding:0.1em 1em 0.1em 1em;\n\t}\ndiv.info table {\n\tborder:solid rgb(204,204,204) 1px;\n\tborder-spacing:0;\n\twidth:100%;\n\t}\ndiv.info table th {\n\tbackground:rgb(204,204,204);\n\tcolor:white;\n\tmargin:0;\n\tpadding:0.1em 1em 0.1em 1em;\n\t}\ndiv.info table th a.sortable { color:black; }\ndiv.info table tr.tr-0 { background:rgb(238,238,238); }\ndiv.info table tr.tr-1 { background:rgb(221,221,221); }\ndiv.info table td { padding:0.3em 1em 0.3em 1em; }\ndiv.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }\ndiv.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }\ndiv.info table td h3 {\n\tcolor:black;\n\tfont-size:1.1em;\n\tmargin-left:-0.3em;\n\t}\n\ndiv.graph { margin-bottom:1em }\ndiv.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }\ndiv.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }\ndiv.graph table td.td-0 { background:rgb(238,238,238); }\ndiv.graph table td.td-1 { background:rgb(221,221,221); }\ndiv.graph table td { padding:0.2em 1em 0.4em 1em; }\n\ndiv.div1,div.div2 { margin-bottom:1em; width:35em; }\ndiv.div3 { /*position:absolute; left:40em; top:1em; width:580px; */}\n//div.div3 { position:absolute; left:37em; top:1em; right:1em; }\n\ndiv.sorting { margin:1.5em 0em 1.5em 2em }\n.center { text-align:center }\n.aright { /*position:absolute;right:1em */}\n.right { text-align:right }\n.ok { color:rgb(0,200,0); font-weight:bold}\n.failed { color:rgb(200,0,0); font-weight:bold}\n\nspan.box {\n\tborder: black solid 1px;\n\tborder-right:solid black 2px;\n\tborder-bottom:solid black 2px;\n\tpadding:0 0.5em 0 0.5em;\n\tmargin-right:1em;\n}\nspan.green { background:#60F060; padding:0 0.5em 0 0.5em}\nspan.red { background:#D06030; padding:0 0.5em 0 0.5em }\n\ndiv.authneeded {\n\tbackground:rgb(238,238,238);\n\tborder:solid rgb(204,204,204) 1px;\n\tcolor:rgb(200,0,0);\n\tfont-size:1.2em;\n\tfont-weight:bold;\n\tpadding:2em;\n\ttext-align:center;\n\t}\n\t\ninput {\n\tbackground:rgb(153,153,204);\n\tborder:solid rgb(102,102,153) 2px;\n\tcolor:white;\n\tfont-weight:bold;\n\tmargin-right:1em;\n\tpadding:0.1em 0.5em 0.1em 0.5em;\n\t}\n\t\n\ta.clearcache {\n\tbackground-color: red;\n\tcolor: #fff;\n\t}\n//-->\n</style>\n</head>\n<body>\n<div class=\"head\">\n\t<h1 class=\"apc\">\n\t\t<div class=\"logo\"><span class=\"logo\"><a href=\"http://pecl.php.net/package/APC\">APC</a></span></div>\n\t\t<div class=\"nameinfo\">Opcode Cache</div>\n\t</h1>\n\t<div class=\"login\">\n\t<?php put_login_link(); ?>\n\t</div>\n\t<hr class=\"apc\">\n</div>\n<?php\n\n\n// Display main Menu\necho <<<EOB\n\t<ol class=menu>\n\t<li><a href=\"$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}\">Refresh Data</a></li>\nEOB;\necho\n\tmenu_entry(1,'View Host Stats'),\n\tmenu_entry(2,'System Cache Entries');\nif ($AUTHENTICATED) {\n\techo menu_entry(4,'Per-Directory Entries');\n}\necho\n\tmenu_entry(3,'User Cache Entries'),\n\tmenu_entry(9,'Version Check');\n\t\necho <<<EOB\n\t</ol>\nEOB;\n\nif ($AUTHENTICATED) {\n\techo <<<EOB\n\t\t<div class=\"menu\" style=\"margin-top: 10px; text-align: right;\"><a class=\"aright clearcache\" href=\"$MY_SELF&CC=1&OB={$MYREQUEST['OB']}\" onClick=\"javascript:return confirm('Are you sure?');\">Clear $cache_mode Cache</a></div>\nEOB;\n}\n\n// CONTENT\necho <<<EOB\n\t<div class=content>\nEOB;\n\n// MAIN SWITCH STATEMENT \n\nswitch ($MYREQUEST['OB']) {\n\n\n\n\n\n// -----------------------------------------------\n// Host Stats\n// -----------------------------------------------\ncase OB_HOST_STATS:\n\t$mem_size = $mem['num_seg']*$mem['seg_size'];\n\t$mem_avail= $mem['avail_mem'];\n\t$mem_used = $mem_size-$mem_avail;\n\t$seg_size = bsize($mem['seg_size']);\n\t$req_rate = sprintf(\"%.2f\",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time']));\n\t$hit_rate = sprintf(\"%.2f\",($cache['num_hits'])/($time-$cache['start_time']));\n\t$miss_rate = sprintf(\"%.2f\",($cache['num_misses'])/($time-$cache['start_time']));\n\t$insert_rate = sprintf(\"%.2f\",($cache['num_inserts'])/($time-$cache['start_time']));\n\t$req_rate_user = sprintf(\"%.2f\",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time']));\n\t$hit_rate_user = sprintf(\"%.2f\",($cache_user['num_hits'])/($time-$cache_user['start_time']));\n\t$miss_rate_user = sprintf(\"%.2f\",($cache_user['num_misses'])/($time-$cache_user['start_time']));\n\t$insert_rate_user = sprintf(\"%.2f\",($cache_user['num_inserts'])/($time-$cache_user['start_time']));\n\t$apcversion = phpversion('apc');\n\t$phpversion = phpversion();\n\t$number_files = $cache['num_entries']; \n    $size_files = bsize($cache['mem_size']);\n\t$number_vars = $cache_user['num_entries'];\n    $size_vars = bsize($cache_user['mem_size']);\n\t$i=0;\n\techo <<< EOB\n\t\t<div class=\"info div1\"><h2>General Cache Information</h2>\n\t\t<table cellspacing=0><tbody>\n\t\t<tr class=tr-0><td class=td-0>APC Version</td><td>$apcversion</td></tr>\n\t\t<tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>\nEOB;\n\n\tif(!empty($_SERVER['SERVER_NAME']))\n\t\techo \"<tr class=tr-0><td class=td-0>APC Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\\n\";\n\tif(!empty($_SERVER['SERVER_SOFTWARE']))\n\t\techo \"<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\\n\";\n\n\techo <<<EOB\n\t\t<tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size \n    <br/> ({$cache['memory_type']} memory, {$cache['locking_type']} locking)\n    </td></tr>\nEOB;\n\techo   '<tr class=tr-1><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$cache['start_time']),'</td></tr>';\n\techo   '<tr class=tr-0><td class=td-0>Uptime</td><td>',duration($cache['start_time']),'</td></tr>';\n\techo   '<tr class=tr-1><td class=td-0>File Upload Support</td><td>',$cache['file_upload_progress'],'</td></tr>';\n\techo <<<EOB\n\t\t</tbody></table>\n\t\t</div>\n\n\t\t<div class=\"info div1\"><h2>File Cache Information</h2>\n\t\t<table cellspacing=0><tbody>\n\t\t<tr class=tr-0><td class=td-0>Cached Files</td><td>$number_files ($size_files)</td></tr>\n\t\t<tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>\n\t\t<tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>\n\t\t<tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr>\n\t\t<tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr>\n\t\t<tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr>\n\t\t<tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate cache requests/second</td></tr>\n\t\t<tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>\n\t\t</tbody></table>\n\t\t</div>\n\n\t\t<div class=\"info div1\"><h2>User Cache Information</h2>\n\t\t<table cellspacing=0><tbody>\n    <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>\n\t\t<tr class=tr-1><td class=td-0>Hits</td><td>{$cache_user['num_hits']}</td></tr>\n\t\t<tr class=tr-0><td class=td-0>Misses</td><td>{$cache_user['num_misses']}</td></tr>\n\t\t<tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>\n\t\t<tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>\n\t\t<tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>\n\t\t<tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>\n\t\t<tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache_user['expunges']}</td></tr>\n\n\t\t</tbody></table>\n\t\t</div>\n\n\t\t<div class=\"info div2\"><h2>Runtime Settings</h2><table cellspacing=0><tbody>\nEOB;\n\n\t$j = 0;\n\tforeach (ini_get_all('apc') as $k => $v) {\n\t\techo \"<tr class=tr-$j><td class=td-0>\",$k,\"</td><td>\",str_replace(',',',<br />',$v['local_value']),\"</td></tr>\\n\";\n\t\t$j = 1 - $j;\n\t}\n\n\tif($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1)\n\t\t$mem_note = \"Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>\";\n\telse\n\t\t$mem_note = \"Memory Usage\";\n\n\techo <<< EOB\n\t\t</tbody></table>\n\t\t</div>\n\n\t\t<div class=\"graph div3\"><h2>Host Status Diagrams</h2>\n\t\t<table cellspacing=0><tbody>\nEOB;\n\t$size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);\n\techo <<<EOB\n\t\t<tr>\n\t\t<td class=td-0>$mem_note</td>\n\t\t<td class=td-1>Hits &amp; Misses</td>\n\t\t</tr>\nEOB;\n\n\techo\n\t\tgraphics_avail() ? \n\t\t\t  '<tr>'.\n\t\t\t  \"<td class=td-0><img alt=\\\"\\\" $size src=\\\"$PHP_SELF?IMG=1&$time\\\"></td>\".\n\t\t\t  \"<td class=td-1><img alt=\\\"\\\" $size src=\\\"$PHP_SELF?IMG=2&$time\\\"></td></tr>\\n\"\n\t\t\t: \"\",\n\t\t'<tr>',\n\t\t'<td class=td-0><span class=\"green box\">&nbsp;</span>Free: ',bsize($mem_avail).sprintf(\" (%.1f%%)\",$mem_avail*100/$mem_size),\"</td>\\n\",\n\t\t'<td class=td-1><span class=\"green box\">&nbsp;</span>Hits: ',$cache['num_hits'].sprintf(\" (%.1f%%)\",$cache['num_hits']*100/($cache['num_hits']+$cache['num_misses'])),\"</td>\\n\",\n\t\t'</tr>',\n\t\t'<tr>',\n\t\t'<td class=td-0><span class=\"red box\">&nbsp;</span>Used: ',bsize($mem_used ).sprintf(\" (%.1f%%)\",$mem_used *100/$mem_size),\"</td>\\n\",\n\t\t'<td class=td-1><span class=\"red box\">&nbsp;</span>Misses: ',$cache['num_misses'].sprintf(\" (%.1f%%)\",$cache['num_misses']*100/($cache['num_hits']+$cache['num_misses'])),\"</td>\\n\";\n\techo <<< EOB\n\t\t</tr>\n\t\t</tbody></table>\n\n\t\t<br/>\n\t\t<h2>Detailed Memory Usage and Fragmentation</h2>\n\t\t<table cellspacing=0><tbody>\n\t\t<tr>\n\t\t<td class=td-0 colspan=2><br/>\nEOB;\n\n\t// Fragementation: (freeseg - 1) / total_seg\n\t$nseg = $freeseg = $fragsize = $freetotal = 0;\n\tfor($i=0; $i<$mem['num_seg']; $i++) {\n\t\t$ptr = 0;\n\t\tforeach($mem['block_lists'][$i] as $block) {\n\t\t\tif ($block['offset'] != $ptr) {\n\t\t\t\t++$nseg;\n\t\t\t}\n\t\t\t$ptr = $block['offset'] + $block['size'];\n                        /* Only consider blocks <5M for the fragmentation % */\n                        if($block['size']<(5*1024*1024)) $fragsize+=$block['size'];\n                        $freetotal+=$block['size'];\n\t\t}\n\t\t$freeseg += count($mem['block_lists'][$i]);\n\t}\n\t\n\tif ($freeseg > 1) {\n\t\t$frag = sprintf(\"%.2f%% (%s out of %s in %d fragments)\", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg);\n\t} else {\n\t\t$frag = \"0%\";\n\t}\n\n\tif (graphics_avail()) {\n\t\t$size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10);\n\t\techo <<<EOB\n\t\t\t<img alt=\"\" $size src=\"$PHP_SELF?IMG=3&$time\">\nEOB;\n\t}\n\techo <<<EOB\n\t\t</br>Fragmentation: $frag\n\t\t</td>\n\t\t</tr>\nEOB;\n        if(isset($mem['adist'])) {\n          foreach($mem['adist'] as $i=>$v) {\n            $cur = pow(2,$i); $nxt = pow(2,$i+1)-1;\n            if($i==0) $range = \"1\";\n            else $range = \"$cur - $nxt\";\n            echo \"<tr><th align=right>$range</th><td align=right>$v</td></tr>\\n\";\n          }\n        }\n        echo <<<EOB\n\t\t</tbody></table>\n\t\t</div>\nEOB;\n\t\t\n\tbreak;\n\n\n// -----------------------------------------------\n// User Cache Entries\n// -----------------------------------------------\ncase OB_USER_CACHE:\n\tif (!$AUTHENTICATED) {\n    echo '<div class=\"error\">You need to login to see the user values here!<br/>&nbsp;<br/>';\n\t\tput_login_link(\"Login now!\");\n\t\techo '</div>';\n\t\tbreak;\n\t}\n\t$fieldname='info';\n\t$fieldheading='User Entry Label';\n\t$fieldkey='info';\n\n// -----------------------------------------------\n// System Cache Entries\t\t\n// -----------------------------------------------\ncase OB_SYS_CACHE:\t\n\tif (!isset($fieldname))\n\t{\n\t\t$fieldname='filename';\n\t\t$fieldheading='Script Filename';\n\t\tif(ini_get(\"apc.stat\")) $fieldkey='inode';\n\t\telse $fieldkey='filename'; \n\t}\n\tif (!empty($MYREQUEST['SH']))\n\t{\n\t\techo <<< EOB\n\t\t\t<div class=\"info\"><table cellspacing=0><tbody>\n\t\t\t<tr><th>Attribute</th><th>Value</th></tr>\nEOB;\n\n\t\t$m=0;\n\t\tforeach($scope_list as $j => $list) {\n\t\t\tforeach($cache[$list] as $i => $entry) {\n\t\t\t\tif (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue;\n\t\t\t\tforeach($entry as $k => $value) {\n\t\t\t\t\tif (!$AUTHENTICATED) {\n\t\t\t\t\t\t// hide all path entries if not logged in\n\t\t\t\t\t\t$value=preg_replace('/^.*(\\\\/|\\\\\\\\)/','<i>&lt;hidden&gt;</i>/',$value);\n\t\t\t\t\t}\n\n\t\t\t\t\tif ($k == \"num_hits\") {\n\t\t\t\t\t\t$value=sprintf(\"%s (%.2f%%)\",$value,$value*100/$cache['num_hits']);\n\t\t\t\t\t}\n\t\t\t\t\tif ($k == 'deletion_time') {\n\t\t\t\t\t\tif(!$entry['deletion_time']) $value = \"None\";\n\t\t\t\t\t}\n\t\t\t\t\techo\n\t\t\t\t\t\t\"<tr class=tr-$m>\",\n\t\t\t\t\t\t\"<td class=td-0>\",ucwords(preg_replace(\"/_/\",\" \",$k)),\"</td>\",\n\t\t\t\t\t\t\"<td class=td-last>\",(preg_match(\"/time/\",$k) && $value!='None') ? date(DATE_FORMAT,$value) : htmlspecialchars($value, ENT_QUOTES, 'UTF-8'),\"</td>\",\n\t\t\t\t\t\t\"</tr>\";\n\t\t\t\t\t$m=1-$m;\n\t\t\t\t}\n\t\t\t\tif($fieldkey=='info') {\n\t\t\t\t\techo \"<tr class=tr-$m><td class=td-0>Stored Value</td><td class=td-last><pre>\";\n\t\t\t\t\t$output = var_export(apc_fetch($entry[$fieldkey]),true);\n\t\t\t\t\techo htmlspecialchars($output, ENT_QUOTES, 'UTF-8');\n\t\t\t\t\techo \"</pre></td></tr>\\n\";\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\techo <<<EOB\n\t\t\t</tbody></table>\n\t\t\t</div>\nEOB;\n\t\tbreak;\n\t}\n\n\t$cols=6;\n\techo <<<EOB\n\t\t<div class=sorting><form>Scope:\n\t\t<input type=hidden name=OB value={$MYREQUEST['OB']}>\n\t\t<select name=SCOPE>\nEOB;\n\techo \n\t\t\"<option value=A\",$MYREQUEST['SCOPE']=='A' ? \" selected\":\"\",\">Active</option>\",\n\t\t\"<option value=D\",$MYREQUEST['SCOPE']=='D' ? \" selected\":\"\",\">Deleted</option>\",\n\t\t\"</select>\",\n\t\t\" Sorting: <select name=SORT1>\",\n\t\t\"<option value=H\",$MYREQUEST['SORT1']=='H' ? \" selected\":\"\",\">Hits</option>\",\n\t\t\"<option value=Z\",$MYREQUEST['SORT1']=='Z' ? \" selected\":\"\",\">Size</option>\",\n\t\t\"<option value=S\",$MYREQUEST['SORT1']=='S' ? \" selected\":\"\",\">$fieldheading</option>\",\n\t\t\"<option value=A\",$MYREQUEST['SORT1']=='A' ? \" selected\":\"\",\">Last accessed</option>\",\n\t\t\"<option value=M\",$MYREQUEST['SORT1']=='M' ? \" selected\":\"\",\">Last modified</option>\",\n\t\t\"<option value=C\",$MYREQUEST['SORT1']=='C' ? \" selected\":\"\",\">Created at</option>\",\n\t\t\"<option value=D\",$MYREQUEST['SORT1']=='D' ? \" selected\":\"\",\">Deleted at</option>\";\n\tif($fieldname=='info') echo\n\t\t\"<option value=D\",$MYREQUEST['SORT1']=='T' ? \" selected\":\"\",\">Timeout</option>\";\n\techo \n\t\t'</select> ',\n\t\t'<select name=SORT2>',\n\t\t'<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',\n\t\t'<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',\n\t\t'</select> ',\n\t\t'<select name=COUNT onChange=\"form.submit()\">',\n\t\t'<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',\n\t\t'<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',\n\t\t'<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',\n\t\t'<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',\n\t\t'<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',\n\t\t'<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',\n\t\t'<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',\n\t\t'<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',\n\t\t'</select>',\n\t\t'<br />',\n    'Search: <input name=SEARCH value=\"',$MYREQUEST['SEARCH'],'\" type=text size=25/>',\n\t\t'&nbsp;<input type=submit value=\"GO!\">',\n\t\t'</form></div>';\n\n  if (isset($MYREQUEST['SEARCH'])) {\n   // Don't use preg_quote because we want the user to be able to specify a\n   // regular expression subpattern.\n   $MYREQUEST['SEARCH'] = '/'.str_replace('/', '\\\\/', $MYREQUEST['SEARCH']).'/i';\n   if (preg_match($MYREQUEST['SEARCH'], 'test') === false) {\n     echo '<div class=\"error\">Error: enter a valid regular expression as a search query.</div>';\n     break;\n   }\n  }\n\n  echo\n\t\t'<div class=\"info\"><table cellspacing=0><tbody>',\n\t\t'<tr>',\n\t\t'<th>',sortheader('S',$fieldheading,  \"&OB=\".$MYREQUEST['OB']),'</th>',\n\t\t'<th>',sortheader('H','Hits',         \"&OB=\".$MYREQUEST['OB']),'</th>',\n\t\t'<th>',sortheader('Z','Size',         \"&OB=\".$MYREQUEST['OB']),'</th>',\n\t\t'<th>',sortheader('A','Last accessed',\"&OB=\".$MYREQUEST['OB']),'</th>',\n\t\t'<th>',sortheader('M','Last modified',\"&OB=\".$MYREQUEST['OB']),'</th>',\n\t\t'<th>',sortheader('C','Created at',   \"&OB=\".$MYREQUEST['OB']),'</th>';\n\n\tif($fieldname=='info') {\n\t\t$cols+=2;\n\t\t echo '<th>',sortheader('T','Timeout',\"&OB=\".$MYREQUEST['OB']),'</th>';\n\t}\n\techo '<th>',sortheader('D','Deleted at',\"&OB=\".$MYREQUEST['OB']),'</th></tr>';\n\n\t// builds list with alpha numeric sortable keys\n\t//\n\t$list = array();\n\tforeach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) {\n\t\tswitch($MYREQUEST['SORT1']) {\n\t\t\tcase 'A': $k=sprintf('%015d-',$entry['access_time']); \tbreak;\n\t\t\tcase 'H': $k=sprintf('%015d-',$entry['num_hits']); \t\tbreak;\n\t\t\tcase 'Z': $k=sprintf('%015d-',$entry['mem_size']); \t\tbreak;\n\t\t\tcase 'M': $k=sprintf('%015d-',$entry['mtime']);\t\t\tbreak;\n\t\t\tcase 'C': $k=sprintf('%015d-',$entry['creation_time']);\tbreak;\n\t\t\tcase 'T': $k=sprintf('%015d-',$entry['ttl']);\t\t\tbreak;\n\t\t\tcase 'D': $k=sprintf('%015d-',$entry['deletion_time']);\tbreak;\n\t\t\tcase 'S': $k='';\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t}\n\t\tif (!$AUTHENTICATED) {\n\t\t\t// hide all path entries if not logged in\n\t\t\t$list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\\\/|\\\\\\\\)/','*hidden*/',$entry);\n\t\t} else {\n\t\t\t$list[$k.$entry[$fieldname]]=$entry;\n\t\t}\n\t}\n\n\tif ($list) {\n\t\t\n\t\t// sort list\n\t\t//\n\t\tswitch ($MYREQUEST['SORT2']) {\n\t\t\tcase \"A\":\tkrsort($list);\tbreak;\n\t\t\tcase \"D\":\tksort($list);\tbreak;\n\t\t}\n\t\t\n\t\t// output list\n\t\t$i=0;\n\t\tforeach($list as $k => $entry) {\n      if(!$MYREQUEST['SEARCH'] || preg_match($MYREQUEST['SEARCH'], $entry[$fieldname]) != 0) {  \n        $field_value = htmlentities(strip_tags($entry[$fieldname],''), ENT_QUOTES, 'UTF-8');\n        echo\n          '<tr class=tr-',$i%2,'>',\n          \"<td class=td-0><a href=\\\"$MY_SELF&OB=\",$MYREQUEST['OB'],\"&SH=\",md5($entry[$fieldkey]),\"\\\">\",$field_value,'</a></td>',\n          '<td class=\"td-n center\">',$entry['num_hits'],'</td>',\n          '<td class=\"td-n right\">',$entry['mem_size'],'</td>',\n          '<td class=\"td-n center\">',date(DATE_FORMAT,$entry['access_time']),'</td>',\n          '<td class=\"td-n center\">',date(DATE_FORMAT,$entry['mtime']),'</td>',\n          '<td class=\"td-n center\">',date(DATE_FORMAT,$entry['creation_time']),'</td>';\n\n        if($fieldname=='info') {\n          if($entry['ttl'])\n            echo '<td class=\"td-n center\">'.$entry['ttl'].' seconds</td>';\n          else\n            echo '<td class=\"td-n center\">None</td>';\n        }\n        if ($entry['deletion_time']) {\n\n          echo '<td class=\"td-last center\">', date(DATE_FORMAT,$entry['deletion_time']), '</td>';\n        } else if ($MYREQUEST['OB'] == OB_USER_CACHE) {\n\n          echo '<td class=\"td-last center\">';\n          echo '[<a href=\"', $MY_SELF, '&OB=', $MYREQUEST['OB'], '&DU=', urlencode($entry[$fieldkey]), '\">Delete Now</a>]';\n          echo '</td>';\n        } else {\n          echo '<td class=\"td-last center\"> &nbsp; </td>';\n        }\n        echo '</tr>';\n        $i++;\n        if ($i == $MYREQUEST['COUNT'])\n          break;\n      }\n\t\t}\n\t\t\n\t} else {\n\t\techo '<tr class=tr-0><td class=\"center\" colspan=',$cols,'><i>No data</i></td></tr>';\n\t}\n\techo <<< EOB\n\t\t</tbody></table>\nEOB;\n\n\tif ($list && $i < count($list)) {\n\t\techo \"<a href=\\\"$MY_SELF&OB=\",$MYREQUEST['OB'],\"&COUNT=0\\\"><i>\",count($list)-$i,' more available...</i></a>';\n\t}\n\n\techo <<< EOB\n\t\t</div>\nEOB;\n\tbreak;\n\n\n// -----------------------------------------------\n// Per-Directory System Cache Entries\n// -----------------------------------------------\ncase OB_SYS_CACHE_DIR:\t\n\tif (!$AUTHENTICATED) {\n\t\tbreak;\n\t}\n\n\techo <<<EOB\n\t\t<div class=sorting><form>Scope:\n\t\t<input type=hidden name=OB value={$MYREQUEST['OB']}>\n\t\t<select name=SCOPE>\nEOB;\n\techo \n\t\t\"<option value=A\",$MYREQUEST['SCOPE']=='A' ? \" selected\":\"\",\">Active</option>\",\n\t\t\"<option value=D\",$MYREQUEST['SCOPE']=='D' ? \" selected\":\"\",\">Deleted</option>\",\n\t\t\"</select>\",\n\t\t\" Sorting: <select name=SORT1>\",\n\t\t\"<option value=H\",$MYREQUEST['SORT1']=='H' ? \" selected\":\"\",\">Total Hits</option>\",\n\t\t\"<option value=Z\",$MYREQUEST['SORT1']=='Z' ? \" selected\":\"\",\">Total Size</option>\",\n\t\t\"<option value=T\",$MYREQUEST['SORT1']=='T' ? \" selected\":\"\",\">Number of Files</option>\",\n\t\t\"<option value=S\",$MYREQUEST['SORT1']=='S' ? \" selected\":\"\",\">Directory Name</option>\",\n\t\t\"<option value=A\",$MYREQUEST['SORT1']=='A' ? \" selected\":\"\",\">Avg. Size</option>\",\n\t\t\"<option value=C\",$MYREQUEST['SORT1']=='C' ? \" selected\":\"\",\">Avg. Hits</option>\",\n\t\t'</select> ',\n\t\t'<select name=SORT2>',\n\t\t'<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',\n\t\t'<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',\n\t\t'</select> ',\n\t\t'<select name=COUNT onChange=\"form.submit()\">',\n\t\t'<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',\n\t\t'<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',\n\t\t'<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',\n\t\t'<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',\n\t\t'<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',\n\t\t'<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',\n\t\t'<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',\n\t\t'<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',\n\t\t'</select> ',\n\t\t\"Group By Dir Level: <select name=AGGR>\",\n\t\t\"<option value='' selected>None</option>\";\n\t\tfor ($i = 1; $i < 10; $i++)\n\t\t\techo \"<option value=$i\",$MYREQUEST['AGGR']==$i ? \" selected\":\"\",\">$i</option>\";\n\t\techo '</select>',\n\t\t'&nbsp;<input type=submit value=\"GO!\">',\n\t\t'</form></div>',\n\n\t\t'<div class=\"info\"><table cellspacing=0><tbody>',\n\t\t'<tr>',\n\t\t'<th>',sortheader('S','Directory Name',\t\"&OB=\".$MYREQUEST['OB']),'</th>',\n\t\t'<th>',sortheader('T','Number of Files',\"&OB=\".$MYREQUEST['OB']),'</th>',\n\t\t'<th>',sortheader('H','Total Hits',\t\"&OB=\".$MYREQUEST['OB']),'</th>',\n\t\t'<th>',sortheader('Z','Total Size',\t\"&OB=\".$MYREQUEST['OB']),'</th>',\n\t\t'<th>',sortheader('C','Avg. Hits',\t\"&OB=\".$MYREQUEST['OB']),'</th>',\n\t\t'<th>',sortheader('A','Avg. Size',\t\"&OB=\".$MYREQUEST['OB']),'</th>',\n\t\t'</tr>';\n\n\t// builds list with alpha numeric sortable keys\n\t//\n\t$tmp = $list = array();\n\tforeach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) {\n\t\t$n = dirname($entry['filename']);\n\t\tif ($MYREQUEST['AGGR'] > 0) {\n\t\t\t$n = preg_replace(\"!^(/?(?:[^/\\\\\\\\]+[/\\\\\\\\]){\".($MYREQUEST['AGGR']-1).\"}[^/\\\\\\\\]*).*!\", \"$1\", $n);\n\t\t}\n\t\tif (!isset($tmp[$n])) {\n\t\t\t$tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0);\n\t\t}\n\t\t$tmp[$n]['hits'] += $entry['num_hits'];\n\t\t$tmp[$n]['size'] += $entry['mem_size'];\n\t\t++$tmp[$n]['ents'];\n\t}\n\n\tforeach ($tmp as $k => $v) {\n\t\tswitch($MYREQUEST['SORT1']) {\n\t\t\tcase 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break;\n\t\t\tcase 'T': $kn=sprintf('%015d-',$v['ents']);\t\tbreak;\n\t\t\tcase 'H': $kn=sprintf('%015d-',$v['hits']);\t\tbreak;\n\t\t\tcase 'Z': $kn=sprintf('%015d-',$v['size']);\t\tbreak;\n\t\t\tcase 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break;\n\t\t\tcase 'S': $kn = $k;\t\t\t\t\tbreak;\n\t\t}\n\t\t$list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']);\n\t}\n\n\tif ($list) {\n\t\t\n\t\t// sort list\n\t\t//\n\t\tswitch ($MYREQUEST['SORT2']) {\n\t\t\tcase \"A\":\tkrsort($list);\tbreak;\n\t\t\tcase \"D\":\tksort($list);\tbreak;\n\t\t}\n\t\t\n\t\t// output list\n\t\t$i = 0;\n\t\tforeach($list as $entry) {\n\t\t\techo\n\t\t\t\t'<tr class=tr-',$i%2,'>',\n\t\t\t\t\"<td class=td-0>\",$entry[0],'</a></td>',\n\t\t\t\t'<td class=\"td-n center\">',$entry[1],'</td>',\n\t\t\t\t'<td class=\"td-n center\">',$entry[2],'</td>',\n\t\t\t\t'<td class=\"td-n center\">',$entry[3],'</td>',\n\t\t\t\t'<td class=\"td-n center\">',round($entry[2] / $entry[1]),'</td>',\n\t\t\t\t'<td class=\"td-n center\">',round($entry[3] / $entry[1]),'</td>',\n\t\t\t\t'</tr>';\n\n\t\t\tif (++$i == $MYREQUEST['COUNT']) break;\n\t\t}\n\t\t\n\t} else {\n\t\techo '<tr class=tr-0><td class=\"center\" colspan=6><i>No data</i></td></tr>';\n\t}\n\techo <<< EOB\n\t\t</tbody></table>\nEOB;\n\n\tif ($list && $i < count($list)) {\n\t\techo \"<a href=\\\"$MY_SELF&OB=\",$MYREQUEST['OB'],\"&COUNT=0\\\"><i>\",count($list)-$i,' more available...</i></a>';\n\t}\n\n\techo <<< EOB\n\t\t</div>\nEOB;\n\tbreak;\n\n// -----------------------------------------------\n// Version check\n// -----------------------------------------------\ncase OB_VERSION_CHECK:\n\techo <<<EOB\n\t\t<div class=\"info\"><h2>APC Version Information</h2>\n\t\t<table cellspacing=0><tbody>\n\t\t<tr>\n\t\t<th></th>\n\t\t</tr>\nEOB;\n  if (defined('PROXY')) {\n    $ctxt = stream_context_create( array( 'http' => array( 'proxy' => PROXY, 'request_fulluri' => True ) ) );\n    $rss = @file_get_contents(\"http://pecl.php.net/feeds/pkg_apc.rss\", False, $ctxt);\n  } else {\n    $rss = @file_get_contents(\"http://pecl.php.net/feeds/pkg_apc.rss\");\n  }\n\tif (!$rss) {\n\t\techo '<tr class=\"td-last center\"><td>Unable to fetch version information.</td></tr>';\n\t} else {\n\t\t$apcversion = phpversion('apc');\n\n\t\tpreg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match);\n\t\techo '<tr class=\"tr-0 center\"><td>';\n\t\tif (version_compare($apcversion, $match[1], '>=')) {\n\t\t\techo '<div class=\"ok\">You are running the latest version of APC ('.$apcversion.')</div>';\n\t\t\t$i = 3;\n\t\t} else {\n\t\t\techo '<div class=\"failed\">You are running an older version of APC ('.$apcversion.'), \n\t\t\t\tnewer version '.$match[1].' is available at <a href=\"http://pecl.php.net/package/APC/'.$match[1].'\">\n\t\t\t\thttp://pecl.php.net/package/APC/'.$match[1].'</a>\n\t\t\t\t</div>';\n\t\t\t$i = -1;\n\t\t}\n\t\techo '</td></tr>';\n\t\techo '<tr class=\"tr-0\"><td><h3>Change Log:</h3><br/>';\n\n\t\tpreg_match_all('!<(title|description)>([^<]+)</\\\\1>!', $rss, $match);\n\t\tnext($match[2]); next($match[2]);\n\n\t\twhile (list(,$v) = each($match[2])) {\n\t\t\tlist(,$ver) = explode(' ', $v, 2);\n\t\t\tif ($i < 0 && version_compare($apcversion, $ver, '>=')) {\n\t\t\t\tbreak;\n\t\t\t} else if (!$i--) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\techo \"<b><a href=\\\"http://pecl.php.net/package/APC/$ver\\\">\".htmlspecialchars($v, ENT_QUOTES, 'UTF-8').\"</a></b><br><blockquote>\";\n\t\t\techo nl2br(htmlspecialchars(current($match[2]), ENT_QUOTES, 'UTF-8')).\"</blockquote>\";\n\t\t\tnext($match[2]);\n\t\t}\n\t\techo '</td></tr>';\n\t}\n\techo <<< EOB\n\t\t</tbody></table>\n\t\t</div>\nEOB;\n\tbreak;\n\n}\n\necho <<< EOB\n\t</div>\nEOB;\n\n?>\n\n<!-- <?php echo \"\\nBased on APCGUI By R.Becker\\n$VERSION\\n\"?> -->\n<?php /*\n</body>\n</html>\n*/"
  },
  {
    "path": "admin/codemirror/codemirror.css",
    "content": ".CodeMirror {\n  line-height: 1em;\n  font-family: monospace;\n\n  /* Necessary so the scrollbar can be absolutely positioned within the wrapper on Lion. */\n  position: relative;\n  /* This prevents unwanted scrollbars from showing up on the body and wrapper in IE. */\n  overflow: hidden;\n}\n\n.CodeMirror-scroll {\n  overflow-x: auto;\n  overflow-y: hidden;\n  height: 300px;\n  /* This is needed to prevent an IE[67] bug where the scrolled content\n     is visible outside of the scrolling box. */\n  position: relative;\n  outline: none;\n}\n\n/* Vertical scrollbar */\n.CodeMirror-scrollbar {\n  float: right;\n  overflow-x: hidden;\n  overflow-y: scroll;\n\n  /* This corrects for the 1px gap introduced to the left of the scrollbar\n     by the rule for .CodeMirror-scrollbar-inner. */\n  margin-left: -1px;\n}\n.CodeMirror-scrollbar-inner {\n  /* This needs to have a nonzero width in order for the scrollbar to appear\n     in Firefox and IE9. */\n  width: 1px;\n}\n.CodeMirror-scrollbar.cm-sb-overlap {\n  /* Ensure that the scrollbar appears in Lion, and that it overlaps the content\n     rather than sitting to the right of it. */\n  position: absolute;\n  z-index: 1;\n  float: none;\n  right: 0;\n  min-width: 12px;\n}\n.CodeMirror-scrollbar.cm-sb-nonoverlap {\n  min-width: 12px;\n}\n.CodeMirror-scrollbar.cm-sb-ie7 {\n  min-width: 18px;\n}\n\n.CodeMirror-gutter {\n  position: absolute; left: 0; top: 0;\n  z-index: 10;\n  background-color: #f7f7f7;\n  border-right: 1px solid #eee;\n  min-width: 2em;\n  height: 100%;\n}\n.CodeMirror-gutter-text {\n  color: #aaa;\n  text-align: right;\n  padding: .4em .2em .4em .4em;\n  white-space: pre !important;\n  cursor: default;\n}\n.CodeMirror-lines {\n  padding: .4em;\n  white-space: pre;\n  cursor: text;\n}\n.CodeMirror-lines * {\n  /* Necessary for throw-scrolling to decelerate properly on Safari. */\n  pointer-events: none;\n}\n\n.CodeMirror pre {\n  -moz-border-radius: 0;\n  -webkit-border-radius: 0;\n  -o-border-radius: 0;\n  border-radius: 0;\n  border-width: 0; margin: 0; padding: 0; background: transparent;\n  font-family: inherit;\n  font-size: inherit;\n  padding: 0; margin: 0;\n  white-space: pre;\n  word-wrap: normal;\n  line-height: inherit;\n  color: inherit;\n}\n\n.CodeMirror-wrap pre {\n  word-wrap: break-word;\n  white-space: pre-wrap;\n  word-break: normal;\n}\n.CodeMirror-wrap .CodeMirror-scroll {\n  overflow-x: hidden;\n}\n\n.CodeMirror textarea {\n  outline: none !important;\n}\n\n.CodeMirror pre.CodeMirror-cursor {\n  z-index: 10;\n  position: absolute;\n  visibility: hidden;\n  border-left: 1px solid black;\n  border-right: none;\n  width: 0;\n}\n.cm-keymap-fat-cursor pre.CodeMirror-cursor {\n  width: auto;\n  border: 0;\n  background: transparent;\n  background: rgba(0, 200, 0, .4);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);\n}\n/* Kludge to turn off filter in ie9+, which also accepts rgba */\n.cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) {\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n.CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {}\n.CodeMirror-focused pre.CodeMirror-cursor {\n  visibility: visible;\n}\n\ndiv.CodeMirror-selected { background: #d9d9d9; }\n.CodeMirror-focused div.CodeMirror-selected { background: #d7d4f0; }\n\n.CodeMirror-searching {\n  background: #ffa;\n  background: rgba(255, 255, 0, .4);\n}\n\n/* Default theme */\n\n.cm-s-default span.cm-keyword {color: #708;}\n.cm-s-default span.cm-atom {color: #219;}\n.cm-s-default span.cm-number {color: #164;}\n.cm-s-default span.cm-def {color: #00f;}\n.cm-s-default span.cm-variable {color: black;}\n.cm-s-default span.cm-variable-2 {color: #05a;}\n.cm-s-default span.cm-variable-3 {color: #085;}\n.cm-s-default span.cm-property {color: black;}\n.cm-s-default span.cm-operator {color: black;}\n.cm-s-default span.cm-comment {color: #a50;}\n.cm-s-default span.cm-string {color: #a11;}\n.cm-s-default span.cm-string-2 {color: #f50;}\n.cm-s-default span.cm-meta {color: #555;}\n.cm-s-default span.cm-error {color: #f00;}\n.cm-s-default span.cm-qualifier {color: #555;}\n.cm-s-default span.cm-builtin {color: #30a;}\n.cm-s-default span.cm-bracket {color: #cc7;}\n.cm-s-default span.cm-tag {color: #170;}\n.cm-s-default span.cm-attribute {color: #00c;}\n.cm-s-default span.cm-header {color: blue;}\n.cm-s-default span.cm-quote {color: #090;}\n.cm-s-default span.cm-hr {color: #999;}\n.cm-s-default span.cm-link {color: #00c;}\n\nspan.cm-header, span.cm-strong {font-weight: bold;}\nspan.cm-em {font-style: italic;}\nspan.cm-emstrong {font-style: italic; font-weight: bold;}\nspan.cm-link {text-decoration: underline;}\n\ndiv.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}\ndiv.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n"
  },
  {
    "path": "admin/codemirror/codemirror.js",
    "content": "var CodeMirror=function(){\"use strict\";function e(r,i){function un(e){if(s.onDragEvent&&s.onDragEvent(ln,I(e)))return;U(e)}function fn(e){return e>=0&&e<At.size}function cn(e){return D(At,e)}function hn(e,t){Vt=!0;var n=t-e.height;for(var r=e;r;r=r.parent)r.height+=n}function pn(e){var t={line:0,ch:0};Mn(t,{line:At.size-1,ch:cn(At.size-1).text.length},pt(e),t,t),qt=!0}function dn(e){var t=[];return At.iter(0,At.size,function(e){t.push(e.text)}),t.join(e||\"\\n\")}function vn(e){R.scrollTop!=Bt&&(Bt=St.scrollTop=R.scrollTop,rr([]))}function mn(e){s.fixedGutter&&bt.style.left!=St.scrollLeft+\"px\"&&(bt.style.left=St.scrollLeft+\"px\"),St.scrollTop!=Bt&&(Bt=St.scrollTop,R.scrollTop!=Bt&&(R.scrollTop=Bt),rr([])),s.onScroll&&s.onScroll(ln)}function gn(e){function u(t){g&&(St.draggable=!1),jt=!1,l(),c(),Math.abs(e.clientX-t.clientX)+Math.abs(e.clientY-t.clientY)<10&&(q(t),hr(n.line,n.ch,!0),Qn())}function m(e){if(i==\"single\")fr(n,e);else if(i==\"double\"){var t=br(e);it(e,d)?fr(t.from,v):fr(d,t.to)}else i==\"triple\"&&(it(e,d)?fr(v,dr({line:e.line,ch:0})):fr(d,dr({line:e.line+1,ch:0})))}function y(e){var t=Zr(e,!0);if(t&&!rt(t,a)){Mt||An(),a=t,m(t),qt=!1;var n=nr();if(t.line>=n.to||t.line<n.from)f=setTimeout(hi(function(){y(e)}),150)}}function b(e){clearTimeout(f);var t=Zr(e);t&&m(t),q(e),Qn(),qt=!0,w(),l()}ar(X(e,\"shiftKey\"));for(var t=z(e);t!=xt;t=t.parentNode)if(t.parentNode==Et&&t!=wt)return;for(var t=z(e);t!=xt;t=t.parentNode)if(t.parentNode==yt)return s.onGutterClick&&s.onGutterClick(ln,ct(yt.childNodes,t)+Kt,e),q(e);var n=Zr(e);switch(W(e)){case 3:h&&ei(e);return;case 2:n&&hr(n.line,n.ch,!0),setTimeout(Qn,20),q(e);return}if(!n){z(e)==St&&q(e);return}Mt||An();var r=+(new Date),i=\"single\";if(Ht&&Ht.time>r-400&&rt(Ht.pos,n))i=\"triple\",q(e),setTimeout(Qn,20),wr(n.line);else if(Pt&&Pt.time>r-400&&rt(Pt.pos,n)){i=\"double\",Ht={time:r,pos:n},q(e);var o=br(n);fr(o.from,o.to)}else Pt={time:r,pos:n};var a=n,f;if(s.dragDrop&&K&&!s.readOnly&&!rt(_t.from,_t.to)&&!it(n,_t.from)&&!it(_t.to,n)&&i==\"single\"){g&&(St.draggable=!0);var l=V(document,\"mouseup\",hi(u),!0),c=V(St,\"drop\",hi(u),!0);jt=!0,St.dragDrop&&St.dragDrop();return}q(e),i==\"single\"&&hr(n.line,n.ch,!0);var d=_t.from,v=_t.to,w=V(document,\"mousemove\",hi(function(e){clearTimeout(f),q(e),!p&&!W(e)?b(e):y(e)}),!0),l=V(document,\"mouseup\",hi(b),!0)}function yn(e){for(var t=z(e);t!=xt;t=t.parentNode)if(t.parentNode==yt)return q(e);q(e)}function bn(e){if(s.onDragEvent&&s.onDragEvent(ln,I(e)))return;q(e);var t=Zr(e,!0),n=e.dataTransfer.files;if(!t||s.readOnly)return;if(n&&n.length&&window.FileReader&&window.File){var r=n.length,i=Array(r),o=0,u=function(e,n){var s=new FileReader;s.onload=function(){i[n]=s.result,++o==r&&(t=dr(t),hi(function(){var e=qn(i.join(\"\"),t,t);fr(t,e)})())},s.readAsText(e)};for(var a=0;a<r;++a)u(n[a],a)}else{if(jt&&!it(t,_t.from)&&!it(_t.to,t))return;try{var i=e.dataTransfer.getData(\"Text\");i&&pi(function(){var e=_t.from,n=_t.to;fr(t,t),jt&&qn(\"\",e,n),Rn(i),Qn()})}catch(e){}}}function wn(e){var t=Wn();e.dataTransfer.setData(\"Text\",t);if(h||y||b){var n=ot(\"img\");n.scr=\"data:image/gif;base64,R0lGODdhAgACAIAAAAAAAP///ywAAAAAAgACAAACAoRRADs=\",e.dataTransfer.setDragImage(n,0,0)}}function En(e,t){if(typeof e==\"string\"){e=u[e];if(!e)return!1}var n=Dt;try{s.readOnly&&(It=!0),t&&(Dt=null),e(ln)}catch(r){if(r!=J)throw r;return!1}finally{Dt=n,It=!1}return!0}function xn(e){function u(){o=!0}var t=f(s.keyMap),n=t.auto;clearTimeout(Sn),n&&!c(e)&&(Sn=setTimeout(function(){f(s.keyMap)==t&&(s.keyMap=n.call?n.call(null,ln):n)},50));var r=vt[X(e,\"keyCode\")],i=!1;if(r==null||e.altGraphKey)return!1;X(e,\"altKey\")&&(r=\"Alt-\"+r),X(e,\"ctrlKey\")&&(r=\"Ctrl-\"+r),X(e,\"metaKey\")&&(r=\"Cmd-\"+r);var o=!1;return X(e,\"shiftKey\")?i=l(\"Shift-\"+r,s.extraKeys,s.keyMap,function(e){return En(e,!0)},u)||l(r,s.extraKeys,s.keyMap,function(e){if(typeof e==\"string\"&&/^go[A-Z]/.test(e))return En(e)},u):i=l(r,s.extraKeys,s.keyMap,En,u),o&&(i=!1),i&&(q(e),ti(),p&&(e.oldKeyCode=e.keyCode,e.keyCode=0)),i}function Tn(e,t){var n=l(\"'\"+t+\"'\",s.extraKeys,s.keyMap,function(e){return En(e,!0)});return n&&(q(e),ti()),n}function Cn(e){Mt||An(),p&&e.keyCode==27&&(e.returnValue=!1),rn&&Jn()&&(rn=!1);if(s.onKeyEvent&&s.onKeyEvent(ln,I(e)))return;var t=X(e,\"keyCode\");ar(t==16||X(e,\"shiftKey\"));var r=xn(e);b&&(Nn=r?t:null,!r&&t==88&&X(e,n?\"metaKey\":\"ctrlKey\")&&Rn(\"\"))}function kn(e){rn&&Jn();if(s.onKeyEvent&&s.onKeyEvent(ln,I(e)))return;var t=X(e,\"keyCode\"),n=X(e,\"charCode\");if(b&&t==Nn){Nn=null,q(e);return}if((b&&(!e.which||e.which<10)||E)&&xn(e))return;var r=String.fromCharCode(n==null?t:n);s.electricChars&&Lt.electricChars&&s.smartIndent&&!s.readOnly&&Lt.electricChars.indexOf(r)>-1&&setTimeout(hi(function(){Sr(_t.to.line,\"smart\")}),75);if(Tn(e,r))return;Vn()}function Ln(e){if(s.onKeyEvent&&s.onKeyEvent(ln,I(e)))return;X(e,\"keyCode\")==16&&(Dt=null)}function An(){if(s.readOnly==\"nocursor\")return;Mt||(s.onFocus&&s.onFocus(ln),Mt=!0,St.className.search(/\\bCodeMirror-focused\\b/)==-1&&(St.className+=\" CodeMirror-focused\"),Xt||Kn(!0)),Xn(),ti()}function On(){Mt&&(s.onBlur&&s.onBlur(ln),Mt=!1,Yt&&hi(function(){Yt&&(Yt(),Yt=null)})(),St.className=St.className.replace(\" CodeMirror-focused\",\"\")),clearInterval(kt),setTimeout(function(){Mt||(Dt=null)},150)}function Mn(e,t,n,r,i){if(It)return;if(on){var o=[];At.iter(e.line,t.line+1,function(e){o.push(e.text)}),on.addChange(e.line,n.length,o);while(on.done.length>s.undoDepth)on.done.shift()}Hn(e,t,n,r,i)}function _n(e,t){if(!e.length)return;var n=e.pop(),r=[];for(var i=n.length-1;i>=0;i-=1){var s=n[i],o=[],u=s.start+s.added;At.iter(s.start,u,function(e){o.push(e.text)}),r.push({start:s.start,added:s.old.length,old:o});var a={line:s.start+s.old.length-1,ch:lt(o[o.length-1],s.old[s.old.length-1])};Hn({line:s.start,ch:0},{line:u-1,ch:cn(u-1).text.length},s.old,a,a)}qt=!0,t.push(r)}function Dn(){_n(on.done,on.undone)}function Pn(){_n(on.undone,on.done)}function Hn(e,t,n,r,i){function x(e){return e<=Math.min(t.line,t.line+g)?e:e+g}if(It)return;var o=!1,u=Zt.text.length;s.lineWrapping||At.iter(e.line,t.line+1,function(e){if(!e.hidden&&e.text.length==u)return o=!0,!0});if(e.line!=t.line||n.length>1)Vt=!0;var a=t.line-e.line,f=cn(e.line),l=cn(t.line);if(e.ch==0&&t.ch==0&&n[n.length-1]==\"\"){var c=[],h=null;e.line?(h=cn(e.line-1),h.fixMarkEnds(l)):l.fixMarkStarts();for(var p=0,d=n.length-1;p<d;++p)c.push(A.inheritMarks(n[p],h));a&&At.remove(e.line,a,$t),c.length&&At.insert(e.line,c)}else if(f==l)if(n.length==1)f.replace(e.ch,t.ch,n[0]);else{l=f.split(t.ch,n[n.length-1]),f.replace(e.ch,null,n[0]),f.fixMarkEnds(l);var c=[];for(var p=1,d=n.length-1;p<d;++p)c.push(A.inheritMarks(n[p],f));c.push(l),At.insert(e.line+1,c)}else if(n.length==1)f.replace(e.ch,null,n[0]),l.replace(null,t.ch,\"\"),f.append(l),At.remove(e.line+1,a,$t);else{var c=[];f.replace(e.ch,null,n[0]),l.replace(null,t.ch,n[n.length-1]),f.fixMarkEnds(l);for(var p=1,d=n.length-1;p<d;++p)c.push(A.inheritMarks(n[p],f));a>1&&At.remove(e.line+1,a-1,$t),At.insert(e.line+1,c)}if(s.lineWrapping){var v=Math.max(5,St.clientWidth/Qr()-3);At.iter(e.line,e.line+n.length,function(e){if(e.hidden)return;var t=Math.ceil(e.text.length/v)||1;t!=e.height&&hn(e,t)})}else At.iter(e.line,e.line+n.length,function(e){var t=e.text;!e.hidden&&t.length>u&&(Zt=e,u=t.length,tn=!0,o=!1)}),o&&(en=!0);var m=[],g=n.length-a-1;for(var p=0,y=Ot.length;p<y;++p){var b=Ot[p];b<e.line?m.push(b):b>t.line&&m.push(b+g)}var w=e.line+Math.min(n.length,500);oi(e.line,w),m.push(w),Ot=m,ai(100),Ut.push({from:e.line,to:t.line+1,diff:g});var E={from:e,to:t,text:n};if(zt){for(var S=zt;S.next;S=S.next);S.next=E}else zt=E;lr(dr(r),dr(i),x(_t.from.line),x(_t.to.line))}function Bn(){var e=At.height*$r()+2*Gr();return e-1>St.offsetHeight?e:!1}function jn(e){var t=Bn();R.style.display=t?\"block\":\"none\",t?(F.style.height=Et.style.minHeight=t+\"px\",R.style.height=St.clientHeight+\"px\",e!=null&&(R.scrollTop=St.scrollTop=e)):Et.style.minHeight=\"\",wt.style.top=Jt*$r()+\"px\"}function Fn(){var e=ot(\"div\",null,\"CodeMirror-scrollbar-inner\",\"height: 200px\"),t=ot(\"div\",[e],\"CodeMirror-scrollbar\",\"position: absolute; left: -9999px; height: 100px;\");document.body.appendChild(t);var n=t.offsetWidth<=1;return document.body.removeChild(t),n}function In(){Zt=cn(0),tn=!0;var e=Zt.text.length;At.iter(1,At.size,function(t){var n=t.text;!t.hidden&&n.length>e&&(e=n.length,Zt=t)}),en=!1}function qn(e,t,n){function r(r){if(it(r,t))return r;if(!it(n,r))return i;var s=r.line+e.length-(n.line-t.line)-1,o=r.ch;return r.line==n.line&&(o+=e[e.length-1].length-(n.ch-(n.line==t.line?t.ch:0))),{line:s,ch:o}}t=dr(t),n?n=dr(n):n=t,e=pt(e);var i;return Un(e,t,n,function(e){return i=e,{from:r(_t.from),to:r(_t.to)}}),i}function Rn(e,t){Un(pt(e),_t.from,_t.to,function(e){return t==\"end\"?{from:e,to:e}:t==\"start\"?{from:_t.from,to:_t.from}:{from:_t.from,to:e}})}function Un(e,t,n,r){var i=e.length==1?e[0].length+t.ch:e[e.length-1].length,s=r({line:t.line+e.length-1,ch:i});Mn(t,n,e,s.from,s.to)}function zn(e,t,n){var r=e.line,i=t.line;if(r==i)return cn(r).text.slice(e.ch,t.ch);var s=[cn(r).text.slice(e.ch)];return At.iter(r+1,i,function(e){s.push(e.text)}),s.push(cn(i).text.slice(0,t.ch)),s.join(n||\"\\n\")}function Wn(e){return zn(_t.from,_t.to,e)}function Xn(){if(rn)return;Nt.set(s.pollInterval,function(){fi(),Jn(),Mt&&Xn(),li()})}function Vn(){function t(){fi();var n=Jn();!n&&!e?(e=!0,Nt.set(60,t)):(rn=!1,Xn()),li()}var e=!1;rn=!0,Nt.set(20,t)}function Jn(){if(Xt||!Mt||dt(L)||s.readOnly)return!1;var e=L.value;if(e==$n)return!1;Dt=null;var t=0,n=Math.min($n.length,e.length);while(t<n&&$n[t]==e[t])++t;return t<$n.length?_t.from={line:_t.from.line,ch:_t.from.ch-($n.length-t)}:Ft&&rt(_t.from,_t.to)&&(_t.to={line:_t.to.line,ch:Math.min(cn(_t.to.line).text.length,_t.to.ch+(e.length-t))}),Rn(e.slice(t),\"end\"),e.length>1e3?L.value=$n=\"\":$n=e,!0}function Kn(e){rt(_t.from,_t.to)?e&&($n=L.value=\"\"):($n=\"\",L.value=Wn(),nt(L))}function Qn(){s.readOnly!=\"nocursor\"&&L.focus()}function Gn(){var e=Z.getBoundingClientRect();if(p&&e.top==e.bottom)return;var t=window.innerHeight||Math.max(document.body.offsetHeight,document.documentElement.offsetHeight);(e.top<0||e.bottom>t)&&Yn()}function Yn(){var e=Zn();er(e.x,e.y,e.x,e.yBot)}function Zn(){var e=Rr(_t.inverted?_t.from:_t.to),t=s.lineWrapping?Math.min(e.x,gt.offsetWidth):e.x;return{x:t,y:e.y,yBot:e.yBot}}function er(e,t,n,r){var i=tr(e,t,n,r);i.scrollLeft!=null&&(St.scrollLeft=i.scrollLeft),i.scrollTop!=null&&(R.scrollTop=St.scrollTop=i.scrollTop)}function tr(e,t,n,r){var i=Yr(),o=Gr();t+=o,r+=o,e+=i,n+=i;var u=St.clientHeight,a=R.scrollTop,f={},l=Bn()||Infinity,c=t<o+10,h=r+o>l-10;t<a?f.scrollTop=c?0:Math.max(0,t):r>a+u&&(f.scrollTop=(h?l:r)-u);var p=St.clientWidth,d=St.scrollLeft,v=s.fixedGutter?bt.clientWidth:0,m=e<v+i+10;return e<d+v||m?(m&&(e=0),f.scrollLeft=Math.max(0,e-10-v)):n>p+d-3&&(f.scrollLeft=n+10-p),f}function nr(e){var t=$r(),n=(e!=null?e:R.scrollTop)-Gr(),r=Math.max(0,Math.floor(n/t)),i=Math.ceil((n+St.clientHeight)/t);return{from:H(At,r),to:H(At,i)}}function rr(e,t,n){function d(){var e=Q.firstChild,t=!1;return At.iter(Kt,Qt,function(n){if(!e)return;if(!n.hidden){var r=Math.round(e.offsetHeight/c)||1;n.height!=r&&(hn(n,r),Vt=t=!0)}e=e.nextSibling}),t}if(!St.clientWidth){Kt=Qt=Jt=0;return}var r=nr(n);if(e!==!0&&e.length==0&&r.from>Kt&&r.to<Qt){jn(n);return}var i=Math.max(r.from-100,0),o=Math.min(At.size,r.to+100);Kt<i&&i-Kt<20&&(i=Kt),Qt>o&&Qt-o<20&&(o=Math.min(At.size,Qt));var u=e===!0?[]:ir([{from:Kt,to:Qt,domStart:0}],e),a=0;for(var f=0;f<u.length;++f){var l=u[f];l.from<i&&(l.domStart+=i-l.from,l.from=i),l.to>o&&(l.to=o),l.from>=l.to?u.splice(f--,1):a+=l.to-l.from}if(a==o-i&&i==Kt&&o==Qt){jn(n);return}u.sort(function(e,t){return e.domStart-t.domStart});var c=$r(),h=bt.style.display;Q.style.display=\"none\",sr(i,o,u),Q.style.display=bt.style.display=\"\";var p=i!=Kt||o!=Qt||Gt!=St.clientHeight+c;p&&(Gt=St.clientHeight+c),Kt=i,Qt=o,Jt=B(At,i);if(Q.childNodes.length!=Qt-Kt)throw new Error(\"BAD PATCH! \"+JSON.stringify(u)+\" size=\"+(Qt-Kt)+\" nodes=\"+Q.childNodes.length);if(s.lineWrapping){d();var v=Bn(),m=v?\"block\":\"none\";R.style.display!=m&&(R.style.display=m,v&&(F.style.height=v+\"px\"),d())}return bt.style.display=h,(p||Vt)&&or()&&s.lineWrapping&&d()&&or(),jn(n),ur(),!t&&s.onUpdate&&s.onUpdate(ln),!0}function ir(e,t){for(var n=0,r=t.length||0;n<r;++n){var i=t[n],s=[],o=i.diff||0;for(var u=0,a=e.length;u<a;++u){var f=e[u];i.to<=f.from&&i.diff?s.push({from:f.from+o,to:f.to+o,domStart:f.domStart}):i.to<=f.from||i.from>=f.to?s.push(f):(i.from>f.from&&s.push({from:f.from,to:i.from,domStart:f.domStart}),i.to<f.to&&s.push({from:i.to+o,to:f.to+o,domStart:f.domStart+(i.to-f.from)}))}e=s}return e}function sr(e,t,n){function r(e){var t=e.nextSibling;return e.parentNode.removeChild(e),t}if(!n.length)ut(Q);else{var i=0,s=Q.firstChild,o;for(var u=0;u<n.length;++u){var a=n[u];while(a.domStart>i)s=r(s),i++;for(var f=0,l=a.to-a.from;f<l;++f)s=s.nextSibling,i++}while(s)s=r(s)}var c=n.shift(),s=Q.firstChild,f=e;At.iter(e,t,function(e){c&&c.to==f&&(c=n.shift());if(!c||c.from>f){if(e.hidden)var t=ot(\"pre\");else{var t=e.getElement(Cr);e.className&&(t.className=e.className);if(e.bgClassName){var r=ot(\"pre\",\"\\u00a0\",e.bgClassName,\"position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2\");t=ot(\"div\",[r,t],null,\"position: relative\")}}Q.insertBefore(t,s)}else s=s.nextSibling;++f})}function or(){if(!s.gutter&&!s.lineNumbers)return;var e=wt.offsetHeight,t=St.clientHeight;bt.style.height=(e-t<2?t:e)+\"px\";var n=document.createDocumentFragment(),r=Kt,i;At.iter(Kt,Math.max(Qt,Kt+1),function(e){if(e.hidden)n.appendChild(ot(\"pre\"));else{var t=e.gutterMarker,o=s.lineNumbers?s.lineNumberFormatter(r+s.firstLineNumber):null;t&&t.text?o=t.text.replace(\"%N%\",o!=null?o:\"\"):o==null&&(o=\"\\u00a0\");var u=n.appendChild(ot(\"pre\",null,t&&t.style));u.innerHTML=o;for(var a=1;a<e.height;++a)u.appendChild(ot(\"br\")),u.appendChild(document.createTextNode(\"\\u00a0\"));t||(i=r)}++r}),bt.style.display=\"none\",at(yt,n);if(i!=null&&s.lineNumbers){var o=yt.childNodes[i-Kt],u=String(At.size).length,a=tt(o.firstChild),f=\"\";while(a.length+f.length<u)f+=\"\\u00a0\";f&&o.insertBefore(document.createTextNode(f),o.firstChild)}bt.style.display=\"\";var l=Math.abs((parseInt(gt.style.marginLeft)||0)-bt.offsetWidth)>2;return gt.style.marginLeft=bt.offsetWidth+\"px\",Vt=!1,l}function ur(){var e=rt(_t.from,_t.to),t=Rr(_t.from,!0),n=e?t:Rr(_t.to,!0),r=_t.inverted?t:n,i=$r(),o=et(xt),u=et(Q);O.style.top=Math.max(0,Math.min(St.offsetHeight,r.y+u.top-o.top))+\"px\",O.style.left=Math.max(0,Math.min(St.offsetWidth,r.x+u.left-o.left))+\"px\";if(e)Z.style.top=r.y+\"px\",Z.style.left=(s.lineWrapping?Math.min(r.x,gt.offsetWidth):r.x)+\"px\",Z.style.display=\"\",Y.style.display=\"none\";else{var a=t.y==n.y,f=document.createDocumentFragment(),l=gt.clientWidth||gt.offsetWidth,c=gt.clientHeight||gt.offsetHeight,h=function(e,t,n,r){var i=m?\"width: \"+(n?l-n-e:l)+\"px\":\"right: \"+n+\"px\";f.appendChild(ot(\"div\",null,\"CodeMirror-selected\",\"position: absolute; left: \"+e+\"px; top: \"+t+\"px; \"+i+\"; height: \"+r+\"px\"))};if(_t.from.ch&&t.y>=0){var p=a?l-n.x:0;h(t.x,t.y,p,i)}var d=Math.max(0,t.y+(_t.from.ch?i:0)),v=Math.min(n.y,c)-d;v>.2*i&&h(0,d,0,v),(!a||!_t.from.ch)&&n.y<c-.5*i&&h(0,n.y,l-n.x,i),at(Y,f),Z.style.display=\"none\",Y.style.display=\"\"}}function ar(e){e?Dt=Dt||(_t.inverted?_t.to:_t.from):Dt=null}function fr(e,t){var n=Dt&&dr(Dt);n&&(it(n,e)?e=n:it(t,n)&&(t=n)),lr(e,t),Rt=!0}function lr(e,t,n,r){sn=null,n==null&&(n=_t.from.line,r=_t.to.line);if(rt(_t.from,e)&&rt(_t.to,t))return;if(it(t,e)){var i=t;t=e,e=i}if(e.line!=n){var o=cr(e,n,_t.from.ch);o?e=o:jr(e.line,!1)}t.line!=r&&(t=cr(t,r,_t.to.ch)),rt(e,t)?_t.inverted=!1:rt(e,_t.to)?_t.inverted=!1:rt(t,_t.from)&&(_t.inverted=!0);if(s.autoClearEmptyLines&&rt(_t.from,_t.to)){var u=_t.inverted?e:t;if(u.line!=_t.from.line&&_t.from.line<At.size){var a=cn(_t.from.line);/^\\s+$/.test(a.text)&&setTimeout(hi(function(){if(a.parent&&/^\\s+$/.test(a.text)){var e=P(a);qn(\"\",{line:e,ch:0},{line:e,ch:a.text.length})}},10))}}_t.from=e,_t.to=t,Wt=!0}function cr(e,t,n){function r(t){var r=e.line+t,i=t==1?At.size:-1;while(r!=i){var o=cn(r);if(!o.hidden){var u=e.ch;if(s||u>n||u>o.text.length)u=o.text.length;return{line:r,ch:u}}r+=t}}var i=cn(e.line),s=e.ch==i.text.length&&e.ch!=n;return i.hidden?e.line>=t?r(1)||r(-1):r(-1)||r(1):e}function hr(e,t,n){var r=dr({line:e,ch:t||0});(n?fr:lr)(r,r)}function pr(e){return Math.max(0,Math.min(e,At.size-1))}function dr(e){if(e.line<0)return{line:0,ch:0};if(e.line>=At.size)return{line:At.size-1,ch:cn(At.size-1).text.length};var t=e.ch,n=cn(e.line).text.length;return t==null||t>n?{line:e.line,ch:n}:t<0?{line:e.line,ch:0}:e}function vr(e,t){function o(){for(var t=r+e,n=e<0?-1:At.size;t!=n;t+=e){var i=cn(t);if(!i.hidden)return r=t,s=i,!0}}function u(t){if(i==(e<0?0:s.text.length)){if(!!t||!o())return!1;i=e<0?s.text.length:0}else i+=e;return!0}var n=_t.inverted?_t.from:_t.to,r=n.line,i=n.ch,s=cn(r);if(t==\"char\")u();else if(t==\"column\")u(!0);else if(t==\"word\"){var a=!1;for(;;){if(e<0&&!u())break;if(ht(s.text.charAt(i)))a=!0;else if(a){e<0&&(e=1,u());break}if(e>0&&!u())break}}return{line:r,ch:i}}function mr(e,t){var n=e<0?_t.from:_t.to;if(Dt||rt(_t.from,_t.to))n=vr(e,t);hr(n.line,n.ch,!0)}function gr(e,t){rt(_t.from,_t.to)?e<0?qn(\"\",vr(e,t),_t.to):qn(\"\",_t.from,vr(e,t)):qn(\"\",_t.from,_t.to),Rt=!0}function yr(e,t){var n=0,r=Rr(_t.inverted?_t.from:_t.to,!0);sn!=null&&(r.x=sn),t==\"page\"?n=Math.min(St.clientHeight,window.innerHeight||document.documentElement.clientHeight):t==\"line\"&&(n=$r());var i=Ur(r.x,r.y+n*e+2);t==\"page\"&&(R.scrollTop+=Rr(i,!0).y-r.y),hr(i.line,i.ch,!0),sn=r.x}function br(e){var t=cn(e.line).text,n=e.ch,r=e.ch;if(t){e.after===!1||r==t.length?--n:++r;var i=t.charAt(n),s=ht(i)?ht:/\\s/.test(i)?function(e){return/\\s/.test(e)}:function(e){return!/\\s/.test(e)&&!ht(e)};while(n>0&&s(t.charAt(n-1)))--n;while(r<t.length&&s(t.charAt(r)))++r}return{from:{line:e.line,ch:n},to:{line:e.line,ch:r}}}function wr(e){fr({line:e,ch:0},dr({line:e+1,ch:0}))}function Er(e){if(rt(_t.from,_t.to))return Sr(_t.from.line,e);var t=_t.to.line-(_t.to.ch?0:1);for(var n=_t.from.line;n<=t;++n)Sr(n,e)}function Sr(e,t){t||(t=\"add\");if(t==\"smart\")if(!Lt.indent)t=\"prev\";else var n=si(e);var r=cn(e),i=r.indentation(s.tabSize),o=r.text.match(/^\\s*/)[0],u;t==\"smart\"&&(u=Lt.indent(n,r.text.slice(o.length),r.text),u==J&&(t=\"prev\")),t==\"prev\"?e?u=cn(e-1).indentation(s.tabSize):u=0:t==\"add\"?u=i+s.indentUnit:t==\"subtract\"&&(u=i-s.indentUnit),u=Math.max(0,u);var a=u-i,f=\"\",l=0;if(s.indentWithTabs)for(var c=Math.floor(u/s.tabSize);c;--c)l+=s.tabSize,f+=\"\t\";while(l<u)++l,f+=\" \";qn(f,{line:e,ch:0},{line:e,ch:o.length})}function xr(){Lt=e.getMode(s,s.mode),At.iter(0,At.size,function(e){e.stateAfter=null}),Ot=[0],ai()}function Tr(){var e=s.gutter||s.lineNumbers;bt.style.display=e?\"\":\"none\",e?Vt=!0:Q.parentNode.style.marginLeft=0}function Nr(e,t){if(s.lineWrapping){xt.className+=\" CodeMirror-wrap\";var n=St.clientWidth/Qr()-3;At.iter(0,At.size,function(e){if(e.hidden)return;var t=Math.ceil(e.text.length/n)||1;t!=1&&hn(e,t)}),gt.style.minWidth=ft.style.left=\"\"}else xt.className=xt.className.replace(\" CodeMirror-wrap\",\"\"),In(),At.iter(0,At.size,function(e){e.height!=1&&!e.hidden&&hn(e,1)});Ut.push({from:0,to:At.size})}function Cr(e){var t=s.tabSize-e%s.tabSize,n=nn[t];if(n)return n;for(var r=\"\",i=0;i<t;++i)r+=\" \";var o=ot(\"span\",r,\"cm-tab\");return nn[t]={element:o,width:t}}function kr(){St.className=St.className.replace(/\\s*cm-s-\\S+/g,\"\")+s.theme.replace(/(^|\\s)\\s*/g,\" cm-s-\")}function Lr(){var e=a[s.keyMap].style;xt.className=xt.className.replace(/\\s*cm-keymap-\\S+/g,\"\")+(e?\" cm-keymap-\"+e:\"\")}function Ar(){this.set=[]}function Or(e,t,n){function i(e,t,n,i){cn(e).addMark(new C(t,n,i,r))}e=dr(e),t=dr(t);var r=new Ar;if(!it(e,t))return r;if(e.line==t.line)i(e.line,e.ch,t.ch,n);else{i(e.line,e.ch,null,n);for(var s=e.line+1,o=t.line;s<o;++s)i(s,null,null,n);i(t.line,null,t.ch,n)}return Ut.push({from:e.line,to:t.line+1}),r}function Mr(e){e=dr(e);var t=new k(e.ch);return cn(e.line).addMark(t),t}function _r(e){e=dr(e);var t=[],n=cn(e.line).marked;if(!n)return t;for(var r=0,i=n.length;r<i;++r){var s=n[r];(s.from==null||s.from<=e.ch)&&(s.to==null||s.to>=e.ch)&&t.push(s.marker||s)}return t}function Dr(e,t,n){return typeof e==\"number\"&&(e=cn(pr(e))),e.gutterMarker={text:t,style:n},Vt=!0,e}function Pr(e){typeof e==\"number\"&&(e=cn(pr(e))),e.gutterMarker=null,Vt=!0}function Hr(e,t){var n=e,r=e;return typeof e==\"number\"?r=cn(pr(e)):n=P(e),n==null?null:t(r,n)?(Ut.push({from:n,to:n+1}),r):null}function Br(e,t,n){return Hr(e,function(e){if(e.className!=t||e.bgClassName!=n)return e.className=t,e.bgClassName=n,!0})}function jr(e,t){return Hr(e,function(e,n){if(e.hidden!=t){e.hidden=t,s.lineWrapping||(t&&e.text.length==Zt.text.length?en=!0:!t&&e.text.length>Zt.text.length&&(Zt=e,en=!1)),hn(e,t?0:1);var r=_t.from.line,i=_t.to.line;if(t&&(r==n||i==n)){var o=r==n?cr({line:r,ch:0},r,0):_t.from,u=i==n?cr({line:i,ch:0},i,0):_t.to;if(!u)return;lr(o,u)}return Vt=!0}})}function Fr(e){if(typeof e==\"number\"){if(!fn(e))return null;var t=e;e=cn(e);if(!e)return null}else{var t=P(e);if(t==null)return null}var n=e.gutterMarker;return{line:t,handle:e,text:e.text,markerText:n&&n.text,markerClass:n&&n.style,lineClass:e.className,bgClass:e.bgClassName}}function Ir(e,t){function i(e){return qr(n,e).left}if(t<=0)return 0;var n=cn(e),r=n.text,s=0,o=0,u=r.length,a,f=Math.min(u,Math.ceil(t/Qr()));for(;;){var l=i(f);if(!(l<=t&&f<u)){a=l,u=f;break}f=Math.min(u,Math.ceil(f*1.2))}if(t>a)return u;f=Math.floor(u*.8),l=i(f),l<t&&(s=f,o=l);for(;;){if(u-s<=1)return a-t>t-o?s:u;var c=Math.ceil((s+u)/2),h=i(c);h>t?(u=c,a=h):(s=c,o=h)}}function qr(e,t){if(t==0)return{top:0,left:0};var n=s.lineWrapping&&t<e.text.length&&G.test(e.text.slice(t-1,t+1)),r=e.getElement(Cr,t,n);at(mt,r);var i=r.anchor,o=i.offsetTop,u=i.offsetLeft;if(p&&o==0&&u==0){var a=ot(\"span\",\"x\");i.parentNode.insertBefore(a,i.nextSibling),o=a.offsetTop}return{top:o,left:u}}function Rr(e,t){var n,r=$r(),i=r*(B(At,e.line)-(t?Jt:0));if(e.ch==0)n=0;else{var o=qr(cn(e.line),e.ch);n=o.left,s.lineWrapping&&(i+=Math.max(0,o.top))}return{x:n,y:i,yBot:i+r}}function Ur(e,t){function h(e){var t=qr(u,e);if(f){var r=Math.round(t.top/n);return c=r!=l,Math.max(0,t.left+(r-l)*St.clientWidth)}return t.left}if(t<0)return{line:0,ch:0};var n=$r(),r=Qr(),i=Jt+Math.floor(t/n),o=H(At,i);if(o>=At.size)return{line:At.size-1,ch:cn(At.size-1).text.length};var u=cn(o),a=u.text,f=s.lineWrapping,l=f?i-B(At,o):0;if(e<=0&&l==0)return{line:o,ch:0};var c=!1,p=0,d=0,v=a.length,m,g=Math.min(v,Math.ceil((e+l*St.clientWidth*.9)/r));for(;;){var y=h(g);if(!(y<=e&&g<v)){m=y,v=g;break}g=Math.min(v,Math.ceil(g*1.2))}if(e>m)return{line:o,ch:v};g=Math.floor(v*.8),y=h(g),y<e&&(p=g,d=y);for(;;){if(v-p<=1){var b=e-d<m-e;return{line:o,ch:b?p:v,after:b}}var w=Math.ceil((p+v)/2),E=h(w);E>e?(v=w,m=E,c&&(m+=1e3)):(p=w,d=E)}}function zr(e){var t=Rr(e,!0),n=et(gt);return{x:n.left+t.x,y:n.top+t.y,yBot:n.top+t.yBot}}function $r(){if(Vr==null){Vr=ot(\"pre\");for(var e=0;e<49;++e)Vr.appendChild(document.createTextNode(\"x\")),Vr.appendChild(ot(\"br\"));Vr.appendChild(document.createTextNode(\"x\"))}var t=Q.clientHeight;return t==Xr?Wr:(Xr=t,at(mt,Vr.cloneNode(!0)),Wr=mt.firstChild.offsetHeight/50||1,ut(mt),Wr)}function Qr(){if(St.clientWidth==Kr)return Jr;Kr=St.clientWidth;var e=ot(\"span\",\"x\"),t=ot(\"pre\",[e]);return at(mt,t),Jr=e.offsetWidth||10}function Gr(){return gt.offsetTop}function Yr(){return gt.offsetLeft}function Zr(e,t){var n=et(St,!0),r,i;try{r=e.clientX,i=e.clientY}catch(e){return null}if(!t&&(r-n.left>St.clientWidth||i-n.top>St.clientHeight))return null;var s=et(gt,!0);return Ur(r-s.left,i-s.top)}function ei(e){function o(){var e=pt(L.value).join(\"\\n\");e!=i&&!s.readOnly&&hi(Rn)(e,\"end\"),O.style.position=\"relative\",L.style.cssText=r,v&&(R.scrollTop=n),Xt=!1,Kn(!0),Xn()}var t=Zr(e),n=R.scrollTop;if(!t||b)return;(rt(_t.from,_t.to)||it(t,_t.from)||!it(t,_t.to))&&hi(hr)(t.line,t.ch);var r=L.style.cssText;O.style.position=\"absolute\",L.style.cssText=\"position: fixed; width: 30px; height: 30px; top: \"+(e.clientY-5)+\"px; left: \"+(e.clientX-5)+\"px; z-index: 1000; background: white; \"+\"border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);\",Xt=!0;var i=L.value=Wn();Qn(),nt(L);if(h){U(e);var u=V(window,\"mouseup\",function(){u(),setTimeout(o,20)},!0)}else setTimeout(o,50)}function ti(){clearInterval(kt);var e=!0;Z.style.visibility=\"\",kt=setInterval(function(){Z.style.visibility=(e=!e)?\"\":\"hidden\"},650)}function ri(e){function v(e,t,n){if(!e.text)return;var r=e.styles,i=o?0:e.text.length-1,s;for(var a=o?0:r.length-2,f=o?r.length:-2;a!=f;a+=2*u){var l=r[a];if(r[a+1]!=h){i+=u*l.length;continue}for(var c=o?0:l.length-1,v=o?l.length:-1;c!=v;c+=u,i+=u)if(i>=t&&i<n&&d.test(s=l.charAt(c))){var m=ni[s];if(m.charAt(1)==\">\"==o)p.push(s);else{if(p.pop()!=m.charAt(0))return{pos:i,match:!1};if(!p.length)return{pos:i,match:!0}}}}}var t=_t.inverted?_t.from:_t.to,n=cn(t.line),r=t.ch-1,i=r>=0&&ni[n.text.charAt(r)]||ni[n.text.charAt(++r)];if(!i)return;var s=i.charAt(0),o=i.charAt(1)==\">\",u=o?1:-1,a=n.styles;for(var f=r+1,l=0,c=a.length;l<c;l+=2)if((f-=a[l].length)<=0){var h=a[l+1];break}var p=[n.text.charAt(r)],d=/[(){}[\\]]/;for(var l=t.line,c=o?Math.min(l+100,At.size):Math.max(-1,l-100);l!=c;l+=u){var n=cn(l),m=l==t.line,g=v(n,m&&o?r+1:0,m&&!o?r:n.text.length);if(g)break}g||(g={pos:null,match:!1});var h=g.match?\"CodeMirror-matchingbracket\":\"CodeMirror-nonmatchingbracket\",y=Or({line:t.line,ch:r},{line:t.line,ch:r+1},h),b=g.pos!=null&&Or({line:l,ch:g.pos},{line:l,ch:g.pos+1},h),w=hi(function(){y.clear(),b&&b.clear()});e?setTimeout(w,800):Yt=w}function ii(e){var t,n;for(var r=e,i=e-40;r>i;--r){if(r==0)return 0;var o=cn(r-1);if(o.stateAfter)return r;var u=o.indentation(s.tabSize);if(n==null||t>u)n=r-1,t=u}return n}function si(e){var t=ii(e),n=t&&cn(t-1).stateAfter;return n?n=x(Lt,n):n=T(Lt),At.iter(t,e,function(e){e.highlight(Lt,n,s.tabSize),e.stateAfter=x(Lt,n)}),t<e&&Ut.push({from:t,to:e}),e<At.size&&!cn(e).stateAfter&&Ot.push(e),n}function oi(e,t){var n=si(e);At.iter(e,t,function(e){e.highlight(Lt,n,s.tabSize),e.stateAfter=x(Lt,n)})}function ui(){var e=+(new Date)+s.workTime,t=Ot.length;while(Ot.length){if(!cn(Kt).stateAfter)var n=Kt;else var n=Ot.pop();if(n>=At.size)continue;var r=ii(n),i=r&&cn(r-1).stateAfter;i?i=x(Lt,i):i=T(Lt);var o=0,u=Lt.compareStates,a=!1,f=r,l=!1;At.iter(f,At.size,function(t){var r=t.stateAfter;if(+(new Date)>e)return Ot.push(f),ai(s.workDelay),a&&Ut.push({from:n,to:f+1}),l=!0;var c=t.highlight(Lt,i,s.tabSize);c&&(a=!0),t.stateAfter=x(Lt,i);var h=null;if(u){var p=r&&u(r,i);p!=J&&(h=!!p)}h==null&&(c!==!1||!r?o=0:++o>3&&(!Lt.indent||Lt.indent(r,\"\")==Lt.indent(i,\"\"))&&(h=!0));if(h)return!0;++f});if(l)return;a&&Ut.push({from:n,to:f+1})}t&&s.onHighlightComplete&&s.onHighlightComplete(ln)}function ai(e){if(!Ot.length)return;Ct.set(e,hi(ui))}function fi(){qt=Rt=zt=null,Ut=[],Wt=!1,$t=[]}function li(){en&&In();if(tn&&!s.lineWrapping){var e=ft.offsetWidth,t=qr(Zt,Zt.text.length).left;ft.style.left=t+\"px\",gt.style.minWidth=t+e+\"px\",tn=!1}var n,r;if(Wt){var i=Zn();n=tr(i.x,i.y,i.x,i.yBot)}if(Ut.length||n&&n.scrollTop!=null)r=rr(Ut,!0,n&&n.scrollTop);r||(Wt&&ur(),Vt&&or()),n&&Yn(),Wt&&(Gn(),ti()),Mt&&!Xt&&(qt===!0||qt!==!1&&Wt)&&Kn(Rt),Wt&&s.matchBrackets&&setTimeout(hi(function(){Yt&&(Yt(),Yt=null),rt(_t.from,_t.to)&&ri(!1)}),20);var o=Wt,u=$t;zt&&s.onChange&&ln&&s.onChange(ln,zt),o&&s.onCursorActivity&&s.onCursorActivity(ln);for(var a=0;a<u.length;++a)u[a](ln);r&&s.onUpdate&&s.onUpdate(ln)}function hi(e){return function(){ci++||fi();try{var t=e.apply(this,arguments)}finally{--ci||li()}return t}}function pi(e){on.startCompound();try{return e()}finally{on.endCompound()}}var s={},w=e.defaults;for(var N in w)w.hasOwnProperty(N)&&(s[N]=(i&&i.hasOwnProperty(N)?i:w)[N]);var L=ot(\"textarea\",null,null,\"position: absolute; padding: 0; width: 1px; height: 1em\");L.setAttribute(\"wrap\",\"off\"),L.setAttribute(\"autocorrect\",\"off\"),L.setAttribute(\"autocapitalize\",\"off\");var O=ot(\"div\",[L],null,\"overflow: hidden; position: relative; width: 3px; height: 0px;\"),F=ot(\"div\",null,\"CodeMirror-scrollbar-inner\"),R=ot(\"div\",[F],\"CodeMirror-scrollbar\"),Q=ot(\"div\"),Y=ot(\"div\",null,null,\"position: relative; z-index: -1\"),Z=ot(\"pre\",\"\\u00a0\",\"CodeMirror-cursor\"),ft=ot(\"pre\",\"\\u00a0\",\"CodeMirror-cursor\",\"visibility: hidden\"),mt=ot(\"div\",null,null,\"position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden;\"),gt=ot(\"div\",[mt,Z,ft,Y,Q],null,\"position: relative; z-index: 0\"),yt=ot(\"div\",null,\"CodeMirror-gutter-text\"),bt=ot(\"div\",[yt],\"CodeMirror-gutter\"),wt=ot(\"div\",[bt,ot(\"div\",[gt],\"CodeMirror-lines\")],null,\"position: relative\"),Et=ot(\"div\",[wt],null,\"position: relative\"),St=ot(\"div\",[Et],\"CodeMirror-scroll\");St.setAttribute(\"tabIndex\",\"-1\");var xt=ot(\"div\",[O,R,St],\"CodeMirror\"+(s.lineWrapping?\" CodeMirror-wrap\":\"\"));r.appendChild?r.appendChild(xt):r(xt),kr(),Lr(),t&&(L.style.width=\"0px\"),g||(St.draggable=!0),gt.style.outline=\"none\",s.tabindex!=null&&(L.tabIndex=s.tabindex),s.autofocus&&Qn(),!s.gutter&&!s.lineNumbers&&(bt.style.display=\"none\"),E&&(O.style.height=\"1px\",O.style.position=\"absolute\"),S?R.className+=Fn()?\" cm-sb-overlap\":\" cm-sb-nonoverlap\":d&&(R.className+=\" cm-sb-ie7\");try{Qr()}catch(Tt){throw Tt.message.match(/runtime/i)&&(Tt=new Error(\"A CodeMirror inside a P-style element does not work in Internet Explorer. (innerHTML bug)\")),Tt}var Nt=new $,Ct=new $,kt,Lt,At=new _([new M([new A(\"\")])]),Ot,Mt;xr();var _t={from:{line:0,ch:0},to:{line:0,ch:0},inverted:!1},Dt,Pt,Ht,Bt=0,jt,Ft=!1,It=!1,qt,Rt,Ut,zt,Wt,Xt,Vt,$t,Jt=0,Kt=0,Qt=0,Gt=0,Yt,Zt=cn(0),en=!1,tn=!0,nn={},rn=!1,sn=null;hi(function(){pn(s.value||\"\"),qt=!1})();var on=new j;V(St,\"mousedown\",hi(gn)),V(St,\"dblclick\",hi(yn)),V(gt,\"selectstart\",q),h||V(St,\"contextmenu\",ei),V(St,\"scroll\",mn),V(R,\"scroll\",vn),V(R,\"mousedown\",function(){Mt&&setTimeout(Qn,0)}),V(window,\"resize\",function(){rr(!0)}),V(L,\"keyup\",hi(Ln)),V(L,\"input\",Vn),V(L,\"keydown\",hi(Cn)),V(L,\"keypress\",hi(kn)),V(L,\"focus\",An),V(L,\"blur\",On),s.dragDrop&&(V(St,\"dragstart\",wn),V(St,\"dragenter\",un),V(St,\"dragover\",un),V(St,\"drop\",hi(bn))),V(St,\"paste\",function(){Qn(),Vn()}),V(L,\"paste\",Vn),V(L,\"cut\",hi(function(){s.readOnly||Rn(\"\")})),E&&V(Et,\"mouseup\",function(){document.activeElement==L&&L.blur(),Qn()});var an;try{an=document.activeElement==L}catch(Tt){}an||s.autofocus?setTimeout(An,20):On();var ln=xt.CodeMirror={getValue:dn,setValue:hi(pn),getSelection:Wn,replaceSelection:hi(Rn),focus:function(){window.focus(),Qn(),An(),Vn()},setOption:function(e,t){var n=s[e];s[e]=t,e==\"mode\"||e==\"indentUnit\"?xr():e==\"readOnly\"&&t==\"nocursor\"?(On(),L.blur()):e==\"readOnly\"&&!t?Kn(!0):e==\"theme\"?kr():e==\"lineWrapping\"&&n!=t?hi(Nr)():e==\"tabSize\"?rr(!0):e==\"keyMap\"&&Lr();if(e==\"lineNumbers\"||e==\"gutter\"||e==\"firstLineNumber\"||e==\"theme\"||e==\"lineNumberFormatter\")Tr(),rr(!0)},getOption:function(e){return s[e]},undo:hi(Dn),redo:hi(Pn),indentLine:hi(function(e,t){typeof t!=\"string\"&&(t==null?t=s.smartIndent?\"smart\":\"prev\":t=t?\"add\":\"subtract\"),fn(e)&&Sr(e,t)}),indentSelection:hi(Er),historySize:function(){return{undo:on.done.length,redo:on.undone.length}},clearHistory:function(){on=new j},setHistory:function(e){on=new j,on.done=e.done,on.undone=e.undone},getHistory:function(){return on.time=0,{done:on.done.concat([]),undone:on.undone.concat([])}},matchBrackets:hi(function(){ri(!0)}),getTokenAt:hi(function(e){return e=dr(e),cn(e.line).getTokenAt(Lt,si(e.line),e.ch)}),getStateAfter:function(e){return e=pr(e==null?At.size-1:e),si(e+1)},cursorCoords:function(e,t){return e==null&&(e=_t.inverted),this.charCoords(e?_t.from:_t.to,t)},charCoords:function(e,t){return e=dr(e),t==\"local\"?Rr(e,!1):t==\"div\"?Rr(e,!0):zr(e)},coordsChar:function(e){var t=et(gt);return Ur(e.x-t.left,e.y-t.top)},markText:hi(Or),setBookmark:Mr,findMarksAt:_r,setMarker:hi(Dr),clearMarker:hi(Pr),setLineClass:hi(Br),hideLine:hi(function(e){return jr(e,!0)}),showLine:hi(function(e){return jr(e,!1)}),onDeleteLine:function(e,t){if(typeof e==\"number\"){if(!fn(e))return null;e=cn(e)}return(e.handlers||(e.handlers=[])).push(t),e},lineInfo:Fr,addWidget:function(e,t,n,r,i){e=Rr(dr(e));var s=e.yBot,o=e.x;t.style.position=\"absolute\",Et.appendChild(t);if(r==\"over\")s=e.y;else if(r==\"near\"){var u=Math.max(St.offsetHeight,At.height*$r()),a=Math.max(Et.clientWidth,gt.clientWidth)-Yr();e.yBot+t.offsetHeight>u&&e.y>t.offsetHeight&&(s=e.y-t.offsetHeight),o+t.offsetWidth>a&&(o=a-t.offsetWidth)}t.style.top=s+Gr()+\"px\",t.style.left=t.style.right=\"\",i==\"right\"?(o=Et.clientWidth-t.offsetWidth,t.style.right=\"0px\"):(i==\"left\"?o=0:i==\"middle\"&&(o=(Et.clientWidth-t.offsetWidth)/2),t.style.left=o+Yr()+\"px\"),n&&er(o,s,o+t.offsetWidth,s+t.offsetHeight)},lineCount:function(){return At.size},clipPos:dr,getCursor:function(e){return e==null&&(e=_t.inverted),st(e?_t.from:_t.to)},somethingSelected:function(){return!rt(_t.from,_t.to)},setCursor:hi(function(e,t,n){t==null&&typeof e.line==\"number\"?hr(e.line,e.ch,n):hr(e,t,n)}),setSelection:hi(function(e,t,n){(n?fr:lr)(dr(e),dr(t||e))}),getLine:function(e){if(fn(e))return cn(e).text},getLineHandle:function(e){if(fn(e))return cn(e)},setLine:hi(function(e,t){fn(e)&&qn(t,{line:e,ch:0},{line:e,ch:cn(e).text.length})}),removeLine:hi(function(e){fn(e)&&qn(\"\",{line:e,ch:0},dr({line:e+1,ch:0}))}),replaceRange:hi(qn),getRange:function(e,t,n){return zn(dr(e),dr(t),n)},triggerOnKeyDown:hi(Cn),execCommand:function(e){return u[e](ln)},moveH:hi(mr),deleteH:hi(gr),moveV:hi(yr),toggleOverwrite:function(){Ft?(Ft=!1,Z.className=Z.className.replace(\" CodeMirror-overwrite\",\"\")):(Ft=!0,Z.className+=\" CodeMirror-overwrite\")},posFromIndex:function(e){var t=0,n;return At.iter(0,At.size,function(r){var i=r.text.length+1;if(i>e)return n=e,!0;e-=i,++t}),dr({line:t,ch:n})},indexFromPos:function(e){if(e.line<0||e.ch<0)return 0;var t=e.ch;return At.iter(0,e.line,function(e){t+=e.text.length+1}),t},scrollTo:function(e,t){e!=null&&(St.scrollLeft=e),t!=null&&(R.scrollTop=St.scrollTop=t),rr([])},getScrollInfo:function(){return{x:St.scrollLeft,y:R.scrollTop,height:R.scrollHeight,width:St.scrollWidth}},setSize:function(e,t){function n(e){return e=String(e),/^\\d+$/.test(e)?e+\"px\":e}e!=null&&(xt.style.width=n(e)),t!=null&&(St.style.height=n(t)),ln.refresh()},operation:function(e){return hi(e)()},compoundChange:function(e){return pi(e)},refresh:function(){rr(!0,null,Bt),R.scrollHeight>Bt&&(R.scrollTop=Bt)},getInputField:function(){return L},getWrapperElement:function(){return xt},getScrollerElement:function(){return St},getGutterElement:function(){return bt}},Sn,Nn=null,$n=\"\";Ar.prototype.clear=hi(function(){var e=Infinity,t=-Infinity;for(var n=0,r=this.set.length;n<r;++n){var i=this.set[n],s=i.marked;if(!s||!i.parent)continue;var o=P(i);e=Math.min(e,o),t=Math.max(t,o);for(var u=0;u<s.length;++u)s[u].marker==this&&s.splice(u--,1)}e!=Infinity&&Ut.push({from:e,to:t+1})}),Ar.prototype.find=function(){var e,t;for(var n=0,r=this.set.length;n<r;++n){var i=this.set[n],s=i.marked;for(var o=0;o<s.length;++o){var u=s[o];if(u.marker==this)if(u.from!=null||u.to!=null){var a=P(i);a!=null&&(u.from!=null&&(e={line:a,ch:u.from}),u.to!=null&&(t={line:a,ch:u.to}))}}}return{from:e,to:t}};var Wr,Xr,Vr,Jr,Kr=0,ni={\"(\":\")>\",\")\":\"(<\",\"[\":\"]>\",\"]\":\"[<\",\"{\":\"}>\",\"}\":\"{<\"},ci=0;for(var di in o)o.propertyIsEnumerable(di)&&!ln.propertyIsEnumerable(di)&&(ln[di]=o[di]);return ln}function f(e){return typeof e==\"string\"?a[e]:e}function l(e,t,n,r,i){function s(t){t=f(t);var n=t[e];if(n===!1)return i&&i(),!0;if(n!=null&&r(n))return!0;if(t.nofallthrough)return i&&i(),!0;var o=t.fallthrough;if(o==null)return!1;if(Object.prototype.toString.call(o)!=\"[object Array]\")return s(o);for(var u=0,a=o.length;u<a;++u)if(s(o[u]))return!0;return!1}return t&&s(t)?!0:s(n)}function c(e){var t=vt[X(e,\"keyCode\")];return t==\"Ctrl\"||t==\"Alt\"||t==\"Shift\"||t==\"Mod\"}function x(e,t){if(t===!0)return t;if(e.copyState)return e.copyState(t);var n={};for(var r in t){var i=t[r];i instanceof Array&&(i=i.concat([])),n[r]=i}return n}function T(e,t,n){return e.startState?e.startState(t,n):!0}function N(e,t){this.pos=this.start=0,this.string=e,this.tabSize=t||8}function C(e,t,n,r){this.from=e,this.to=t,this.style=n,this.marker=r}function k(e){this.from=e,this.to=e,this.line=null}function A(e,t){this.styles=t||[e,null],this.text=e,this.height=1}function O(e,t,n,r){for(var i=0,s=0,o=0;s<t;i+=2){var u=n[i],a=s+u.length;o==0?(a>e&&r.push(u.slice(e-s,Math.min(u.length,t-s)),n[i+1]),a>=e&&(o=1)):o==1&&(a>t?r.push(u.slice(0,t-s),n[i+1]):r.push(u,n[i+1])),s=a}}function M(e){this.lines=e,this.parent=null;for(var t=0,n=e.length,r=0;t<n;++t)e[t].parent=this,r+=e[t].height;this.height=r}function _(e){this.children=e;var t=0,n=0;for(var r=0,i=e.length;r<i;++r){var s=e[r];t+=s.chunkSize(),n+=s.height,s.parent=this}this.size=t,this.height=n,this.parent=null}function D(e,t){while(!e.lines)for(var n=0;;++n){var r=e.children[n],i=r.chunkSize();if(t<i){e=r;break}t-=i}return e.lines[t]}function P(e){if(e.parent==null)return null;var t=e.parent,n=ct(t.lines,e);for(var r=t.parent;r;t=r,r=r.parent)for(var i=0,s=r.children.length;;++i){if(r.children[i]==t)break;n+=r.children[i].chunkSize()}return n}function H(e,t){var n=0;e:do{for(var r=0,i=e.children.length;r<i;++r){var s=e.children[r],o=s.height;if(t<o){e=s;continue e}t-=o,n+=s.chunkSize()}return n}while(!e.lines);for(var r=0,i=e.lines.length;r<i;++r){var u=e.lines[r],a=u.height;if(t<a)break;t-=a}return n+r}function B(e,t){var n=0;e:do{for(var r=0,i=e.children.length;r<i;++r){var s=e.children[r],o=s.chunkSize();if(t<o){e=s;continue e}t-=o,n+=s.height}return n}while(!e.lines);for(var r=0;r<t;++r)n+=e.lines[r].height;return n}function j(){this.time=0,this.done=[],this.undone=[],this.compound=0,this.closed=!1}function F(){U(this)}function I(e){return e.stop||(e.stop=F),e}function q(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function R(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function U(e){q(e),R(e)}function z(e){return e.target||e.srcElement}function W(e){var t=e.which;return t==null&&(e.button&1?t=1:e.button&2?t=3:e.button&4&&(t=2)),n&&e.ctrlKey&&t==1&&(t=3),t}function X(e,t){var n=e.override&&e.override.hasOwnProperty(t);return n?e.override[t]:e[t]}function V(e,t,n,r){if(typeof e.addEventListener==\"function\"){e.addEventListener(t,n,!1);if(r)return function(){e.removeEventListener(t,n,!1)}}else{var i=function(e){n(e||window.event)};e.attachEvent(\"on\"+t,i);if(r)return function(){e.detachEvent(\"on\"+t,i)}}}function $(){this.id=null}function Y(e,t,n){t==null&&(t=e.search(/[^\\s\\u00a0]/),t==-1&&(t=e.length));for(var r=0,i=0;r<t;++r)e.charAt(r)==\"\t\"?i+=n-i%n:++i;return i}function Z(e){return e.currentStyle?e.currentStyle:window.getComputedStyle(e,null)}function et(e,t){try{var n=e.getBoundingClientRect();n={top:n.top,left:n.left}}catch(r){n={top:0,left:0}}if(!t)if(window.pageYOffset==null){var i=document.documentElement||document.body.parentNode;i.scrollTop==null&&(i=document.body),n.top+=i.scrollTop,n.left+=i.scrollLeft}else n.top+=window.pageYOffset,n.left+=window.pageXOffset;return n}function tt(e){return e.textContent||e.innerText||e.nodeValue||\"\"}function nt(e){t?(e.selectionStart=0,e.selectionEnd=e.value.length):e.select()}function rt(e,t){return e.line==t.line&&e.ch==t.ch}function it(e,t){return e.line<t.line||e.line==t.line&&e.ch<t.ch}function st(e){return{line:e.line,ch:e.ch}}function ot(e,t,n,r){var i=document.createElement(e);n&&(i.className=n),r&&(i.style.cssText=r);if(typeof t==\"string\")ft(i,t);else if(t)for(var s=0;s<t.length;++s)i.appendChild(t[s]);return i}function ut(e){return e.innerHTML=\"\",e}function at(e,t){ut(e).appendChild(t)}function ft(e,t){v?(e.innerHTML=\"\",e.appendChild(document.createTextNode(t))):e.textContent=t}function lt(e,t){if(!t)return 0;if(!e)return t.length;for(var n=e.length,r=t.length;n>=0&&r>=0;--n,--r)if(e.charAt(n)!=t.charAt(r))break;return r+1}function ct(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0,r=e.length;n<r;++n)if(e[n]==t)return n;return-1}function ht(e){return/\\w/.test(e)||e.toUpperCase()!=e.toLowerCase()}e.defaults={value:\"\",mode:null,theme:\"default\",indentUnit:2,indentWithTabs:!1,smartIndent:!0,tabSize:4,keyMap:\"default\",extraKeys:null,electricChars:!0,autoClearEmptyLines:!1,onKeyEvent:null,onDragEvent:null,lineWrapping:!1,lineNumbers:!1,gutter:!1,fixedGutter:!1,firstLineNumber:1,readOnly:!1,dragDrop:!0,onChange:null,onCursorActivity:null,onGutterClick:null,onHighlightComplete:null,onUpdate:null,onFocus:null,onBlur:null,onScroll:null,matchBrackets:!1,workTime:100,workDelay:200,pollInterval:100,undoDepth:40,tabindex:null,autofocus:null,lineNumberFormatter:function(e){return e}};var t=/AppleWebKit/.test(navigator.userAgent)&&/Mobile\\/\\w+/.test(navigator.userAgent),n=t||/Mac/.test(navigator.platform),r=/Win/.test(navigator.platform),i=e.modes={},s=e.mimeModes={};e.defineMode=function(t,n){!e.defaults.mode&&t!=\"null\"&&(e.defaults.mode=t);if(arguments.length>2){n.dependencies=[];for(var r=2;r<arguments.length;++r)n.dependencies.push(arguments[r])}i[t]=n},e.defineMIME=function(e,t){s[e]=t},e.resolveMode=function(t){if(typeof t==\"string\"&&s.hasOwnProperty(t))t=s[t];else if(typeof t==\"string\"&&/^[\\w\\-]+\\/[\\w\\-]+\\+xml$/.test(t))return e.resolveMode(\"application/xml\");return typeof t==\"string\"?{name:t}:t||{name:\"null\"}},e.getMode=function(t,n){var n=e.resolveMode(n),r=i[n.name];return r?r(t,n):e.getMode(t,\"text/plain\")},e.listModes=function(){var e=[];for(var t in i)i.propertyIsEnumerable(t)&&e.push(t);return e},e.listMIMEs=function(){var e=[];for(var t in s)s.propertyIsEnumerable(t)&&e.push({mime:t,mode:s[t]});return e};var o=e.extensions={};e.defineExtension=function(e,t){o[e]=t};var u=e.commands={selectAll:function(e){e.setSelection({line:0,ch:0},{line:e.lineCount()-1})},killLine:function(e){var t=e.getCursor(!0),n=e.getCursor(!1),r=!rt(t,n);!r&&e.getLine(t.line).length==t.ch?e.replaceRange(\"\",t,{line:t.line+1,ch:0}):e.replaceRange(\"\",t,r?n:{line:t.line})},deleteLine:function(e){var t=e.getCursor().line;e.replaceRange(\"\",{line:t,ch:0},{line:t})},undo:function(e){e.undo()},redo:function(e){e.redo()},goDocStart:function(e){e.setCursor(0,0,!0)},goDocEnd:function(e){e.setSelection({line:e.lineCount()-1},null,!0)},goLineStart:function(e){e.setCursor(e.getCursor().line,0,!0)},goLineStartSmart:function(e){var t=e.getCursor(),n=e.getLine(t.line),r=Math.max(0,n.search(/\\S/));e.setCursor(t.line,t.ch<=r&&t.ch?0:r,!0)},goLineEnd:function(e){e.setSelection({line:e.getCursor().line},null,!0)},goLineUp:function(e){e.moveV(-1,\"line\")},goLineDown:function(e){e.moveV(1,\"line\")},goPageUp:function(e){e.moveV(-1,\"page\")},goPageDown:function(e){e.moveV(1,\"page\")},goCharLeft:function(e){e.moveH(-1,\"char\")},goCharRight:function(e){e.moveH(1,\"char\")},goColumnLeft:function(e){e.moveH(-1,\"column\")},goColumnRight:function(e){e.moveH(1,\"column\")},goWordLeft:function(e){e.moveH(-1,\"word\")},goWordRight:function(e){e.moveH(1,\"word\")},delCharLeft:function(e){e.deleteH(-1,\"char\")},delCharRight:function(e){e.deleteH(1,\"char\")},delWordLeft:function(e){e.deleteH(-1,\"word\")},delWordRight:function(e){e.deleteH(1,\"word\")},indentAuto:function(e){e.indentSelection(\"smart\")},indentMore:function(e){e.indentSelection(\"add\")},indentLess:function(e){e.indentSelection(\"subtract\")},insertTab:function(e){e.replaceSelection(\"\t\",\"end\")},defaultTab:function(e){e.somethingSelected()?e.indentSelection(\"add\"):e.replaceSelection(\"\t\",\"end\")},transposeChars:function(e){var t=e.getCursor(),n=e.getLine(t.line);t.ch>0&&t.ch<n.length-1&&e.replaceRange(n.charAt(t.ch)+n.charAt(t.ch-1),{line:t.line,ch:t.ch-1},{line:t.line,ch:t.ch+1})},newlineAndIndent:function(e){e.replaceSelection(\"\\n\",\"end\"),e.indentLine(e.getCursor().line)},toggleOverwrite:function(e){e.toggleOverwrite()}},a=e.keyMap={};a.basic={Left:\"goCharLeft\",Right:\"goCharRight\",Up:\"goLineUp\",Down:\"goLineDown\",End:\"goLineEnd\",Home:\"goLineStartSmart\",PageUp:\"goPageUp\",PageDown:\"goPageDown\",Delete:\"delCharRight\",Backspace:\"delCharLeft\",Tab:\"defaultTab\",\"Shift-Tab\":\"indentAuto\",Enter:\"newlineAndIndent\",Insert:\"toggleOverwrite\"},a.pcDefault={\"Ctrl-A\":\"selectAll\",\"Ctrl-D\":\"deleteLine\",\"Ctrl-Z\":\"undo\",\"Shift-Ctrl-Z\":\"redo\",\"Ctrl-Y\":\"redo\",\"Ctrl-Home\":\"goDocStart\",\"Alt-Up\":\"goDocStart\",\"Ctrl-End\":\"goDocEnd\",\"Ctrl-Down\":\"goDocEnd\",\"Ctrl-Left\":\"goWordLeft\",\"Ctrl-Right\":\"goWordRight\",\"Alt-Left\":\"goLineStart\",\"Alt-Right\":\"goLineEnd\",\"Ctrl-Backspace\":\"delWordLeft\",\"Ctrl-Delete\":\"delWordRight\",\"Ctrl-S\":\"save\",\"Ctrl-F\":\"find\",\"Ctrl-G\":\"findNext\",\"Shift-Ctrl-G\":\"findPrev\",\"Shift-Ctrl-F\":\"replace\",\"Shift-Ctrl-R\":\"replaceAll\",\"Ctrl-[\":\"indentLess\",\"Ctrl-]\":\"indentMore\",fallthrough:\"basic\"},a.macDefault={\"Cmd-A\":\"selectAll\",\"Cmd-D\":\"deleteLine\",\"Cmd-Z\":\"undo\",\"Shift-Cmd-Z\":\"redo\",\"Cmd-Y\":\"redo\",\"Cmd-Up\":\"goDocStart\",\"Cmd-End\":\"goDocEnd\",\"Cmd-Down\":\"goDocEnd\",\"Alt-Left\":\"goWordLeft\",\"Alt-Right\":\"goWordRight\",\"Cmd-Left\":\"goLineStart\",\"Cmd-Right\":\"goLineEnd\",\"Alt-Backspace\":\"delWordLeft\",\"Ctrl-Alt-Backspace\":\"delWordRight\",\"Alt-Delete\":\"delWordRight\",\"Cmd-S\":\"save\",\"Cmd-F\":\"find\",\"Cmd-G\":\"findNext\",\"Shift-Cmd-G\":\"findPrev\",\"Cmd-Alt-F\":\"replace\",\"Shift-Cmd-Alt-F\":\"replaceAll\",\"Cmd-[\":\"indentLess\",\"Cmd-]\":\"indentMore\",fallthrough:[\"basic\",\"emacsy\"]},a[\"default\"]=n?a.macDefault:a.pcDefault,a.emacsy={\"Ctrl-F\":\"goCharRight\",\"Ctrl-B\":\"goCharLeft\",\"Ctrl-P\":\"goLineUp\",\"Ctrl-N\":\"goLineDown\",\"Alt-F\":\"goWordRight\",\"Alt-B\":\"goWordLeft\",\"Ctrl-A\":\"goLineStart\",\"Ctrl-E\":\"goLineEnd\",\"Ctrl-V\":\"goPageUp\",\"Shift-Ctrl-V\":\"goPageDown\",\"Ctrl-D\":\"delCharRight\",\"Ctrl-H\":\"delCharLeft\",\"Alt-D\":\"delWordRight\",\"Alt-Backspace\":\"delWordLeft\",\"Ctrl-K\":\"killLine\",\"Ctrl-T\":\"transposeChars\"},e.fromTextArea=function(t,n){function r(){t.value=o.getValue()}n||(n={}),n.value=t.value,!n.tabindex&&t.tabindex&&(n.tabindex=t.tabindex),n.autofocus==null&&t.getAttribute(\"autofocus\")!=null&&(n.autofocus=!0);if(t.form){var i=V(t.form,\"submit\",r,!0);if(typeof t.form.submit==\"function\"){var s=t.form.submit;t.form.submit=function u(){r(),t.form.submit=s,t.form.submit(),t.form.submit=u}}}t.style.display=\"none\";var o=e(function(e){t.parentNode.insertBefore(e,t.nextSibling)},n);return o.save=r,o.getTextArea=function(){return t},o.toTextArea=function(){r(),t.parentNode.removeChild(o.getWrapperElement()),t.style.display=\"\",t.form&&(i(),typeof t.form.submit==\"function\"&&(t.form.submit=s))},o};var h=/gecko\\/\\d{7}/i.test(navigator.userAgent),p=/MSIE \\d/.test(navigator.userAgent),d=/MSIE [1-7]\\b/.test(navigator.userAgent),v=/MSIE [1-8]\\b/.test(navigator.userAgent),m=p&&document.documentMode==5,g=/WebKit\\//.test(navigator.userAgent),y=/Chrome\\//.test(navigator.userAgent),b=/Opera\\//.test(navigator.userAgent),w=/Apple Computer/.test(navigator.vendor),E=/KHTML\\//.test(navigator.userAgent),S=/Mac OS X 10\\D([7-9]|\\d\\d)\\D/.test(navigator.userAgent);e.copyState=x,e.startState=T,N.prototype={eol:function(){return this.pos>=this.string.length},sol:function(){return this.pos==0},peek:function(){return this.string.charAt(this.pos)},next:function(){if(this.pos<this.string.length)return this.string.charAt(this.pos++)},eat:function(e){var t=this.string.charAt(this.pos);if(typeof e==\"string\")var n=t==e;else var n=t&&(e.test?e.test(t):e(t));if(n)return++this.pos,t},eatWhile:function(e){var t=this.pos;while(this.eat(e));return this.pos>t},eatSpace:function(){var e=this.pos;while(/[\\s\\u00a0]/.test(this.string.charAt(this.pos)))++this.pos;return this.pos>e},skipToEnd:function(){this.pos=this.string.length},skipTo:function(e){var t=this.string.indexOf(e,this.pos);if(t>-1)return this.pos=t,!0},backUp:function(e){this.pos-=e},column:function(){return Y(this.string,this.start,this.tabSize)},indentation:function(){return Y(this.string,null,this.tabSize)},match:function(e,t,n){if(typeof e!=\"string\"){var i=this.string.slice(this.pos).match(e);return i&&t!==!1&&(this.pos+=i[0].length),i}var r=function(e){return n?e.toLowerCase():e};if(r(this.string).indexOf(r(e),this.pos)==this.pos)return t!==!1&&(this.pos+=e.length),!0},current:function(){return this.string.slice(this.start,this.pos)}},e.StringStream=N,C.prototype={attach:function(e){this.marker.set.push(e)},detach:function(e){var t=ct(this.marker.set,e);t>-1&&this.marker.set.splice(t,1)},split:function(e,t){if(this.to<=e&&this.to!=null)return null;var n=this.from<e||this.from==null?null:this.from-e+t,r=this.to==null?null:this.to-e+t;return new C(n,r,this.style,this.marker)},dup:function(){return new C(null,null,this.style,this.marker)},clipTo:function(e,t,n,r,i){e&&r>this.from&&(r<this.to||this.to==null)?this.from=null:this.from!=null&&this.from>=t&&(this.from=Math.max(r,this.from)+i),n&&(t<this.to||this.to==null)&&(t>this.from||this.from==null)?this.to=null:this.to!=null&&this.to>t&&(this.to=r<this.to?this.to+i:t)},isDead:function(){return this.from!=null&&this.to!=null&&this.from>=this.to},sameSet:function(e){return this.marker==e.marker}},k.prototype={attach:function(e){this.line=e},detach:function(e){this.line==e&&(this.line=null)},split:function(e,t){if(e<this.from)return this.from=this.to=this.from-e+t,this},isDead:function(){return this.from>this.to},clipTo:function(e,t,n,r,i){(e||t<this.from)&&(n||r>this.to)?(this.from=0,this.to=-1):this.from>t&&(this.from=this.to=Math.max(r,this.from)+i)},sameSet:function(e){return!1},find:function(){return!this.line||!this.line.parent?null:{line:P(this.line),ch:this.from}},clear:function(){if(this.line){var e=ct(this.line.marked,this);e!=-1&&this.line.marked.splice(e,1),this.line=null}}};var L=\" \";h||p&&!d?L=\"\\u200b\":b&&(L=\"\"),A.inheritMarks=function(e,t){var n=new A(e),r=t&&t.marked;if(r)for(var i=0;i<r.length;++i)if(r[i].to==null&&r[i].style){var s=n.marked||(n.marked=[]),o=r[i],u=o.dup();s.push(u),u.attach(n)}return n},A.prototype={replace:function(e,t,n){var r=[],i=this.marked,s=t==null?this.text.length:t;O(0,e,this.styles,r),n&&r.push(n,null),O(s,this.text.length,this.styles,r),this.styles=r,this.text=this.text.slice(0,e)+n+this.text.slice(s),this.stateAfter=null;if(i){var o=n.length-(s-e);for(var u=0;u<i.length;++u){var a=i[u];a.clipTo(e==null,e||0,t==null,s,o),a.isDead()&&(a.detach(this),i.splice(u--,1))}}},split:function(e,t){var n=[t,null],r=this.marked;O(e,this.text.length,this.styles,n);var i=new A(t+this.text.slice(e),n);if(r)for(var s=0;s<r.length;++s){var o=r[s],u=o.split(e,t.length);u&&(i.marked||(i.marked=[]),i.marked.push(u),u.attach(i),u==o&&r.splice(s--,1))}return i},append:function(e){var t=this.text.length,n=e.marked,r=this.marked;this.text+=e.text,O(0,e.text.length,e.styles,this.styles);if(r)for(var i=0;i<r.length;++i)r[i].to==null&&(r[i].to=t);if(n&&n.length){r||(this.marked=r=[]);e:for(var i=0;i<n.length;++i){var s=n[i];if(!s.from)for(var o=0;o<r.length;++o){var u=r[o];if(u.to==t&&u.sameSet(s)){u.to=s.to==null?null:s.to+t,u.isDead()&&(u.detach(this),n.splice(i--,1));continue e}}r.push(s),s.attach(this),s.from+=t,s.to!=null&&(s.to+=t)}}},fixMarkEnds:function(e){var t=this.marked,n=e.marked;if(!t)return;e:for(var r=0;r<t.length;++r){var i=t[r],s=i.to==null;if(s&&n)for(var o=0;o<n.length;++o){var u=n[o];if(!u.sameSet(i)||u.from!=null)continue;if(i.from==this.text.length&&u.to==0){n.splice(o,1),t.splice(r--,1);continue e}s=!1;break}s&&(i.to=this.text.length)}},fixMarkStarts:function(){var e=this.marked;if(!e)return;for(var t=0;t<e.length;++t)e[t].from==null&&(e[t].from=0)},addMark:function(e){e.attach(this),this.marked==null&&(this.marked=[]),this.marked.push(e),this.marked.sort(function(e,t){return(e.from||0)-(t.from||0)})},highlight:function(e,t,n){var r=new N(this.text,n),i=this.styles,s=0,o=!1,u=i[0],a;this.text==\"\"&&e.blankLine&&e.blankLine(t);while(!r.eol()){var f=e.token(r,t),l=this.text.slice(r.start,r.pos);r.start=r.pos,s&&i[s-1]==f?i[s-2]+=l:l&&(!o&&(i[s+1]!=f||s&&i[s-2]!=a)&&(o=!0),i[s++]=l,i[s++]=f,a=u,u=i[s]);if(r.pos>5e3){i[s++]=this.text.slice(r.pos),i[s++]=null;break}}return i.length!=s&&(i.length=s,o=!0),s&&i[s-2]!=a&&(o=!0),o||(i.length<5&&this.text.length<10?null:!1)},getTokenAt:function(e,t,n){var r=this.text,i=new N(r);while(i.pos<n&&!i.eol()){i.start=i.pos;var s=e.token(i,t)}return{start:i.start,end:i.pos,string:i.current(),className:s||null,state:t}},indentation:function(e){return Y(this.text,null,e)},getElement:function(e,t,n){function u(t,n,o){if(!n)return;r&&p&&n.charAt(0)==\" \"&&(n=\"\\u00a0\"+n.slice(1)),r=!1;if(!s.test(n)){i+=n.length;var u=document.createTextNode(n)}else{var u=document.createDocumentFragment(),a=0;for(;;){s.lastIndex=a;var f=s.exec(n),l=f?f.index-a:n.length-a;l&&(u.appendChild(document.createTextNode(n.slice(a,a+l))),i+=l);if(!f)break;a+=l+1;if(f[0]==\"\t\"){var c=e(i);u.appendChild(c.element.cloneNode(!0)),i+=c.width}else{var h=ot(\"span\",\"\\u2022\",\"cm-invalidchar\");h.title=\"\\\\u\"+f[0].charCodeAt(0).toString(16),u.appendChild(h),i+=1}}}o?t.appendChild(ot(\"span\",[u],o)):t.appendChild(u)}function m(e){return e?\"cm-\"+e.replace(/ +/g,\" cm-\"):null}var r=!0,i=0,s=/[\\t\\u0000-\\u0019\\u200b\\u2028\\u2029\\uFEFF]/g,o=ot(\"pre\"),a=u;if(t!=null){var f=0,l=o.anchor=ot(\"span\");a=function(e,r,i){var s=r.length;if(t>=f&&t<f+s){t>f&&(u(e,r.slice(0,t-f),i),n&&e.appendChild(ot(\"wbr\"))),e.appendChild(l);var o=t-f;u(l,b?r.slice(o,o+1):r.slice(o),i),b&&u(e,r.slice(o+1),i),t--,f+=s}else f+=s,u(e,r,i),f==t&&f==v?(ft(l,L),e.appendChild(l)):f>t+10&&/\\s/.test(r)&&(a=function(){})}}var c=this.styles,h=this.text,d=this.marked,v=h.length;if(!h&&t==null)a(o,\" \");else if(!d||!d.length)for(var g=0,y=0;y<v;g+=2){var w=c[g],E=c[g+1],S=w.length;y+S>v&&(w=w.slice(0,v-y)),y+=S,a(o,w,m(E))}else{var x=0,g=0,T=\"\",E,N=0,C=d[0].from||0,k=[],A=0,O=function(){var e;while(A<d.length&&((e=d[A]).from==x||e.from==null))e.style!=null&&k.push(e),++A;C=A<d.length?d[A].from:Infinity;for(var t=0;t<k.length;++t){var n=k[t].to;n==null&&(n=Infinity),n==x?k.splice(t--,1):C=Math.min(n,C)}},M=0;while(x<v){C==x&&O();var _=Math.min(v,C);for(;;){if(T){var D=x+T.length,P=E;for(var H=0;H<k.length;++H)P=(P?P+\" \":\"\")+k[H].style;a(o,D>_?T.slice(0,_-x):T,P);if(D>=_){T=T.slice(_-x),x=_;break}x=D}T=c[g++],E=m(c[g++])}}}return o},cleanUp:function(){this.parent=null;if(this.marked)for(var e=0,t=this.marked.length;e<t;++e)this.marked[e].detach(this)}},M.prototype={chunkSize:function(){return this.lines.length},remove:function(e,t,n){for(var r=e,i=e+t;r<i;++r){var s=this.lines[r];this.height-=s.height,s.cleanUp();if(s.handlers)for(var o=0;o<s.handlers.length;++o)n.push(s.handlers[o])}this.lines.splice(e,t)},collapse:function(e){e.splice.apply(e,[e.length,0].concat(this.lines))},insertHeight:function(e,t,n){this.height+=n,this.lines=this.lines.slice(0,e).concat(t).concat(this.lines.slice(e));for(var r=0,i=t.length;r<i;++r)t[r].parent=this},iterN:function(e,t,n){for(var r=e+t;e<r;++e)if(n(this.lines[e]))return!0}},_.prototype={chunkSize:function(){return this.size},remove:function(e,t,n){this.size-=t;for(var r=0;r<this.children.length;++r){var i=this.children[r],s=i.chunkSize();if(e<s){var o=Math.min(t,s-e),u=i.height;i.remove(e,o,n),this.height-=u-i.height,s==o&&(this.children.splice(r--,1),i.parent=null);if((t-=o)==0)break;e=0}else e-=s}if(this.size-t<25){var a=[];this.collapse(a),this.children=[new M(a)],this.children[0].parent=this}},collapse:function(e){for(var t=0,n=this.children.length;t<n;++t)this.children[t].collapse(e)},insert:function(e,t){var n=0;for(var r=0,i=t.length;r<i;++r)n+=t[r].height;this.insertHeight(e,t,n)},insertHeight:function(e,t,n){this.size+=t.length,this.height+=n;for(var r=0,i=this.children.length;r<i;++r){var s=this.children[r],o=s.chunkSize();if(e<=o){s.insertHeight(e,t,n);if(s.lines&&s.lines.length>50){while(s.lines.length>50){var u=s.lines.splice(s.lines.length-25,25),a=new M(u);s.height-=a.height,this.children.splice(r+1,0,a),a.parent=this}this.maybeSpill()}break}e-=o}},maybeSpill:function(){if(this.children.length<=10)return;var e=this;do{var t=e.children.splice(e.children.length-5,5),n=new _(t);if(!e.parent){var r=new _(e.children);r.parent=e,e.children=[r,n],e=r}else{e.size-=n.size,e.height-=n.height;var i=ct(e.parent.children,e);e.parent.children.splice(i+1,0,n)}n.parent=e.parent}while(e.children.length>10);e.parent.maybeSpill()},iter:function(e,t,n){this.iterN(e,t-e,n)},iterN:function(e,t,n){for(var r=0,i=this.children.length;r<i;++r){var s=this.children[r],o=s.chunkSize();if(e<o){var u=Math.min(t,o-e);if(s.iterN(e,u,n))return!0;if((t-=u)==0)break;e=0}else e-=o}}},j.prototype={addChange:function(e,t,n){this.undone.length=0;var r=+(new Date),i=this.done[this.done.length-1],s=i&&i[i.length-1],o=r-this.time;if(this.compound&&i&&!this.closed)i.push({start:e,added:t,old:n});else if(o>400||!s||this.closed||s.start>e+n.length||s.start+s.added<e)this.done.push([{start:e,added:t,old:n}]),this.closed=!1;else{var u=Math.max(0,s.start-e),a=Math.max(0,e+n.length-(s.start+s.added));for(var f=u;f>0;--f)s.old.unshift(n[f-1]);for(var f=a;f>0;--f)s.old.push(n[n.length-f]);u&&(s.start=e),s.added+=t-(n.length-u-a)}this.time=r},startCompound:function(){this.compound++||(this.closed=!0)},endCompound:function(){--this.compound||(this.closed=!0)}},e.e_stop=U,e.e_preventDefault=q,e.e_stopPropagation=R,e.connect=V,$.prototype={set:function(e,t){clearTimeout(this.id),this.id=setTimeout(t,e)}};var J=e.Pass={toString:function(){return\"CodeMirror.Pass\"}},K=function(){if(v)return!1;var e=ot(\"div\");return\"draggable\"in e||\"dragDrop\"in e}(),Q=function(){var e=ot(\"textarea\");return e.value=\"foo\\nbar\",e.value.indexOf(\"\\r\")>-1?\"\\r\\n\":\"\\n\"}(),G=/^$/;h?G=/$'/:w?G=/\\-[^ \\-?]|\\?[^ !'\\\"\\),.\\-\\/:;\\?\\]\\}]/:y&&(G=/\\-[^ \\-\\.?]|\\?[^ \\-\\.?\\]\\}:;!'\\\"\\),\\/]|[\\.!\\\"#&%\\)*+,:;=>\\]|\\}~][\\(\\{\\[<]|\\$'/),e.setTextContent=ft;var pt=\"\\n\\nb\".split(/\\n/).length!=3?function(e){var t=0,n=[],r=e.length;while(t<=r){var i=e.indexOf(\"\\n\",t);i==-1&&(i=e.length);var s=e.slice(t,e.charAt(i-1)==\"\\r\"?i-1:i),o=s.indexOf(\"\\r\");o!=-1?(n.push(s.slice(0,o)),t+=o+1):(n.push(s),t=i+1)}return n}:function(e){return e.split(/\\r\\n?|\\n/)};e.splitLines=pt;var dt=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(t){return!1}}:function(e){try{var t=e.ownerDocument.selection.createRange()}catch(n){}return!t||t.parentElement()!=e?!1:t.compareEndPoints(\"StartToEnd\",t)!=0};e.defineMode(\"null\",function(){return{token:function(e){e.skipToEnd()}}}),e.defineMIME(\"text/plain\",\"null\");var vt={3:\"Enter\",8:\"Backspace\",9:\"Tab\",13:\"Enter\",16:\"Shift\",17:\"Ctrl\",18:\"Alt\",19:\"Pause\",20:\"CapsLock\",27:\"Esc\",32:\"Space\",33:\"PageUp\",34:\"PageDown\",35:\"End\",36:\"Home\",37:\"Left\",38:\"Up\",39:\"Right\",40:\"Down\",44:\"PrintScrn\",45:\"Insert\",46:\"Delete\",59:\";\",91:\"Mod\",92:\"Mod\",93:\"Mod\",109:\"-\",107:\"=\",127:\"Delete\",186:\";\",187:\"=\",188:\",\",189:\"-\",190:\".\",191:\"/\",192:\"`\",219:\"[\",220:\"\\\\\",221:\"]\",222:\"'\",63276:\"PageUp\",63277:\"PageDown\",63275:\"End\",63273:\"Home\",63234:\"Left\",63232:\"Up\",63235:\"Right\",63233:\"Down\",63302:\"Insert\",63272:\"Delete\"};return e.keyNames=vt,function(){for(var e=0;e<10;e++)vt[e+48]=String(e);for(var e=65;e<=90;e++)vt[e]=String.fromCharCode(e);for(var e=1;e<=12;e++)vt[e+111]=vt[e+63235]=\"F\"+e}(),e}();CodeMirror.defineMode(\"properties\",function(){return{token:function(e,t){var n=e.sol()||t.afterSection,r=e.eol();t.afterSection=!1,n&&(t.nextMultiline?(t.inMultiline=!0,t.nextMultiline=!1):t.position=\"def\"),r&&!t.nextMultiline&&(t.inMultiline=!1,t.position=\"def\");if(n)while(e.eatSpace());var i=e.next();return!n||i!==\"#\"&&i!==\"!\"&&i!==\";\"?n&&i===\"[\"?(t.afterSection=!0,e.skipTo(\"]\"),e.eat(\"]\"),\"header\"):i===\"=\"||i===\":\"?(t.position=\"quote\",null):(i===\"\\\\\"&&t.position===\"quote\"&&e.next()!==\"u\"&&(t.nextMultiline=!0),t.position):(t.position=\"comment\",e.skipToEnd(),\"comment\")},startState:function(){return{position:\"def\",nextMultiline:!1,inMultiline:!1,afterSection:!1}}}}),CodeMirror.defineMIME(\"text/x-properties\",\"properties\"),CodeMirror.defineMIME(\"text/x-ini\",\"properties\")"
  },
  {
    "path": "admin/codemirror/properties.js",
    "content": "CodeMirror.defineMode(\"properties\", function() {\n  return {\n    token: function(stream, state) {\n      var sol = stream.sol() || state.afterSection;\n      var eol = stream.eol();\n\n      state.afterSection = false;\n\n      if (sol) {\n        if (state.nextMultiline) {\n          state.inMultiline = true;\n          state.nextMultiline = false;\n        } else {\n          state.position = \"def\";\n        }\n      }\n\n      if (eol && ! state.nextMultiline) {\n        state.inMultiline = false;\n        state.position = \"def\";\n      }\n\n      if (sol) {\n        while(stream.eatSpace());\n      }\n\n      var ch = stream.next();\n\n      if (sol && (ch === \"#\")) {\n        state.position = \"comment\";\n        stream.skipToEnd();\n        return \"comment\";\n      } else if (sol && ch === \"[\") {\n        state.afterSection = true;\n        stream.skipTo(\"]\"); stream.eat(\"]\");\n        return \"header\";\n      } else if (ch === \":\") {\n        state.position = \"quote\";\n        return null;\n      } else if (ch === \"\\\\\" && state.position === \"quote\") {\n        if (stream.next() !== \"u\") {    // u = Unicode sequence \\u1234\n          // Multiline value\n          state.nextMultiline = true;\n        }\n      }\n\n      return state.position;\n    },\n\n    startState: function() {\n      return {\n        position : \"def\",       // Current position, \"def\", \"quote\" or \"comment\"\n        nextMultiline : false,  // Is the next line multiline value\n        inMultiline : false,    // Is the current line a multiline value\n        afterSection : false    // Did we just open a section\n      };\n    }\n\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-properties\", \"properties\");\nCodeMirror.defineMIME(\"text/x-ini\", \"properties\");\n"
  },
  {
    "path": "admin/edit-pattern.php",
    "content": "<?php\n// Edit site config files for Full-Text RSS\n// Author: Keyvan Minoukadeh\n// Copyright (c) 2013 Keyvan Minoukadeh\n// License: AGPLv3\n// Date: 2013-05-09\n// More info: http://fivefilters.org/content-only/\n// Help: http://help.fivefilters.org\n\n/*\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n// Usage\n// -----\n// Access this file in your browser and follow the instructions to update your site config files.\n\nerror_reporting(E_ALL ^ E_NOTICE);\nini_set(\"display_errors\", 1);\n@set_time_limit(120);\n\nif (get_magic_quotes_gpc()) {\n    $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);\n    while (list($key, $val) = each($process)) {\n        foreach ($val as $k => $v) {\n            unset($process[$key][$k]);\n            if (is_array($v)) {\n                $process[$key][stripslashes($k)] = $v;\n                $process[] = &$process[$key][stripslashes($k)];\n            } else {\n                $process[$key][stripslashes($k)] = stripslashes($v);\n            }\n        }\n    }\n    unset($process);\n}\n\nrequire_once '../libraries/content-extractor/SiteConfig.php';\n\n////////////////////////////////\n// Load config file\n////////////////////////////////\n$admin_page = 'edit-pattern';\nrequire_once('../config.php');\nrequire_once('require_login.php');\nrequire_once('template.php');\ntpl_header('Edit site patterns');\n\n$version = file_get_contents('../site_config/standard/version.txt');\n\nfunction filter_only_text($filename) {\n\treturn (strtolower(substr($filename, -4)) == '.txt');\n}\nfunction is_valid_hostname($host) {\n\treturn preg_match('!^[a-z0-9_.-]+$!i', $host);\n}\n\n/////////////////////////////////\n// Process changes\n/////////////////////////////////\nif ($_SERVER['REQUEST_METHOD'] == 'POST') {\n\t// DELETE\n\tif (@$_POST['delete'] != '' && @$_POST['delete_dir'] != '') {\n\t\tif (is_valid_hostname($_POST['delete'])) {\n\t\t\t$delete = $_POST['delete'];\n\t\t\tif ($_POST['delete_dir'] == 'standard') {\n\t\t\t\t$delete = '../site_config/standard/'.$delete;\n\t\t\t} else {\n\t\t\t\t$delete = '../site_config/custom/'.$delete;\n\t\t\t}\n\t\t\tif (@unlink($delete)) {\n\t\t\t\techo 'Deleted <strong>'.$delete.'</strong>';\n\t\t\t} else {\n\t\t\t\techo 'Failed to delete <strong>'.$delete.'</strong>';\n\t\t\t}\n\t\t}\n\t\texit;\n\t}\n\t\n\t// SAVE\n\tif (@$_POST['save'] != '' && isset($_POST['contents'])) {\n\t\tif (is_valid_hostname(trim($_POST['save']))) {\n\t\t\t$save = strtolower(trim($_POST['save']));\n\t\t\tif (@$_POST['save_dir'] == 'standard') {\n\t\t\t\t$savepath = '../site_config/standard/'.$save.'.txt';\n\t\t\t} else {\n\t\t\t\t$savepath = '../site_config/custom/'.$save.'.txt';\n\t\t\t}\n\t\t\t// TODO: check if file exists, if it does, prompt user whether to overwrite\n\t\t\tif (file_put_contents($savepath, $_POST['contents']) !== false) {\n\t\t\t\techo '<p>Saved to <strong>'.$savepath.'</strong></p>';\n\t\t\t\t// check caching\n\t\t\t\tif ($options->caching) {\n\t\t\t\t\techo '<p>Note: caching is enabled &mdash; you may have to disable caching or delete cache files to see changes.<p>';\n\t\t\t\t}\n\t\t\t\tif ($options->apc && function_exists('apc_delete') && function_exists('apc_cache_info')) {\n\t\t\t\t\t$_apc_data = apc_cache_info('user');\n\t\t\t\t\tforeach ($_apc_data['cache_list'] as $_apc_item) {\n\t\t\t\t\t\tif (substr($_apc_item['info'], 0, 3) == 'sc.') {\n\t\t\t\t\t\t\tapc_delete($_apc_item['info']);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\techo '<p>Cleared site config cache in APC.</p>';\n\t\t\t\t}\n\t\t\t\tSiteConfig::set_config_path(dirname($savepath));\n\t\t\t\t$sconfig = SiteConfig::build($save, $exact_host_match=true);\n\t\t\t\tif ($sconfig) {\n\t\t\t\t\tif (!empty($sconfig->test_url)) {\n\t\t\t\t\t\techo '<h4>Test URLs</h4>';\n\t\t\t\t\t\techo '<ul>';\n\t\t\t\t\t\tforeach ($sconfig->test_url as $test_url) {\n\t\t\t\t\t\t\t$ftr_test_url = $test_url;\n\t\t\t\t\t\t\tif (strtolower(substr($ftr_test_url, 0, 7)) == 'http://') {\n\t\t\t\t\t\t\t\t$ftr_test_url = substr($ftr_test_url, 7);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$ftr_test_url = '../makefulltextfeed.php?url='.urlencode($ftr_test_url);\n\t\t\t\t\t\t\techo '<li>';\n\t\t\t\t\t\t\techo '<a href=\"'.htmlspecialchars($test_url).'\" target=\"_blank\">'.htmlspecialchars($test_url).'</a>';\n\t\t\t\t\t\t\techo ' | <a href=\"'.$ftr_test_url.'\" target=\"_blank\">Full-Text RSS result</a>';\n\t\t\t\t\t\t\techo ' | <a href=\"'.$ftr_test_url.'&debug\" target=\"_blank\">Debug</a>';\n\t\t\t\t\t\t\techo '</li>';\n\t\t\t\t\t\t}\n\t\t\t\t\t\techo '</ul>';\n\t\t\t\t\t} else {\n\t\t\t\t\t\techo '<p>No test URLs found in config, if you supply one we\\'ll give you a link to test how Full-Text RSS will extract it</p>';\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\techo '<p>Could not load/parse config file</p>';\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\techo 'Failed to save <strong>'.$savepath.'</strong>. Make sure the directory is writable.';\n\t\t\t}\n\t\t}\n\t\texit;\n\t}\n}\n\n/////////////////////////////////\n// Show list of site config files\n/////////////////////////////////\nif (!isset($_REQUEST['url']) || trim($_REQUEST['url']) == '') {\n\t$sc_files = array_merge(scandir('../site_config/standard/'), scandir('../site_config/custom/'));\n\t$sc_files = array_unique(array_filter($sc_files, 'filter_only_text'));\n\t?>\n\t<p><strong>Note:</strong> This feature is for advanced users familiar with XPath. It allows you to override automatic article extraction and specify what Full-Text RSS should extract from specific domains. If you're uncomfortable writing your own, you can <a href=\"http://fivefilters.org/content-only/custom_site_patterns.php\">request one</a> from us.</p>\n\t<form class=\"well form-search\" action=\"edit-pattern.php\">\n\t<input id=\"search\" type=\"text\" name=\"url\" class=\"span8\" placeholder=\"Enter a host name or URL, e.g. http://www.example.org/article-123.html\">\n\t<button type=\"submit\" class=\"btn\">Search or add</button>\n\t</form>\n\t<?php\n\techo '<ul style=\"-webkit-column-count: 3; -moz-column-count: 3; column-count: 3\" id=\"list\">';\n\tforeach ($sc_files as $file) {\n\t\t$file = basename($file, '.txt');\n\t\techo '<li><a href=\"edit-pattern.php?url='.urlencode($file).'\">'.htmlspecialchars($file).'</a></li>';\n\t}\n\techo '</ul>';\n\t// adapted from http://stackoverflow.com/a/11022738/407938 ...\n\t?>\n\t<script>\n\t$('input#search').bind('keyup',function(){\n\t\tvar inputString = $(this).val();\n\t\tvar items = $('ul#list li');\n\t\titems.hide();\n\t\titems.each(function(){\n\t\t\tvar item = $(this).text().toString();\n\t\t\tif (item.indexOf(inputString)>=0)\n\t\t\t\t$(this).show();\n\t\t});\n\t});\n\t</script>\n\t<?php\n\texit;\n}\n\n//////////////////////////////////\n// Check if primary or secondary \n// folder specified\n//////////////////////////////////\n$lookin = null;\nif (isset($_REQUEST['lookin']) && in_array($_REQUEST['lookin'], array('standard', 'custom'))) {\n\t$lookin = $_REQUEST['lookin'];\n}\n\n//////////////////////////////////\n// Find file and display\n//////////////////////////////////\n$hostname = false;\nif (is_valid_hostname($_REQUEST['url'])) {\n\t$hostname = $_REQUEST['url'];\n} else {\n\tif ($_host = parse_url($_REQUEST['url'], PHP_URL_HOST)) {\n\t\tif (is_valid_hostname($_host)) {\n\t\t\t$hostname = $_host;\n\t\t}\n\t}\n}\nif (!$hostname) die('Invalid URL');\n$hostname_base = ltrim($hostname, '.');\nif (strtolower(substr($hostname, 0, 4)) == 'www.') {\n\t$hostname = substr($hostname, 4);\n\t$hostname_base = $hostname;\n}\n$check = array(\n\t'../site_config/standard/'.$hostname_base.'.txt',\n\t'../site_config/standard/.'.$hostname_base.'.txt',\n\t'../site_config/custom/'.$hostname_base.'.txt',\n\t'../site_config/custom/.'.$hostname_base.'.txt'\n);\n$related = array();\n$matched = array();\n$exact_match = false;\nforeach ($check as $filename) {\n\tif (file_exists($filename)) {\n\t\t$related[$filename] = file_get_contents($filename);\n\t\tif ($lookin === null || strpos($filename, \"/$lookin/\") !== false) {\n\t\t\t$matched[$filename] = file_get_contents($filename);\n\t\t\tif (strpos($filename, \"/$hostname\") !== false) $exact_match = $filename;\n\t\t}\n\t}\n}\n\nif (empty($matched)) {\n\t$contents = \"# No matching files found, you can write yours here\\n\\n# body: //div[@id='body']\\n\\n# test_url: http://...\";\n\techo '<p>No matching files found...</p>';\n} elseif ($exact_match) {\n\t$contents = $matched[$exact_match];\n\t$file_location = $exact_match;\n\techo '<p style=\"position: absolute;\">Loaded <strong>'.htmlspecialchars($exact_match).'</strong></p>';\n} else {\n\t$contents = end($matched);\n\t$file_location = array_pop(array_keys($matched));\n\techo '<p style=\"position: absolute;\">Loaded <strong>'.htmlspecialchars($file_location).'</strong></p>';\n}\n\nif (isset($file_location)) unset($related[$file_location]);\n\n$save_locations = array(\n\t'custom' => 'custom (recommended)',\n\t'standard' => 'standard'\n);\necho '<form method=\"POST\" action=\"edit-pattern.php\">';\necho '<div style=\"text-align: right; margin-top: 10px; margin-bottom: 5px;\"><a href=\"http://help.fivefilters.org/customer/portal/articles/223153-site-patterns\" target=\"_blank\">Need help?</a></div>';\necho '<textarea name=\"contents\" class=\"span8\" style=\"height: 400px;\" id=\"config\">'.htmlspecialchars($contents).'</textarea>';\necho '<div style=\"margin-top: 8px; margin-bottom: 4px;\">';\necho '<label>Save as</label> <input type=\"text\" name=\"save\" value=\"'.htmlspecialchars($hostname).'\" />.txt';\necho '<br />';\necho '<label>In directory</label> ';\necho '<select name=\"save_dir\">';\nforeach ($save_locations as $_sl_val => $_sl_display) {\n\techo \"<option value=\\\"$_sl_val\\\">$_sl_display</option>\";\n}\necho '</select>';\necho '</div>';\necho '<input type=\"submit\" class=\"btn btn-primary\" value=\"Save\" /> ';\necho 'or <a href=\"edit-pattern.php\" class=\"btn\" >Cancel and return to listing</a>';\necho '</form>';\n\n// DELETE option\nif (!empty($matched)) {\n\techo '<hr /><h3>Delete file?</h3>';\n\techo '<p>Delete <strong>'.htmlspecialchars($file_location).'</strong></p>';\n\techo '<form method=\"POST\" action=\"edit-pattern.php\" onsubmit=\"return confirm(\\'Are you sure?\\');\">';\n\techo '<input type=\"hidden\" name=\"delete\" value=\"'.htmlspecialchars(basename($file_location)).'\" />';\n\techo '<input type=\"hidden\" name=\"delete_dir\" value=\"'.(strpos($file_location, '/standard/') ? 'standard' : 'custom').'\" />';\n\techo '<input type=\"submit\" value=\"Delete\" class=\"btn btn-danger\" />';\n\techo '</form>';\n}\n\n// TEST URLs\nif (!empty($matched)) {\n\tif ($sconfig = SiteConfig::build_from_array(explode(\"\\n\", $contents))) {\n\t\tif (!empty($sconfig->test_url)) {\n\t\t\techo '<hr /><h3>Test URLs</h3>';\n\t\t\techo '<ul>';\n\t\t\tforeach ($sconfig->test_url as $test_url) {\n\t\t\t\t$ftr_test_url = $test_url;\n\t\t\t\tif (strtolower(substr($ftr_test_url, 0, 7)) == 'http://') {\n\t\t\t\t\t$ftr_test_url = substr($ftr_test_url, 7);\n\t\t\t\t}\n\t\t\t\t$ftr_test_url = '../makefulltextfeed.php?url='.urlencode($ftr_test_url);\n\t\t\t\techo '<li>';\n\t\t\t\techo '<a href=\"'.htmlspecialchars($test_url).'\" target=\"_blank\">'.htmlspecialchars($test_url).'</a>';\n\t\t\t\techo ' | <a href=\"'.$ftr_test_url.'\" target=\"_blank\">Full-Text RSS result</a>';\n\t\t\t\techo ' | <a href=\"'.$ftr_test_url.'&debug\" target=\"_blank\">Debug</a>';\n\t\t\t\techo '</li>';\n\t\t\t}\n\t\t\techo '</ul>';\n\t\t}\n\t}\n}\n\n// RELATED files\nif (!empty($related)) {\n\techo '<hr /><h3>Related files</h3>';\n\techo '<ul>';\n\tforeach (array_keys($related) as $_m_file) {\n\t\tpreg_match('!/(standard|custom)/(.+?)\\.txt$!', $_m_file, $_m);\n\t\techo '<li><a href=\"edit-pattern.php?lookin='.$_m[1].'&url='.urlencode($_m[2]).'\">'.htmlspecialchars($_m_file).'</a></li>';\n\t}\n\techo '</ul>';\n}\n?>\n<script>\nvar editor = CodeMirror.fromTextArea(document.getElementById(\"config\"), {\n\tlineNumbers: true,\n\ttheme: 'default',\n\tlineWrapping: true\n});\n</script>"
  },
  {
    "path": "admin/index.php",
    "content": "<?php\n// Admin page for Full-Text RSS\n// Author: Keyvan Minoukadeh\n// Copyright (c) 2012 Keyvan Minoukadeh\n// License: AGPLv3\n// Date: 2012-04-29\n// More info: http://fivefilters.org/content-only/\n// Help: http://help.fivefilters.org\n\n/*\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n// Usage\n// -----\n// Access this file in your browser\n\nerror_reporting(E_ALL ^ E_NOTICE);\nini_set(\"display_errors\", 1);\n@set_time_limit(120);\n\n////////////////////////////////\n// Load config file\n////////////////////////////////\nrequire_once('../config.php');\nrequire_once('require_login.php');\nrequire_once('template.php');\ntpl_header('Admin');\n\n?>\n<p>The admin pages are intended to help you manage your copy of Full-Text RSS more easily.</p>\n<ul>\n<li><a href=\"update.php\">Update patterns</a>: an easy way to keep site config files up to date.</li>\n<li><a href=\"edit-pattern.php\">Edit patterns</a>: need to fine-tune extraction for a certain site? Use this tool.</li>\n<li><a href=\"apc.php?OB=3\">APC</a>: If APC is enabled, you can use this tool to see what Full-Text RSS caches, and clear the cache if you need to.</li>\n</ul>"
  },
  {
    "path": "admin/login.php",
    "content": "<?php\nheader(\"X-Robots-Tag: noindex, nofollow\", true);\nsession_start();\nrequire_once(dirname(dirname(__FILE__)).'/config.php');\nif (!isset($options->admin_credentials) || $options->admin_credentials['username'] == '' || $options->admin_credentials['password'] == '') {\n\tdie('<h2>Admin privileges required</h2><p>This page requires admin privileges but Full-Text RSS has not been configured with admin credentials.</p><p>If you are the administrator, please edit your <tt>custom_config.php</tt> file and enter the credentials in the appropriate section. When you\\'ve done that, this page will prompt you for your admin credentials.</p>');\n}\n\n$name = @$_POST['username'];\n$pass = @$_POST['pass'];\n$invalid_login = false;\n\nif ($name || $pass) {\n\tif ($name == $options->admin_credentials['username'] && $pass == $options->admin_credentials['password']) {\n\t\t// Authentication successful - set session\n\t\t$_SESSION['auth'] = 1;\n\t\tif (isset($_POST['redirect']) && preg_match('/^[0-9a-z]+$/', $_POST['redirect'])) {\n\t\t\theader('Location: '.$_POST['redirect'].'.php');\n\t\t} else {\n\t\t\theader('Location: index.php');\n\t\t}\n\t\texit;\n\t}\n\t$invalid_login = true;\n}\n?>\n<!DOCTYPE html>\n<html>\n<head><title>Login</title></head>\n<body>\n<?php if ($invalid_login) echo '<p><strong>Invalid login, please try again.</strong> If you can\\'t remember your admin credentials, open your <tt>custom_config.php</tt> and you\\'ll find them in there.</p>'; ?>\n<form method=\"post\" action=\"login.php\">\n<?php if (isset($_GET['redirect'])) echo '<input type=\"hidden\" name=\"redirect\" value=\"'.htmlspecialchars($_GET['redirect']).'\" />'; ?>\n<label>Username: <input type=\"text\" name=\"username\" value=\"<?php echo @$_POST['username']; ?>\" /></label>\n<label>Password: <input type=\"password\" name=\"pass\" /></label>\n<input type=\"submit\" name=\"submit\" value=\"Log In\" />\n</form>\n</body>\n</html>"
  },
  {
    "path": "admin/require_login.php",
    "content": "<?php\n// Require login for admin access\n// Author: Keyvan Minoukadeh\n// Copyright (c) 2013 Keyvan Minoukadeh\n// License: AGPLv3\n// Date: 2013-05-09\n// More info: http://fivefilters.org/content-only/\n// Help: http://help.fivefilters.org\n\n/*\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n// Usage\n// -----\n// This file is included on pages which require admin privileges - e.g. updating the software.\n// The username is 'admin' by default and the password should be set in the custom_config.php file.\nsession_start();\nrequire_once(dirname(dirname(__FILE__)).'/config.php');\n\nif (isset($_GET['logout'])) $_SESSION['auth'] = 0;\n\nif (!isset($_SESSION['auth']) || $_SESSION['auth'] != 1) {\n\tif (isset($admin_page)) {\n\t\theader('Location: login.php?redirect='.$admin_page);\n\t} else {\n\t\theader('Location: login.php');\n\t}\n\texit;\n}"
  },
  {
    "path": "admin/template.php",
    "content": "<?php\nob_start();\nfunction tpl_header($title='Full-Text RSS Admin Area') {\nglobal $admin_page;\n?>\n<!DOCTYPE html>\n<html>\n  <head>\n    <title><?php echo $title; ?></title>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\t\n\t<meta name=\"robots\" content=\"noindex, nofollow\" />\n\t<link rel=\"stylesheet\" href=\"../css/bootstrap.min.css\" type=\"text/css\" media=\"screen\" />\n\t<script type=\"text/javascript\" src=\"../js/jquery.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"../js/bootstrap-tooltip.js\"></script>\n\t<script type=\"text/javascript\" src=\"../js/bootstrap-popover.js\"></script>\n\t<script type=\"text/javascript\" src=\"../js/bootstrap-tab.js\"></script>\n\t<script type=\"text/javascript\" src=\"codemirror/codemirror.js\"></script>\n\t<script type=\"text/javascript\" src=\"codemirror/properties.js\"></script>\n\t<link rel=\"stylesheet\" href=\"codemirror/codemirror.css\" />\n  <style>\n\thtml, body { background-color: #eee; }\n\tbody { margin: 0; line-height: 1.4em; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; }\n\tlabel, input, select, textarea { font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; }\n\t.actions { padding-left: 220px; }\n\t.popover .inner { width: 200px; }\n\t#main-container { width: 800px; padding-bottom: 60px; }\n\t.page-header { padding-bottom: 0; }\n    .CodeMirror {border: 1px solid black; font-size:13px}\n\t.cm-def {color: green !important;}\n\t.cm-quote {color: #000 !important;}\n\t.CodeMirror-scroll { height: auto; overflow: visible; }\n  </style>\n  </head>\n  <body> \n  <div class=\"container\" id=\"main-container\">\n  <div class=\"navbar\">\n    <div class=\"navbar-inner\">\n      <div class=\"container\">\n\t  <a class=\"brand\" href=\"../\">Full-Text RSS</a>\n\t\t<ul class=\"nav\">\n\t\t  <li <?php if (@$admin_page == 'update') echo 'class=\"active\"'; ?>><a href=\"update.php\">Update patterns</a></li>\n\t\t  <li <?php if (@$admin_page == 'edit-pattern') echo 'class=\"active\"'; ?>><a href=\"edit-pattern.php\">Edit patterns</a></li>\n\t\t  <li <?php if (@$admin_page == 'apc') echo 'class=\"active\"'; ?>><a href=\"apc.php?OB=3\">APC</a></li>\t\t  \n\t\t  <li><a href=\"index.php?logout\">Logout</a></li>\n\t\t</ul>\n      </div>\n    </div>\n   </div>  \n  <div class=\"page-header\"><h1><?php echo $title; ?></h1></div>\n<?php\n}\n\nfunction tpl_footer() {\n?>\n\n  </div> <!-- close container -->\n  </body>\n</html>\n<?php\n}\n\nregister_shutdown_function('tpl_footer');"
  },
  {
    "path": "admin/update.php",
    "content": "<?php\n// Update site config files for Full-Text RSS\n// Author: Keyvan Minoukadeh\n// Copyright (c) 2013 Keyvan Minoukadeh\n// License: AGPLv3\n// Date: 2013-05-12\n// More info: http://fivefilters.org/content-only/\n// Help: http://help.fivefilters.org\n\n/*\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n// Usage\n// -----\n// * Access this file in your browser and follow the instructions to update your site config files.\n// * See section on automatic updates for a URL you can fetch periodically (e.g. with cron) to update site config files\n\nerror_reporting(E_ALL ^ E_NOTICE);\nini_set(\"display_errors\", 1);\n@set_time_limit(120);\n\n////////////////////////////////\n// Load config file\n////////////////////////////////\n$admin_page = 'update';\nrequire_once('../config.php');\nrequire_once 'template.php';\ntpl_header('Update site patterns');\n\n//////////////////////////////////\n// Username and password must be available\n//////////////////////////////////\nif (!isset($options->admin_credentials) || $options->admin_credentials['username'] == '' || $options->admin_credentials['password'] == '') {\n\theader(\"X-Robots-Tag: noindex, nofollow\", true);\n\n\tdie('<h2>Username and password not set</h2><p>Full-Text RSS has not been configured with admin credentials.</p><p>If you are the administrator, please edit your <tt>custom_config.php</tt> file and enter the credentials in the appropriate section. When you\\'ve done that, this page will prompt you for your admin credentials.</p>');\n}\n$admin_hash = sha1($options->admin_credentials['username'].'+'.$options->admin_credentials['password']);\n\n$_self_host = $_SERVER['HTTP_HOST'];\n$_self_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/\\\\');\n$self_update_url = 'http://'.htmlspecialchars($_self_host.$_self_path).'/update.php?key='.urlencode($admin_hash);\n\n$latest_remote = 'https://codeload.github.com/fivefilters/ftr-site-config/zip/master';\n$version = @file_get_contents('../site_config/standard/version.txt');\n\n/////////////////////////////////\n// Check for update key\n/////////////////////////////////\nif (!isset($_REQUEST['key']) || trim($_REQUEST['key']) == '') {\n\n\trequire_once 'require_login.php';\n\n\tif ($_SERVER['REQUEST_METHOD'] == 'POST') {\n\t\theader('Location: update.php');\n\t\texit;\n\t}\t\n\t\n\t$auto = true;\n\t$no_auto_reasons = array();\n\tif (!class_exists('ZipArchive')) {\n\t\t$auto = false;\n\t\t$no_auto_reasons[] = 'zip support (PHP\\'s <a href=\"http://php.net/manual/en/zip.requirements.php\">ZipArchive</a> class) is missing';\n\t}\n\tif (!is_writable('../site_config')) {\n\t\t$auto = false;\n\t\t$no_auto_reasons[] = 'your <tt>site_config/</tt> folder is not writable - change permissions to 777 and try again.</p>';\n\t}\n\tif (!file_exists('../site_config/standard/version.txt')) {\n\t\tdie('Could not determine current version of your site pattern files (site_config/standard/version.txt). Make sure you\\'re using at least version 3.2 of Full-Text RSS.');\n\t}\n\t?>\n\t<p>You have Full-Text RSS <strong><?php echo _FF_FTR_VERSION; ?></strong>\n\t(Site Patterns version: <strong><?php echo (isset($version) ? $version : 'Unknown'); ?></strong>)\n\t</p>\n\t<p>To see if you have the latest versions, <a href=\"http://fivefilters.org/content-only/latest_version.php?version=<?php echo urlencode(_FF_FTR_VERSION).'&site_config='.urlencode(@$version); ?>\">check for updates</a>.</p>\n\t<?php\n\tif ($auto) {\n\t\techo '<p>This update tool will attempt to fetch the latest site patterns from our <a href=\"https://github.com/fivefilters/ftr-site-config/\">GitHub repository</a>.</p>';\n\t\techo '<p><strong>Important: </strong>if you\\'ve modified or added your own config files in the <tt>site_config/standard/</tt> folder, please move them to <tt>site_config/custom/</tt> &mdash; the update process will attempt to replace everything in <tt>site_config/standard/</tt> with our updated version.</p>';\n\t\techo '<form method=\"post\" action=\"update.php\" class=\"well\">';\n\t\techo '<input type=\"hidden\" name=\"key\" value=\"'.$admin_hash.'\" />';\n\t\techo '<input type=\"submit\" value=\"Update site config files\" />';\n\t\techo '</form>';\n\t\techo '<h3>Automatic updates</h3>';\n\t\techo '<p>You can schedule automatic updates using something like cron. The URL to call is:</p>';\n\t\techo '<p class=\"well\">'.$self_update_url.'</p>';\n\t\techo '<p>We recommend you schedule this URL to be fetched once a day. If you do not have access to a scheduling service ';\n\t\techo 'you may want to consider one of these online services: <a href=\"http://www.easycron.com/\">Easycron</a>, <a href=\"https://www.setcronjob.com/\">SetCronJob</a>, <a href=\"http://www.onlinecronjobs.com/\">onlinecronjobs.com</a>.</p>';\n\t\techo '<p>Note: the key contained in the URL is a hash value generated from your admin credentials. If you change these, the key will also change.</p>';\n\t} else {\n\t\techo '<div class=\"notice\">';\n\t\techo '<p>We cannot automatically update your site pattern files because:</p>';\n\t\techo '<ul>';\n\t\tforeach ($no_auto_reasons as $reason) {\n\t\t\techo '<li>',$reason,'</li>';\n\t\t}\n\t\techo '</ul>';\n\t\techo '<p>You can still manually update by downloading the zip file and replacing everything in your <tt>site_config/standard/</tt> folder with the contents of the zip file.</p>';\n\t\techo '</div>';\n\t\techo '<p><a href=\"'.$latest_remote.'\">Download site config files (zip)</a></p>';\n\t}\n\techo '<h3>Help</h3>';\n\techo '<p>If you have any trouble, please contact us via our <a href=\"http://help.fivefilters.org\">support site</a>.</p>';\n\texit;\n}\n\n//////////////////////////////////\n// Check update key valid\n//////////////////////////////////\nif ($_REQUEST['key'] !== $admin_hash) {\n\tprintln(\"Sorry, invalid key supplied.\");\n\texit;\n}\n\n//////////////////////////////////\n// Check for updates\n//////////////////////////////////\n//$ff_version = @file_get_contents('http://fivefilters.org/content-only/site_config/standard/version.txt');\n$_context = stream_context_create(array('http' => array('user_agent' => 'PHP/5.4')));\n$latest_info_json = @file_get_contents('https://api.github.com/repos/fivefilters/ftr-site-config', false, $_context);\nif (!$latest_info_json) {\n\tprintln(\"Sorry, couldn't get info on latest site config files. Please try again later or contact us.\");\n\texit;\n}\n$latest_info_json = @json_decode($latest_info_json);\nif (!is_object($latest_info_json)) {\n\tprintln(\"Sorry, couldn't parse JSON from GitHub. Please try again later or contact us.\");\n\texit;\n}\n$ff_version = $latest_info_json->updated_at;\nif ($version == $ff_version) {\n\tdie('Your site config files are up to date! If you have trouble extracting from a particular site, please email us: help@fivefilters.org');\n} else {\n\tprintln(\"Updated site patterns are available (version $ff_version)...\");\n}\n\n//////////////////////////////////\n// Prepare\n//////////////////////////////////\n$tmp_latest_local = '../site_config/latest_site_config.zip';\n$tmp_latest_local_dir = '../site_config/standard_latest';\n$tmp_old_local_dir = '../site_config/standard_old';\nif (file_exists($tmp_latest_local)) unlink($tmp_latest_local);\nif (file_exists($tmp_latest_local_dir)) {\n\tif (!rrmdir($tmp_latest_local_dir)) {\n\t\tprintln(\"Sorry, couldn't remove old folder from last update\");\n\t\texit;\n\t}\n}\nif (file_exists($tmp_old_local_dir)) {\n\trrmdir($tmp_old_local_dir);\n}\n$standard_local_dir = '../site_config/standard/';\n//@copy($latest_remote, $tmp_latest_local);\n//copy() does not appear to fill $http_response_header in certain environments\n@file_put_contents($tmp_latest_local, @file_get_contents($latest_remote));\n$headers = implode(\"\\n\", $http_response_header);\n//var_dump($headers); exit;\nif (strpos($headers, 'HTTP/1.0 200') === false) {\n\tprintln(\"Sorry, something went wrong. Please contact us if the problem persists.\");\n\texit;\n}\nif (class_exists('ZipArchive') && file_exists($tmp_latest_local)) {\n\tprintln(\"Downloaded latest copy of the site pattern files to $tmp_latest_local\");\n\t$zip = new ZipArchive;\n\tif ($zip->open($tmp_latest_local) === TRUE) {\n\t\t$zip->extractTo($tmp_latest_local_dir);\n\t\t$zip->close();\n\t\t@unlink($tmp_latest_local);\n\t\tif (file_exists($tmp_latest_local_dir)) {\n\t\t\tprintln(\"Unzipped contents to $tmp_latest_local_dir\");\n\t\t\tif (!file_exists($tmp_latest_local_dir.'/ftr-site-config-master/README.md')) {\n\t\t\t\tprintln(\"There was a problem extracting the latest site patterns archive - your current site patterns remain untouched.\");\n\t\t\t\tprintln(\"Please <a href=\\\"$latest_remote\\\">update manually</a>.\");\n\t\t\t\texit;\n\t\t\t}\n\t\t\t@file_put_contents($tmp_latest_local_dir.'/ftr-site-config-master/version.txt', $ff_version);\n\t\t\tif (!file_exists($tmp_latest_local_dir.'/ftr-site-config-master/version.txt')) {\n\t\t\t\tprintln(\"There was a problem writing the new version number - your current site patterns remain untouched.\");\n\t\t\t\tprintln(\"Please <a href=\\\"$latest_remote\\\">update manually</a>.\");\n\t\t\t\texit;\n\t\t\t}\n\t\t\trename($standard_local_dir, $tmp_old_local_dir);\n\t\t\tif (file_exists($tmp_old_local_dir)) println(\"Renamed $standard_local_dir to $tmp_old_local_dir\");\n\t\t\trename($tmp_latest_local_dir.\"/ftr-site-config-master\", $standard_local_dir);\n\t\t\tif (file_exists($standard_local_dir)) println(\"Renamed $tmp_latest_local_dir/ftr-site-config-master to $standard_local_dir\");\n\t\t\trmdir($tmp_latest_local_dir);\n\t\t\t// clear cached site config files from APC\n\t\t\tif ($options->apc && function_exists('apc_delete') && function_exists('apc_cache_info')) {\n\t\t\t\t$_apc_data = apc_cache_info('user');\n\t\t\t\tforeach ($_apc_data['cache_list'] as $_apc_item) {\n\t\t\t\t\tif (substr($_apc_item['info'], 0, 3) == 'sc.') {\n\t\t\t\t\t\tapc_delete($_apc_item['info']);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tprintln('Cleared site config cache in APC.');\n\t\t\t}\n\t\t\t// all done!\n\t\t\tprintln(\"<strong style=\\\"color: darkgreen;\\\">All done!</strong> Your old site config files are in $tmp_old_local_dir &mdash; these will be removed next time you go through the update process.\");\n\t\t} else {\n\t\t\tif (file_exists($tmp_latest_local)) @unlink($tmp_latest_local);\n\t\t\tprintln(\"Failed to unzip to $tmp_latest_local_dir - your current site patterns remain untouched\");\n\t\t}\n\t} else {\n\t\tif (file_exists($tmp_latest_local)) @unlink($tmp_latest_local);\n\t\tprintln(\"Failed to extract from $tmp_latest_local - your current site patterns remain untouched\");\n\t}\n} else {\n\tprintln(\"Could not download the latest site config files. Please <a href=\\\"$latest_remote\\\">update manually</a> - your current site patterns remain untouched.\");\n}\n\nfunction println($txt) {\n\techo $txt,\"<br />\\n\";\n\tob_end_flush(); \n    ob_flush(); \n    flush(); \n}\n\nfunction rrmdir($dir) {\n    foreach(glob($dir . '/{*.txt,*.php,.*.txt,.*.php,.gitattributes,.gitignore,ftr-site-config-master,README.md}', GLOB_BRACE|GLOB_NOSORT) as $file) {\n        if(is_dir($file)) {\n            rrmdir($file);\n        } else {\n            unlink($file);\n\t\t}\n    }\n    return rmdir($dir);\n}"
  },
  {
    "path": "cache/index.php",
    "content": "<?php\n// this is here to prevent directory listing over the web\n?>"
  },
  {
    "path": "cache/rss/index.php",
    "content": "<?php\n// this is here to prevent directory listing over the web\n?>"
  },
  {
    "path": "cache/urls/index.php",
    "content": "<?php\n// this is here to prevent directory listing over the web\n?>"
  },
  {
    "path": "changelog.txt",
    "content": "FiveFilters.org: Full-Text RSS\nhttp://fivefilters.org/content-only/\nCHANGELOG\n------------------------------------\n3.2 (2013-05-14)\n - A short excerpt from the first few lines of the extracted content can now be included in the output (pass &summary=1 in querystring, see $options->summary in config file for more info)\n - Full content can now be excluded from the output (pass &content=0 in querystring, see $options->content in config file for more info) \n - Site config files can now be automatically updated from our GitHub repository (URL to call visible in admin area)\n - Site config files updated for better extraction\n - PHP Readability updated to be more lenient when pruning HTML \n - Language detection library updated\n - HTML meta refresh redirects now also followed\n - APC stats (if APC is available on your server) now visible in admin area\n - Bug fix: Duplicate find_string and replace_string values in site config files no longer removed (thanks Fabrizio!)\n - Bug fix: MIME type actions now applied when following single page URLs\n - Other minor fixes/improvements\n\n3.1 (2013-03-06)\n - PHP Readability updated to preserve more images/videos\n - Site config files updated for better extraction\n - SimplePie updated\n - New config option favour_feed_titles and request parameter use_extracted_title to allow extracted titles to be used in generated feed\n - Remove image lazy loading (looks for markup used by http://wordpress.org/extend/plugins/lazy-load/)\n - <category> elements appearing inside <item> elements are now preserved in generated feed\n - <media:thumbnail> elements now preserved\n - Allow multiple <media:content> elements (previously only one was preserved)\n - Bug fix: No more self-closing iframe elements\n - Bug fix: Fixed manifest.yml to prevent error message when deploying to AppFog\n - Other minor fixes/improvements\n\n3.0 (2012-09-04)\n - Multi-page support - next_page_link now supported in site config (enable/disable with $options->multipage)\n - HTML5 parser available - use parser: html5lib in site config, also see $options->allowed_parsers\n - Updated site patterns for better extraction\n - New global site config to be applied to all sites (global.txt)\n - APC caching of site config files to improve performance, if APC available - see $options->apc \n - Site config editor in admin/ - easily find, edit, test, and test site config files, or add new ones\n - Debug mode to see what's happening behind the scenes - see $options->debug\n - Removed deprecated config options: restrict, message_to_prepend_with_key, message_to_append_with_key, error_message_with_key\n - Removed extraction with CSS via querystring\n - Removed config option: $options->alternative_url\n - Bug fix: allow extraction of a single element\n - Bug fix: redirect handling improved\n - Strip 'http://' prefix when API key is supplied\n - Site config merging (custom + standard + fingerprint + global)\n - Site config command replace_string(find): replace can now be split over two lines: find_string: find, replace_string: replace\n - YouTube and Vimeo URLs now return iframe embed code\n - We now look for OpenGraph title and date elements\n - Improved extraction from AJAX pages - we now look for AJAX triggers embedded in HTML, per Google spec\n - JSONP support - use &format=json&callback=functionName in querystring\n - New config option to enable Cross-Origin Resource Sharing (CORS): $option->cors\n - New config option to enable XSS filtering, if required: $option->xss_filter\n - Zend_Cache updated\n - Smart caching - experimental feature to store cache IDs in APC first, and write output to disk on subsequent request (see $options->smart_cache)\n - Easier cloud deploy - manifest.yml added for AppFog\n - Override most config options with environment variables, e.g. ftr_max_entries: 3\n\n2.9.5 (2012-04-29)\n - Language detection using Text_LanguageDetect or PHP-CLD (dc:language field in output and $options->detect_language in config)\n - New site patterns added and old ones updated\n - Experimental tool for simpler site pattern updates (access admin/ folder)\n - Plus other fixes/improvements\n\n2.9.1 (2011-11-02)\n - Fix: Character encoding issue affecting some non-English articles (makefulltextfeed.php and SimplePie/Misc.php changed)\n\n2.9 (2011-11-01)\n - New site patterns added and old ones updated\n - New config option: require_key - restrict access to those with password/key\n - New config option: rewrite_url - URL rewrite rules to be applied before HTTP request\n - New site config options to extract author(s) and publication date (matches included in feed item as <dc:creator> and <pubDate>)\n - New site config option: replace_string([string to find]): [replacement string]\n - New site identification method: site fingerprints (HTML fragments linked to site config)\n - Update check now also checks for new site patterns\n - Effective URL (URL after redirects/rewrites) now included in feed item as <dc:identifier>\n - Prevent indexing of generated feeds by search engines\n - Enclosure support (enclosures preserved as <media:content> elements)\n - Better handling of non-HTML content types\n - Sending custom User-Agent HTTP header for matching sites now supported\n - CSS extraction deprecated in favour of site patterns (still works, but form field removed and feature may disappear in 3.0)\n - Fix: Improved character-encoding detection\n - Fix: URL parsing issues for certain URLs (SimplePie updated)\n - Fix: Author and other Dublin Core (<dc:..>) elements now appear in JSON output\n - Fix: Minor fixes for PHP Readability\n - Plus other minor fixes/improvements\n \n2.8 (2011-05-30)\n - Tidy no longer stripping HTML5 elements\n - JSON output (pass &format=json in querystring)\n - New site patterns added and old ones updated\n - New site config option to force full-page retrieval on multi-page articles: single_page_link\n - User Guide (PDF) now included (although still a work in progress)\n - URL placeholders now accepted in message_to_prepend/append config options\n - Plus minor fixes...\n\n2.7 (2011-03-21)\n - Site patterns for better control over extraction (see site_config/README.txt)\n - hNews support (improves content extraction for sites using hNews microformatting)\n - Cookie Jar now used to store and sends cookies when following HTTP redirects\n - Better handling of certain cases where HTML Tidy fails to clean up properly\n - Bug fix: curl_multi_select() timing out in certain environments (fixed in HumbleHttpAgent.php)\n - Bug fix: broken HTTP header parsing in some environments (fixed in SimplePie_HumbleHttpAgent.php)\n - Bug fix: invalid API URL shown (fixed in index.php)\n - Plus other minor fixes...\n\n2.6 (2011-03-02)\n - Rewriting of hash-bang (#!) URLs (see http://www.tbray.org/ongoing/When/201x/2011/02/09/Hash-Blecch for an explanation)\n - Improved parallel fetching support (HumbleHttpAgent uses curl_multi_* functions if PECL HTTP extension is not present)\n - Improved HTTP redirect support (now handled in HumbleHttpAgent, no longer relies on PHP)\n - Improved performance for single page (non-feed) requests: (SimplePie connected to HumbleHttpAgent)\n - Improved memory use for processing large feeds (HumbleHttpAgent's stored responses cleared as they're retrieved)\n - Bug fix: exclude on fail option no longer requires valid key\n - Bug fix: workaround for PHP bug http://bugs.php.net/51192 (fixed in makefulltextfeed.php)\n - Plus other minor changes...\n\n2.5 (2011-01-08)\n - New option: custom extraction pattern (CSS selectors)\n - New option: allowed URLs (restrict service to pre-defined feeds/domains)\n - New option: exclude items on fail (remove items from feed if content extraction fails)\n - Remove 'http://' from URL before form submission (prevents errors on hosts which have overly vigilant security software)\n - Allow overriding of index.php with custom_index.php\n - config.php now required (override with custom_config.php)\n - index.php now uses config.php to determine what to display\n - Bug fix: occasional fatal error in IRI::__toString() (IRI updated)\n - Bug fix: workaround for PHP bug http://bugs.php.net/51192 (fixed in HumbleHttpAgent.php)\n\n2.2 (2010-10-30)\n - Character-encoding detection improved (minor change)\n - Rewriting of relative URLs improved (tracks redirect URLs)\n - Minor changes to prevent errors in certain hosting environments\n - Compatibility test file updated with more tests\n\n2.1 (2010-09-13)\n - Better content extraction (using PHP Readability 1.7.1)\n - Parallel HTTP requests (using Humble HTTP Agent)\n - Auto loading of necessary classes\n - Rewriting of relative URLs (using IRI)\n - Added compatibility test file (to check if server meets requirements)\n - Character-encoding support improved (using SimplePie)\n\n1.5 (2010-05-30)\n - Support for PHP 5.3 (thanks Murilo!)\n - Character-encoding support improved (favours iconv over mb_convert_encoding)\n\n1.0 (2010-03-05)\n - Better support for different character-encodings\n - Auto-cleanup of cache files\n - Very basic option for load distribution (if you're planning on installing the code on multiple servers)\n - Separate config file (see config-sample.php) "
  },
  {
    "path": "cleancache.php",
    "content": "<?php\n// Full-Text RSS: Clear Cache\n// Author: Keyvan Minoukadeh\n// Copyright (c) 2012 Keyvan Minoukadeh\n// License: AGPLv3\n\n/*\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n// Usage\n// -----\n// Set up your scheduler (e.g. cron) to request this file periodically.\n// Note: this file must _not_ be named cleancache.php so please rename it.\n// We ask you to do this to prevent others from initiating\n// the cache cleanup process. It will not run if it's called cleancache.php.\n\nerror_reporting(E_ALL ^ E_NOTICE);\nini_set(\"display_errors\", 1);\n@set_time_limit(200);\n\n// check file name\nif (basename(__FILE__) == 'cleancache.php') die('cleancache.php must be renamed');\n\n// set include path\nset_include_path(realpath(dirname(__FILE__).'/libraries').PATH_SEPARATOR.get_include_path());\n\n// Autoloading of classes allows us to include files only when they're\n// needed. If we've got a cached copy, for example, only Zend_Cache is loaded.\nfunction __autoload($class_name) {\n\tstatic $mapping = array(\n\t\t'Zend_Cache' => 'Zend/Cache.php'\n\t);\n\tif (isset($mapping[$class_name])) {\n\t\t//echo \"Loading $class_name\\n<br />\";\n\t\trequire_once $mapping[$class_name];\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n}\nrequire_once dirname(__FILE__).'/config.php';\nif (!$options->caching) die('Caching is disabled');\n\n// clean APC cache\nif ($options->apc && function_exists('apc_delete')) {\n\t$_apc_data = apc_cache_info('user');\n\tforeach ($_apc_data['cache_list'] as $_apc_item) {\n\t  if ($_apc_item['ttl'] > 0 && ($_apc_item['ttl'] + $_apc_item['creation_time'] < time())) {\n\t\tapc_delete($_apc_item['info']);\n\t  }\n\t}\n}\n\n// clean rss (non-key) cache\n$frontendOptions = array(\n   'lifetime' => 20*60,\n   'automatic_serialization' => false,\n   'write_control' => false,\n   'automatic_cleaning_factor' => 0,\n   'ignore_user_abort' => false\n);\n$backendOptions = array(\n\t'cache_dir' => $options->cache_dir.'/rss/',\n\t'file_locking' => false,\n\t'read_control' => true,\n\t'read_control_type' => 'strlen',\n\t'hashed_directory_level' => $options->cache_directory_level,\n\t'hashed_directory_perm' => 0777,\n\t'cache_file_perm' => 0664,\n\t'file_name_prefix' => 'ff'\n);\n$cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);\n$cache->clean(Zend_Cache::CLEANING_MODE_OLD);\n\n// clean rss (key) cache\n$frontendOptions = array(\n   'lifetime' => 20*60,\n   'automatic_serialization' => false,\n   'write_control' => false,\n   'automatic_cleaning_factor' => 0,\n   'ignore_user_abort' => false\n);\n$backendOptions = array(\n\t'cache_dir' => $options->cache_dir.'/rss-with-key/',\n\t'file_locking' => false,\n\t'read_control' => true,\n\t'read_control_type' => 'strlen',\n\t'hashed_directory_level' => $options->cache_directory_level,\n\t'hashed_directory_perm' => 0777,\n\t'cache_file_perm' => 0664,\n\t'file_name_prefix' => 'ff'\n);\n$cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);\n$cache->clean(Zend_Cache::CLEANING_MODE_OLD);\n\n// clean rss (urls) cache\n$frontendOptions = array(\n   'lifetime' => 60*60,\n   'automatic_serialization' => false,\n   'write_control' => false,\n   'automatic_cleaning_factor' => 0,\n   'ignore_user_abort' => false\n);\n$backendOptions = array(\n\t'cache_dir' => $options->cache_dir.'/urls/',\n\t'file_locking' => false,\n\t'read_control' => true,\n\t'read_control_type' => 'strlen',\n\t'hashed_directory_level' => $options->cache_directory_level,\n\t'hashed_directory_perm' => 0777,\n\t'cache_file_perm' => 0664,\n\t'file_name_prefix' => 'ff'\n);\n$cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);\n$cache->clean(Zend_Cache::CLEANING_MODE_OLD);\n\n?>"
  },
  {
    "path": "config.php",
    "content": "<?php\n/* Full-Text RSS config */\n\n// ......IMPORTANT......................................\n// .....................................................\n// Please do not change this file (config.php) directly.\n// Save a copy as custom_config.php and make your\n// changes to that instead. It will automatically\n// override anything in config.php. Because config.php\n// always gets loaded anyway, you can simply specify\n// options you'd like to override in custom_config.php.\n// .....................................................\n\n// Create config object\nif (!isset($options)) $options = new stdClass();\n\n// Enable service\n// ----------------------\n// Set this to false if you want to disable the service.\n// If set to false, no feed is produced and users will \n// be told that the service is disabled.\n$options->enabled = true;\n\n// Debug mode\n// ----------------------\n// Enable or disable debugging. When enabled debugging works by passing\n// &debug=1 to the makefulltextfeed.php querystring.\n// Valid values:\n// true or 'user' (default) - let user decide\n// 'admin' - debug works only for logged in admin users\n// false - disabled\n$options->debug = true;\n\n// Default entries (without access key)\n// ----------------------\n// The number of feed items to process when no API key is supplied\n// and no &max=x value is supplied in the querystring.\n$options->default_entries = 5;\n\n// Max entries (without access key)\n// ----------------------\n// The maximum number of feed items to process when no access key is supplied.\n// This limits the user-supplied &max=x value. For example, if the user\n// asks for 20 items to be processed (&max=20), if max_entries is set to \n// 10, only 10 will be processed.\n$options->max_entries = 10;\n\n// Full content\n// ----------------------\n// By default Full-Text RSS includes the extracted content in the output.\n// You can exclude this from the output by passing '&content=0' in the querystring.\n// \n// Possible values...\n// Always include: true\n// Never include: false\n// Include unless user overrides (&content=0): 'user' (default)\n//\n// Note: currently this does not disable full content extraction. It simply omits it\n// from the output.\n$options->content = 'user';\n\n// Excerpts\n// ----------------------\n// By default Full-Text RSS does not include excerpts in the output.\n// You can enable this by passing '&summary=1' in the querystring.\n// This will include a plain text excerpt from the extracted content.\n// \n// Possible values...\n// Always include: true (recommended for new users)\n// Never include: false\n// Don't include unless user overrides (&summary=1): 'user' (default)\n//\n// Important: if both content and excerpts are requested, the excerpt will be\n// placed in the description element and the full content inside content:encoded.\n// If excerpts are not requested, the full content will go inside the description element.\n// \n// Why are we not returning both excerpts and content by default?\n// Mainly for backward compatibility.\n// Excerpts should appear in the feed item's description element. Previous versions \n// of Full-Text RSS did not return excerpts, so the description element was always \n// used for the full content (as recommended by the RSS advisory). When returning both, \n// we need somewhere else to place the content (content:encoded). \n// Having both enabled should not create any problems for news readers, but it may create\n// problems for developers upgrading from one of our earlier versions who may now find\n// their applications are returning excerpts instead of the full content they were\n// expecting. To avoid such surprises for users who are upgrading Full-Text RSS, \n// excerpts must be explicitly requested in the querystring by default.\n// \n// Why not use a different element name for excerpts?\n// According to the RSS advisory: \n// \"Publishers who employ summaries should store the summary in description and \n// the full content in content:encoded, ordering description first within the item. \n// On items with no summary, the full content should be stored in description.\"\n// See: http://www.rssboard.org/rss-profile#namespace-elements-content-encoded\n// \n// For more consistent element naming, we recommend new users set this option to true.\n// The full content can still be excluded via the querystring, but the element names\n// will not change: when $options->summary = true, the description element will always\n// be reserved for the excerpt and content:encoded always for full content.\n$options->summary = 'user';\n\n// Rewrite relative URLs\n// ----------------------\n// With this enabled relative URLs found in the extracted content\n// block are automatically rewritten as absolute URLs.\n$options->rewrite_relative_urls = true;\n\n// Exclude items if extraction fails\n// ---------------------------------\n// Excludes items from the resulting feed\n// if we cannot extract any content from the\n// item URL.\n// Possible values...\n// Enable: true\n// Disable: false (default)\n// User decides: 'user' (this option will appear on the form)\n$options->exclude_items_on_fail = 'user';\n\n// Enable multi-page support\n// -------------------------\n// If enabled, we will try to follow next page links on multi-page articles.\n// Currently this only happens for sites where next_page_link has been defined \n// in a site config file.\n$options->multipage = true;\n\n// Enable caching\n// ----------------------\n// Enable this if you'd like to cache results\n// for 10 minutes. Cache files are written to disk (in cache/ subfolders\n// - which must be writable).\n// Initially it's best to keep this disabled to make sure everything works\n// as expected. If you have APC enabled, please also see smart_cache in the\n// advanced section.\n$options->caching = false;\n\n// Cache directory\n// ----------------------\n// Only used if caching is true\n$options->cache_dir = dirname(__FILE__).'/cache';\n\n// Message to prepend (without access key)\n// ----------------------\n// HTML to insert at the beginning of each feed item when no access key is supplied.\n// Substitution tags:\n// {url} - Feed item URL\n// {effective-url} - Feed item URL after we've followed all redirects\n$options->message_to_prepend = '';\n\n// Message to append (without access key)\n// ----------------------\n// HTML to insert at the end of each feed item when no access key is supplied.\n// Substitution tags:\n// {url} - Feed item URL\n// {effective-url} - Feed item URL after we've followed all redirects\n$options->message_to_append = '';\n\n// Error message when content extraction fails (without access key)\n// ----------------------\n$options->error_message = '[unable to retrieve full-text content]';\n\n// Keep enclosure in feed items\n// If enabled, we will try to preserve enclosures if present.\n// ----------------------\n$options->keep_enclosures = true;\n\n// Detect language\n// ---------------\n// Should we try and find/guess the language of the article being processed?\n// Values will be placed inside the <dc:language> element inside each <item> element\n// Possible values:\n// * Ignore language: 0\n// * Use article/feed metadata (e.g. HTML lang attribute): 1 (default)\n// * As above, but guess if not present: 2\n// * Always guess: 3\n// * User decides: 'user' (value of 0-3 can be passed in querystring: e.g. &l=2)\n$options->detect_language = 1;\n\n// Registration key\n// ---------------\n// The registration key is optional. It is not required to use Full-Text RSS, \n// and does not affect the normal operation of Full-Text RSS. It is currently \n// only used on admin pages which help you update site patterns with the \n// latest version offered by FiveFilters.org. For these admin-related \n// tasks to complete, we will require a valid registration key.\n// If you would like one, you can purchase the latest version of Full-Text RSS\n// at http://fivefilters.org/content-only/\n// Your registration key will automatically be sent in the confirmation email.\n// Once you have it, simply copy and paste it here.\n$options->registration_key = '';\n\n/////////////////////////////////////////////////\n/// RESTRICT ACCESS /////////////////////////////\n/////////////////////////////////////////////////\n\n// Admin credentials\n// ----------------------\n// Certain pages/actions, e.g. updating site patterns with our online tool, will require admin credentials.\n// To use these pages, enter a password here and you'll be prompted for it when you try to access those pages.\n// If no password or username is set, pages requiring admin privelages will be inaccessible. \n// The default username is 'admin'.\n// If overriding with an environment variable, separate username and password with a colon, e.g.:\n// ftr_admin_credentials: admin:my-secret-password\n// Example: $options->admin_credentials = array('username'=>'admin', 'password'=>'my-secret-password');\n$options->admin_credentials = array('username'=>'admin0', 'password'=>'admin0');\n\n// URLs to allow\n// ----------------------\n// List of URLs (or parts of a URL) which the service will accept.\n// If the list is empty, all URLs (except those specified in the blocked list below)\n// will be permitted.\n// Empty: array();\n// Non-empty example: array('example.com', 'anothersite.org');\n$options->allowed_urls = array();\n\n// URLs to block\n// ----------------------\n// List of URLs (or parts of a URL) which the service will not accept.\n// Note: this list is ignored if allowed_urls is not empty\n$options->blocked_urls = array();\n\n// Key holder(s) only?\n// ----------------------\n// Set this to true if you want to restrict access only to\n// those with a key (see below to specify key(s)).\n// If set to true, no feed is produced unless a valid\n// key is provided.\n$options->key_required = false;\n\n// Favour item titles in feed\n// ----------------------\n// By default, when processing feeds, we assume item titles in the feed\n// have not been truncated. So after processing web pages, the extracted titles\n// are not used in the generated feed. If you prefer to have extracted titles in \n// the feed you can either set this to false, in which case we will always favour \n// extracted titles. Alternatively, if set to 'user' (default) we'll use the \n// extracted title if you pass '&use_extracted_title' in the querystring.\n// Possible values:\n// * Favour feed titles: true \n// * Favour extracted titles: false\n// * Favour feed titles with user override: 'user' (default)\n// Note: this has no effect when the input URL is to a web page - in these cases\n// we always use the extracted title in the generated feed.\n$options->favour_feed_titles = 'user';\n\n// Access keys (password protected access)\n// ------------------------------------\n// NOTE: You do not need an API key from fivefilters.org to run your own \n// copy of the code. This is here if you'd like to restrict access to\n// _your_ copy.\n// Keys let you group users - those with a key and those without - and\n// restrict access to the service to those without a key.\n// If you want everyone to access the service in the same way, you can\n// leave the array below empty and ignore the access key options further down.\n// The options further down let you control how the service should behave \n// in each mode.\n// Note: Explicitly including the index number (1 and 2 in the examples below) \n// is highly recommended (when generating feeds, we encode the key and \n// refer to it by index number and hash).\n$options->api_keys = array();\n// Example:\n// $options->api_keys[1] = 'secret-key-1';\n// $options->api_keys[2] = 'secret-key-2';\n\n// Default entries (with access key)\n// ----------------------\n// The number of feed items to process when a valid access key is supplied.\n$options->default_entries_with_key = 5;\n\n// Max entries (with access key)\n// ----------------------\n// The maximum number of feed items to process when a valid access key is supplied.\n$options->max_entries_with_key = 10;\n\n/////////////////////////////////////////////////\n/// ADVANCED OPTIONS ////////////////////////////\n/////////////////////////////////////////////////\n\n// Enable XSS filter?\n// ----------------------\n// We have not enabled this by default because we assume the majority of\n// our users do not display the HTML retrieved by Full-Text RSS\n// in a web page without further processing. If you subscribe to our generated\n// feeds in your news reader application, it should, if it's good software, already\n// filter the resulting HTML for XSS attacks, making it redundant for\n// Full-Text RSS do the same. Similarly with frameworks/CMS which display\n// feed content - the content should be treated like any other user-submitted content.\n// \n// If you are writing an application yourself which is processing feeds generated by\n// Full-Text RSS, you can either filter the HTML yourself to remove potential XSS attacks\n// or enable this option. This might be useful if you are processing our generated\n// feeds with JavaScript on the client side - although there's client side xss\n// filtering available too, e.g. https://code.google.com/p/google-caja/wiki/JsHtmlSanitizer\n// \n// If enabled, we'll pass retrieved HTML content through htmLawed with\n// safe flag on and style attributes denied, see\n// http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/htmLawed_README.htm#s3.6\n// Note: if enabled this will also remove certain elements you may want to preserve, such as iframes.\n//\n// Valid values:\n// true - enabled, all content will be filtered\n// 'user' (default) - user must pass &xss in makefulltextfeed.php querystring to enable\n// false - disabled\n$options->xss_filter = 'user';\n\n// Allowed parsers\n// ----------------------\n// Full-Text RSS attempts to use PHP's libxml extension to process HTML.\n// While fast, on some sites it may not always produce good results. \n// For these sites, you can specify an alternative HTML parser: \n// parser: html5lib\n// The html5lib parser is bundled with Full-Text RSS.\n// see http://code.google.com/p/html5lib/\n//\n// To disable HTML parsing with html5lib, you can remove it from this list.\n// By default we allow both: libxml and html5lib.\n$options->allowed_parsers = array('libxml', 'html5lib');\n//$options->allowed_parsers = array('libxml'); //disable html5lib - forcing libxml in all cases\n\n// Enable Cross-Origin Resource Sharing (CORS)\n// ----------------------\n// If enabled we'll send the following HTTP header\n// Access-Control-Allow-Origin: *\n// see http://en.wikipedia.org/wiki/Cross-origin_resource_sharing\n$options->cors = false;\n\n// Use APC user cache?\n// ----------------------\n// If enabled we will store site config files (when requested \n// for the first time) in APC's user cache. Keys prefixed with 'sc.'\n// This improves performance by reducing disk access.\n// Note: this has no effect if APC is unavailable on your server.\n$options->apc = true;\n\n// Smart cache (experimental)\n// ----------------------\n// With this option enabled we will not cache to disk immediately.\n// We will store the cache key in APC and if it's requested again\n// we will cache results to disk. Keys prefixed with 'cache.'\n// This improves performance by reducing disk access.\n// Note: this has no effect if APC is disabled or unavailable on your server,\n// or if you have caching disabled.\n$options->smart_cache = true;\n\n// Fingerprints\n// ----------------------\n// key is fingerprint (fragment to find in HTML)\n// value is host name to use for site config lookup if fingerprint matches\n$options->fingerprints = array(\n\t// Posterous\n\t'<meta name=\"generator\" content=\"Posterous\"' => array('hostname'=>'fingerprint.posterous.com', 'head'=>true),\n\t// Blogger\n\t'<meta content=\\'blogger\\' name=\\'generator\\'' => array('hostname'=>'fingerprint.blogspot.com', 'head'=>true),\n\t'<meta name=\"generator\" content=\"Blogger\"' => array('hostname'=>'fingerprint.blogspot.com', 'head'=>true),\n\t// WordPress (hosted)\n\t// '<meta name=\"generator\" content=\"WordPress.com\"' => array('hostname'=>'fingerprint.wordpress.com', 'head'=>true),\n\t// WordPress (self-hosted and hosted)\n\t'<meta name=\"generator\" content=\"WordPress' => array('hostname'=>'fingerprint.wordpress.com', 'head'=>true)\n);\n\n// User Agent strings - mapping domain names\n// ----------------------\n// e.g. $options->user_agents = array('example.org' => 'PHP/5.2');\n$options->user_agents = array( 'lifehacker.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   'gawker.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   'deadspin.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   'kotaku.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   'jezebel.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   'io9.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   'jalopnik.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   'gizmodo.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   '.wikipedia.org' => 'Mozilla/5.2',\n\t\t\t\t\t\t\t   '.fok.nl' => 'Googlebot/2.1',\n\t\t\t\t\t\t\t   'getpocket.com' => 'PHP/5.2'\n\t\t\t\t\t\t\t  );\n\n// URL Rewriting\n// ----------------------\n// Currently allows simple string replace of URLs.\n// Useful for rewriting certain URLs to point to a single page\n// or HTML view. Although using the single_page_link site config\n// instruction is the preferred way to do this, sometimes, as\n// with Google Docs URLs, it's not possible.\n// Note: this might move to the site config file at some point.\n$options->rewrite_url = array(\n\t// Rewrite public Google Docs URLs to point to HTML view:\n\t// if a URL contains docs.google.com, replace /Doc? with /View?\n\t'docs.google.com' => array('/Doc?' => '/View?'),\n\t'tnr.com' => array('tnr.com/article/' => 'tnr.com/print/article/'),\n\t'.m.wikipedia.org' => array('.m.wikipedia.org' => '.wikipedia.org'),\n\t'm.vanityfair.com' => array('m.vanityfair.com' => 'www.vanityfair.com')\n);\n\n// Content-Type exceptions\n// -----------------------\n// Here you can define different actions based\n// on the Content-Type header returned by server.\n// MIME type as key, action as value.\n// Valid actions:\n// * 'exclude' - exclude this item from the result\n// * 'link' - create HTML link to the item\n$options->content_type_exc = array( \n\t\t\t\t\t\t\t   'application/pdf' => array('action'=>'link', 'name'=>'PDF'),\n\t\t\t\t\t\t\t   'image' => array('action'=>'link', 'name'=>'Image'),\n\t\t\t\t\t\t\t   'audio' => array('action'=>'link', 'name'=>'Audio'),\n\t\t\t\t\t\t\t   'video' => array('action'=>'link', 'name'=>'Video')\n\t\t\t\t\t\t\t  );\n\n// Cache directory level\n// ----------------------\n// Spread cache files over different directories (only used if caching is enabled).\n// Used to prevent large number of files in one directory.\n// This corresponds to Zend_Cache's hashed_directory_level\n// see http://framework.zend.com/manual/en/zend.cache.backends.html\n// It's best not to change this if you're unsure.\n$options->cache_directory_level = 0;\n\n// Cache cleanup\n// -------------\n// 0 = script will not clean cache (rename cachecleanup.php and use it for scheduled (e.g. cron) cache cleanup)\n// 1 = clean cache everytime the script runs (not recommended)\n// 100 = clean cache roughly once every 100 script runs\n// x = clean cache roughly once every x script runs\n// ...you get the idea :)\n$options->cache_cleanup = 100;\n\n/////////////////////////////////////////////////\n/// DO NOT CHANGE ANYTHING BELOW THIS ///////////\n/////////////////////////////////////////////////\n\nif (!defined('_FF_FTR_VERSION')) define('_FF_FTR_VERSION', '3.2');\n\nif (basename(__FILE__) == 'config.php') {\n\tif (file_exists(dirname(__FILE__).'/custom_config.php')) {\n\t\trequire_once dirname(__FILE__).'/custom_config.php';\n\t}\n\t\n\t// check for environment variables - often used on cloud platforms\n\t// environment variables should be prefixed with 'ftr_', e.g.\n\t// ftr_max_entries: 1\n\t// will set the max_entries value to 1.\n\tforeach ($options as $_key=>&$_val) {\n\t\t$_key = \"ftr_$_key\";\n\t\tif (($_env = getenv($_key)) !== false) {\n\t\t\tif (is_array($_val)) {\n\t\t\t\tif ($_key === 'ftr_admin_credentials') {\n\t\t\t\t\t$_val = array_combine(array('username', 'password'), array_map('trim', explode(':', $_env, 2)));\n\t\t\t\t\tif ($_val === false) $_val = array('username'=>'admin', 'password'=>'');\n\t\t\t\t}\n\t\t\t} elseif ($_env === 'true' || $_env === 'false') {\n\t\t\t\t$_val = ($_env === 'true');\n\t\t\t} elseif (is_numeric($_env)) {\n\t\t\t\t$_val = (int)$_env;\n\t\t\t} else { // string\n\t\t\t\t$_val = $_env;\n\t\t\t}\n\t\t}\n\t}\n\tunset($_key, $_val, $_env);\n}"
  },
  {
    "path": "css/feed.css",
    "content": "/* RSS CSS Document */\n\n* { margin:0; padding:0; }\n\np { padding: .5em 0; }\n\nh1,h2,h3,h4,h5,h6 { font-size: 1em; padding: .5em 0; }\n\nhtml { display:block; padding-bottom:50px; }\nbody { font:80% Verdana, sans-serif; color:#000; padding:25px 0 0 35px; }\n\na { color:#5BAB03; text-decoration:none; }\na:hover { color:#5BAB03; text-decoration: underline;}\n\nul { margin-left:1.5em; }\nli { margin-bottom:0.4em; }\ndiv#content>ul { list-style-type: none; }\ndiv.article>li>a { font-weight:bold; font-size: 1.3em;}\n\n\ndiv { line-height:1.6em; }\n\ndiv#content { background:#fff; margin-right:15px; padding-left:1em;}\ndiv#content div { margin:0 1em 1em 0; }\n\ndiv#explanation { padding:1em 1em 0 1em; border:1px solid #ddd; background:#efefef; margin:0 2em 2em 0; }\ndiv#explanation h1 { font-weight:normal; font-size:1.8em; margin-bottom:0.3em; }\ndiv#explanation p { margin-bottom:1em; }\n\n.small { font-size: .7em; color: #666; }"
  },
  {
    "path": "css/feed.xsl",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:content=\"http://purl.org/rss/1.0/modules/content/\">\n<xsl:output method=\"html\" /> \n<xsl:variable name=\"title\" select=\"/rss/channel/title\"/>\t\t\n<xsl:template match=\"/\">\n<html>\n  <head>\n    <title><xsl:value-of select=\"$title\"/> (full-text feed)</title>\n    <style type=\"text/css\">\n    @import url(css/feed.css);\n    </style>\n  </head>\n  <body>\n    <div id=\"explanation\">\n      <h1><xsl:value-of select=\"$title\"/> <span class=\"small\"> (full-text feed)</span></h1>\n      <p>You are viewing an auto-generated full-text <acronym title=\"Really Simple Syndication\">RSS</acronym> feed. RSS feeds allow you to stay up to date with the latest news and features you want from websites. To subscribe to it, you will need a News Reader or other similar device.</p>\n      <p>Below is the latest content available from this feed.</p>\n    </div>\n    \n    <div id=\"content\">\n    <ul>\n      <xsl:for-each select=\"rss/channel/item\">\n      <div class=\"article\">\n        <li><a href=\"{link}\" rel=\"bookmark\"><xsl:value-of disable-output-escaping=\"yes\" select=\"title\"/></a>\n\t\t\t<div>\n\t\t\t<xsl:choose>\n\t\t\t\t<xsl:when test=\"content:encoded\"><xsl:value-of disable-output-escaping=\"yes\" select=\"content:encoded\" /></xsl:when>\n\t\t\t\t<xsl:when test=\"description\"><xsl:value-of disable-output-escaping=\"yes\" select=\"description\" /></xsl:when>\n\t\t\t</xsl:choose>\n\t\t\t</div>\n\t\t</li>        \n      </div>\n      </xsl:for-each>\n      </ul>\n    </div>\n</body>\n</html>\n</xsl:template>\n</xsl:stylesheet>"
  },
  {
    "path": "custom_config.php.demo",
    "content": "<?php\n/* Full-Text RSS config */\n$options->debug = true;\n$options->default_entries = 15;\n$options->max_entries = 40;\n$options->summary = 'user';\n$options->rewrite_relative_urls = true;\n$options->exclude_items_on_fail = 'user';\n$options->multipage = true;\n$options->caching = true;\n$options->cache_dir = dirname(__FILE__).'/cache';\n$options->error_message = '[unable to retrieve full-text content]';\n$options->keep_enclosures = true;\n$options->detect_language = 1;\n$options->registration_key = '';\n$options->admin_credentials = array('username'=>'admin0', 'password'=>'admin0');\n// Non-empty example: array('example.com', 'anothersite.org');\n$options->allowed_urls = array();\n$options->blocked_urls = array();\n$options->favour_feed_titles = 'user';\n$options->xss_filter = 'user';\n$options->allowed_parsers = array('libxml', 'html5lib');\n$options->cors = false;\n$options->apc = true;\n$options->smart_cache = true;\n$options->cache_ttl = 60*60;\n$options->http_cache_ttl = 3*24*60*60;\n$options->fingerprints = array(\n\t// Posterous\n\t'<meta name=\"generator\" content=\"Posterous\"' => array('hostname'=>'fingerprint.posterous.com', 'head'=>true),\n\t// Blogger\n\t'<meta content=\\'blogger\\' name=\\'generator\\'' => array('hostname'=>'fingerprint.blogspot.com', 'head'=>true),\n\t'<meta name=\"generator\" content=\"Blogger\"' => array('hostname'=>'fingerprint.blogspot.com', 'head'=>true),\n\t// WordPress (self-hosted and hosted)\n\t'<meta name=\"generator\" content=\"WordPress' => array('hostname'=>'fingerprint.wordpress.com', 'head'=>true)\n);\n$options->user_agents = array( 'lifehacker.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   'gawker.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   'deadspin.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   'kotaku.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   'jezebel.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   'io9.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   'jalopnik.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   'gizmodo.com' => 'PHP/5.2',\n\t\t\t\t\t\t\t   '.wikipedia.org' => 'Mozilla/5.2',\n\t\t\t\t\t\t\t   '.fok.nl' => 'Googlebot/2.1',\n\t\t\t\t\t\t\t   'getpocket.com' => 'PHP/5.2'\n\t\t\t\t\t\t\t  );\n$options->rewrite_url = array(\n\t// Rewrite public Google Docs URLs to point to HTML view:\n\t// if a URL contains docs.google.com, replace /Doc? with /View?\n\t'docs.google.com' => array('/Doc?' => '/View?'),\n\t'tnr.com' => array('tnr.com/article/' => 'tnr.com/print/article/'),\n\t'.m.wikipedia.org' => array('.m.wikipedia.org' => '.wikipedia.org'),\n\t'm.vanityfair.com' => array('m.vanityfair.com' => 'www.vanityfair.com')\n);\n$options->content_type_exc = array( \n\t\t\t\t\t\t\t   'application/pdf' => array('action'=>'link', 'name'=>'PDF'),\n\t\t\t\t\t\t\t   'image' => array('action'=>'link', 'name'=>'Image'),\n\t\t\t\t\t\t\t   'audio' => array('action'=>'link', 'name'=>'Audio'),\n\t\t\t\t\t\t\t   'video' => array('action'=>'link', 'name'=>'Video')\n\t\t\t\t\t\t\t  );\n$options->cache_directory_level = 0;\n$options->cache_cleanup = 100;"
  },
  {
    "path": "ftr_compatibility_test.php",
    "content": "<?php\n/*\nFULL-TEXT-RSS V3 COMPATIBILITY TEST\n\n1) Upload ftr_compatibility_test.php to the web-accessible root of your website.\nFor example, if your website is www.example.com, upload it so that you can get\nto it at www.example.com/ftr_compatibility_test.php\n\n2) Open your web browser and go to the page you just uploaded.\n\nIf things don't look right, have a look at our hosting suggestions:\nhttp://help.fivefilters.org/customer/portal/articles/1143210-hosting\n\nNote: This compatibility test has been borrowed (and slightly adapted) from the one supplied by \nSimplePie.org. We have kept most of their checks intact as we use SimplePie in our application.\nhttp://github.com/simplepie/simplepie/tree/master/compatibility_test/\n*/\n\n$app_name = 'Full-Text RSS 3.2';\n\n$php_ok = (function_exists('version_compare') && version_compare(phpversion(), '5.2.0', '>='));\n$pcre_ok = extension_loaded('pcre');\n$zlib_ok = extension_loaded('zlib');\n$mbstring_ok = extension_loaded('mbstring');\n$iconv_ok = extension_loaded('iconv');\n$tidy_ok = function_exists('tidy_parse_string');\n$curl_ok = function_exists('curl_exec');\n$parallel_ok = ((extension_loaded('http') && class_exists('HttpRequestPool')) || ($curl_ok && function_exists('curl_multi_init')));\n$allow_url_fopen_ok = (bool)ini_get('allow_url_fopen');\n$filter_ok = extension_loaded('filter');\n\nif (extension_loaded('xmlreader')) {\n\t$xml_ok = true;\n} elseif (extension_loaded('xml')) {\n\t$parser_check = xml_parser_create();\n\txml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);\n\txml_parser_free($parser_check);\n\t$xml_ok = isset($values[0]['value']);\n} else {\n\t$xml_ok = false;\n}\n\nheader('Content-type: text/html; charset=UTF-8');\n\n?><!DOCTYPE html>\n\n<html lang=\"en\">\n<head>\n<title><?php echo $app_name; ?>: Server Compatibility Test</title>\n\n<style type=\"text/css\">\nbody {\n\tfont:14px/1.4em \"Lucida Grande\", Verdana, Arial, Helvetica, Clean, Sans, sans-serif;\n\tletter-spacing:0px;\n\tcolor:#333;\n\tmargin:0;\n\tpadding:0;\n\tbackground:#fff;\n}\n\ndiv#site {\n\twidth:550px;\n\tmargin:20px auto 0 auto;\n}\n\na {\n\tcolor:#000;\n\ttext-decoration:underline;\n\tpadding:0 1px;\n}\n\na:hover {\n\tcolor:#fff;\n\tbackground-color:#333;\n\ttext-decoration:none;\n\tpadding:0 1px;\n}\n\np {\n\tmargin:0;\n\tpadding:5px 0;\n}\n\nem {\n\tfont-style:normal;\n\tbackground-color:#ffc;\n\tpadding: 0.1em 0;\n}\n\n.success {\n  background-color: lightgreen;\n}\n\n.highlight {\n  background-color: #ffc;\n}\n\nul, ol {\n\tmargin:10px 0 10px 20px;\n\tpadding:0 0 0 15px;\n}\n\nul li, ol li {\n\tmargin:0 0 7px 0;\n\tpadding:0 0 0 3px;\n}\n\nh2 {\n\tfont-size:18px;\n\tpadding:0;\n\tmargin:30px 0 20px 0;\n}\n\nh3 {\n\tfont-size:16px;\n\tpadding:0;\n\tmargin:20px 0 5px 0;\n}\n\nh4 {\n\tfont-size:14px;\n\tpadding:0;\n\tmargin:15px 0 5px 0;\n}\n\ncode {\n\tfont-size:1.1em;\n\tcolor:#000;\n}\n\nem strong {\n    text-transform: uppercase;\n}\n\ntable.chart {\n\tborder-collapse:collapse;\n}\n\ntable.chart th {\n\tbackground-color:#eee;\n\tpadding:2px 3px;\n\tborder:1px solid #fff;\n}\n\ntable.chart td {\n\ttext-align:center;\n\tpadding:2px 3px;\n\tborder:1px solid #eee;\n}\n\ntable.chart tr.enabled td {\n\t/* Leave this alone */\n}\n\ntable.chart tr.disabled td, \ntable.chart tr.disabled td a {\n\tcolor:#999;\n\tfont-style:italic;\n}\n\ntable.chart tr.disabled td a {\n\ttext-decoration:underline;\n}\n\ndiv.chunk {\n\tmargin:20px 0 0 0;\n\tpadding:0 0 10px 0;\n\tborder-bottom:1px solid #ccc;\n}\n\n.footnote,\n.footnote a {\n\tfont:10px/12px verdana, sans-serif;\n\tcolor:#aaa;\n}\n\n.footnote em {\n\tbackground-color:transparent;\n\tfont-style:italic;\n}\n</style>\n\n</head>\n\n<body>\n\n<div id=\"site\">\n\t<div id=\"content\">\n\n\t\t<div class=\"chunk\">\n\t\t\t<h2 style=\"text-align:center;\"><?php echo $app_name; ?>: Compatibility Test</h2>\n\t\t\t<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\" class=\"chart\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th>Test</th>\n\t\t\t\t\t\t<th>Should Be</th>\n\t\t\t\t\t\t<th>What You Have</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t<tr class=\"<?php echo ($php_ok) ? 'enabled' : 'disabled'; ?>\">\n\t\t\t\t\t\t<td>PHP</td>\n\t\t\t\t\t\t<td>5.2.0 or higher</td>\n\t\t\t\t\t\t<td><?php echo phpversion(); ?></td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr class=\"<?php echo ($xml_ok) ? 'enabled, and sane' : 'disabled, or broken'; ?>\">\n\t\t\t\t\t\t<td><a href=\"http://php.net/xml\">XML</a></td>\n\t\t\t\t\t\t<td>Enabled</td>\n\t\t\t\t\t\t<td><?php echo ($xml_ok) ? 'Enabled, and sane' : 'Disabled, or broken'; ?></td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr class=\"<?php echo ($pcre_ok) ? 'enabled' : 'disabled'; ?>\">\n\t\t\t\t\t\t<td><a href=\"http://php.net/pcre\">PCRE</a></td>\n\t\t\t\t\t\t<td>Enabled</td>\n\t\t\t\t\t\t<td><?php echo ($pcre_ok) ? 'Enabled' : 'Disabled'; ?></td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr class=\"<?php echo ($zlib_ok) ? 'enabled' : 'disabled'; ?>\">\n\t\t\t\t\t\t<td><a href=\"http://php.net/zlib\">Zlib</a></td>\n\t\t\t\t\t\t<td>Enabled</td>\n\t\t\t\t\t\t<td><?php echo ($zlib_ok) ? 'Enabled' : 'Disabled'; ?></td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr class=\"<?php echo ($mbstring_ok) ? 'enabled' : 'disabled'; ?>\">\n\t\t\t\t\t\t<td><a href=\"http://php.net/mbstring\">mbstring</a></td>\n\t\t\t\t\t\t<td>Enabled</td>\n\t\t\t\t\t\t<td><?php echo ($mbstring_ok) ? 'Enabled' : 'Disabled'; ?></td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr class=\"<?php echo ($iconv_ok) ? 'enabled' : 'disabled'; ?>\">\n\t\t\t\t\t\t<td><a href=\"http://php.net/iconv\">iconv</a></td>\n\t\t\t\t\t\t<td>Enabled</td>\n\t\t\t\t\t\t<td><?php echo ($iconv_ok) ? 'Enabled' : 'Disabled'; ?></td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr class=\"<?php echo ($filter_ok) ? 'enabled' : 'disabled'; ?>\">\n\t\t\t\t\t\t<td><a href=\"http://uk.php.net/manual/en/book.filter.php\">Data filtering</a></td>\n\t\t\t\t\t\t<td>Enabled</td>\n\t\t\t\t\t\t<td><?php echo ($filter_ok) ? 'Enabled' : 'Disabled'; ?></td>\n\t\t\t\t\t</tr>\t\t\t\t\t\n\t\t\t\t\t<tr class=\"<?php echo ($tidy_ok) ? 'enabled' : 'disabled'; ?>\">\n\t\t\t\t\t\t<td><a href=\"http://php.net/tidy\">Tidy</a></td>\n\t\t\t\t\t\t<td>Enabled</td>\n\t\t\t\t\t\t<td><?php echo ($tidy_ok) ? 'Enabled' : 'Disabled'; ?></td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr class=\"<?php echo ($curl_ok) ? 'enabled' : 'disabled'; ?>\">\n\t\t\t\t\t\t<td><a href=\"http://php.net/curl\">cURL</a></td>\n\t\t\t\t\t\t<td>Enabled</td>\n\t\t\t\t\t\t<td><?php echo (extension_loaded('curl')) ? 'Enabled' : 'Disabled'; ?></td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr class=\"<?php echo ($parallel_ok) ? 'enabled' : 'disabled'; ?>\">\n\t\t\t\t\t\t<td>Parallel URL fetching</td>\n\t\t\t\t\t\t<td>Enabled</td>\n\t\t\t\t\t\t<td><?php echo ($parallel_ok) ? 'Enabled' : 'Disabled'; ?></td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t<tr class=\"<?php echo ($allow_url_fopen_ok) ? 'enabled' : 'disabled'; ?>\">\n\t\t\t\t\t\t<td><a href=\"http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen\">allow_url_fopen</a></td>\n\t\t\t\t\t\t<td>Enabled</td>\n\t\t\t\t\t\t<td><?php echo ($allow_url_fopen_ok) ? 'Enabled' : 'Disabled'; ?></td>\n\t\t\t\t\t</tr>\t\t\t\t\t\t\n\t\t\t\t</tbody>\n\t\t\t</table>\n\t\t</div>\n\t\t\n\t\t<div class=\"chunk\">\n\t\t\t<h3>What does this mean?</h3>\n\t\t\t<ol>\n\t\t\t\t<?php if ($php_ok && $xml_ok && $pcre_ok && $mbstring_ok && $iconv_ok && $filter_ok && $zlib_ok && $tidy_ok && $curl_ok && $parallel_ok && $allow_url_fopen_ok): ?>\n\t\t\t\t<li>You have everything you need to run <?php echo $app_name; ?> properly!  Congratulations!</li>\n\t\t\t\t<?php else: ?>\n\t\t\t\t\t<?php if ($php_ok): ?>\n\t\t\t\t\t\t<li><strong>PHP:</strong> You are running a supported version of PHP.  No problems here.</li>\n\t\t\t\t\t\t<?php if ($xml_ok): ?>\n\t\t\t\t\t\t\t<li><strong>XML:</strong> You have XMLReader support or a version of XML support that isn't broken installed.  No problems here.</li>\n\t\t\t\t\t\t\t<?php if ($pcre_ok): ?>\n\t\t\t\t\t\t\t\t<li><strong>PCRE:</strong> You have PCRE support installed. No problems here.</li>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<?php if ($allow_url_fopen_ok): ?>\n\t\t\t\t\t\t\t\t\t<li><strong>allow_url_fopen:</strong> You have allow_url_fopen enabled. No problems here.</li>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t<?php if ($filter_ok): ?>\n\t\t\t\t\t\t\t\t\t\t<li><strong>Data filtering:</strong> You have the PHP filter extension enabled. No problems here.</li>\n\t\n\t\t\t\t\t\t\t\t\t\t<?php if ($zlib_ok): ?>\n\t\t\t\t\t\t\t\t\t\t\t<li><strong>Zlib:</strong> You have <code>Zlib</code> enabled.  This allows SimplePie to support GZIP-encoded feeds.  No problems here.</li>\n\t\t\t\t\t\t\t\t\t\t<?php else: ?>\n\t\t\t\t\t\t\t\t\t\t\t<li class=\"highlight\"><strong>Zlib:</strong> The <code>Zlib</code> extension is not available.  SimplePie will ignore any GZIP-encoding, and instead handle feeds as uncompressed text.</li>\n\t\t\t\t\t\t\t\t\t\t<?php endif; ?>\n\t\t\t\n\t\t\t\t\t\t\t\t\t\t<?php if ($mbstring_ok && $iconv_ok): ?>\n\t\t\t\t\t\t\t\t\t\t\t<li><strong>mbstring and iconv:</strong> You have both <code>mbstring</code> and <code>iconv</code> installed!  This will allow <?php echo $app_name; ?> to handle the greatest number of languages. No problems here.</li>\n\t\t\t\t\t\t\t\t\t\t<?php elseif ($mbstring_ok): ?>\n\t\t\t\t\t\t\t\t\t\t\t<li class=\"highlight\"><strong>mbstring:</strong> <code>mbstring</code> is installed, but <code>iconv</code> is not.</li>\n\t\t\t\t\t\t\t\t\t\t<?php elseif ($iconv_ok): ?>\n\t\t\t\t\t\t\t\t\t\t\t<li class=\"highlight\"><strong>iconv:</strong> <code>iconv</code> is installed, but <code>mbstring</code> is not.</li>\n\t\t\t\t\t\t\t\t\t\t<?php else: ?>\n\t\t\t\t\t\t\t\t\t\t\t<li class=\"highlight\"><strong>mbstring and iconv:</strong> <em>You do not have either of the extensions installed.</em> This will significantly impair your ability to read non-English feeds, as well as even some English ones.</li>\n\t\t\t\t\t\t\t\t\t\t<?php endif; ?>\n\n\t\t\t\t\t\t\t\t\t\t<?php if ($tidy_ok): ?>\n\t\t\t\t\t\t\t\t\t\t\t<li><strong>Tidy:</strong> You have <code>Tidy</code> support installed.  No problems here.</li>\n\t\t\t\t\t\t\t\t\t\t<?php else: ?>\n\t\t\t\t\t\t\t\t\t\t\t<li class=\"highlight\"><strong>Tidy:</strong> The <code>Tidy</code> extension is not available.  <?php echo $app_name; ?> should still work with most feeds/articles, but you may experience problems with some.</li>\n\t\t\t\t\t\t\t\t\t\t<?php endif; ?>\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t<?php if ($curl_ok): ?>\n\t\t\t\t\t\t\t\t\t\t\t<li><strong>cURL:</strong> You have <code>cURL</code> support installed.  No problems here.</li>\n\t\t\t\t\t\t\t\t\t\t<?php else: ?>\n\t\t\t\t\t\t\t\t\t\t\t<li class=\"highlight\"><strong>cURL:</strong> The <code>cURL</code> extension is not available.  SimplePie will use <code>fsockopen()</code> instead.</li>\n\t\t\t\t\t\t\t\t\t\t<?php endif; ?>\n\t\t\t\n\t\t\t\t\t\t\t\t\t\t<?php if ($parallel_ok): ?>\n\t\t\t\t\t\t\t\t\t\t\t<li><strong>Parallel URL fetching:</strong> You have <code>HttpRequestPool</code> or <code>curl_multi</code> support installed.  No problems here.</li>\n\t\t\t\t\t\t\t\t\t\t<?php else: ?>\n\t\t\t\t\t\t\t\t\t\t\t<li class=\"highlight\"><strong>Parallel URL fetching:</strong> <code>HttpRequestPool</code> or <code>curl_multi</code> support is not available.  <?php echo $app_name; ?> will use <code>file_get_contents()</code> instead to fetch URLs sequentially rather than in parallel.</li>\n\t\t\t\t\t\t\t\t\t\t<?php endif; ?>\n\n\t\t\t\t\t\t\t\t\t<?php else: ?>\n\t\t\t\t\t\t\t\t\t\t<li class=\"highlight\"><strong>Data filtering:</strong> Your PHP configuration has the filter extension disabled.  <em><?php echo $app_name; ?> will not work here.</em></li>\n\t\t\t\t\t\t\t\t\t<?php endif; ?>\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t<?php else: ?>\n\t\t\t\t\t\t\t\t\t<li class=\"highlight\"><strong>allow_url_fopen:</strong> Your PHP configuration has allow_url_fopen disabled.  <em><?php echo $app_name; ?> will not work here.</em></li>\n\t\t\t\t\t\t\t\t<?php endif; ?>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t<?php else: ?>\n\t\t\t\t\t\t\t\t<li class=\"highlight\"><strong>PCRE:</strong> Your PHP installation doesn't support Perl-Compatible Regular Expressions.  <em><?php echo $app_name; ?> will not work here.</em></li>\n\t\t\t\t\t\t\t<?php endif; ?>\n\t\t\t\t\t\t<?php else: ?>\n\t\t\t\t\t\t\t<li class=\"highlight\"><strong>XML:</strong> Your PHP installation doesn't support XML parsing.  <em><?php echo $app_name; ?> will not work here.</em></li>\n\t\t\t\t\t\t<?php endif; ?>\n\t\t\t\t\t<?php else: ?>\n\t\t\t\t\t\t<li class=\"highlight\"><strong>PHP:</strong> You are running an unsupported version of PHP.  <em><?php echo $app_name; ?> will not work here.</em></li>\n\t\t\t\t\t<?php endif; ?>\n\t\t\t\t<?php endif; ?>\n\t\t\t</ol>\n\t\t</div>\n\n\t\t<div class=\"chunk\">\n\t\t\t<?php if ($php_ok && $xml_ok && $pcre_ok && $mbstring_ok && $iconv_ok && $filter_ok && $allow_url_fopen_ok) { ?>\n\t\t\t\t<h3>Bottom Line: Yes, you can!</h3>\n\t\t\t\t<p><em class=\"success\">Your webhost has its act together!</em></p>\n\t\t\t\t<p>You can download the latest version of <?php echo $app_name; ?> from <a href=\"http://fivefilters.org/content-only/#download\">FiveFilters.org</a>.</p>\n\t\t\t\t<p><strong>Note</strong>: Passing this test does not guarantee that <?php echo $app_name; ?> will run on your webhost &mdash; it only ensures that the basic requirements have been addressed. If you experience any problems, please let us know.</p>\n\t\t\t<?php } else if ($php_ok && $xml_ok && $pcre_ok && $mbstring_ok && $allow_url_fopen_ok && $filter_ok) { ?>\n\t\t\t\t<h3>Bottom Line: Yes, you can!</h3>\n\t\t\t\t<p><em>For most feeds, it'll run with no problems.</em> There are certain languages that you might have a hard time with though.</p>\n\t\t\t\t<p>You can download the latest version of <?php echo $app_name; ?> from <a href=\"http://fivefilters.org/content-only/#download\">FiveFilters.org</a>.</p>\n\t\t\t\t<p><strong>Note</strong>: Passing this test does not guarantee that <?php echo $app_name; ?> will run on your webhost &mdash; it only ensures that the basic requirements have been addressed. If you experience any problems, please let us know.</p>\n\t\t\t<?php } else { ?>\n\t\t\t\t<h3>Bottom Line: We're sorry…</h3>\n\t\t\t\t<p><em>Your webhost does not support the minimum requirements for <?php echo $app_name; ?>.</em>  It may be a good idea to contact your webhost and point them to the results of this test. They may be able to enable/install the required components.</p> <p>Alternatively, you can try one of our <a href=\"http://help.fivefilters.org/customer/portal/articles/1143210-hosting\">recommended hosts</a>.</p>\n\t\t\t<?php } ?>\n\t\t</div>\n\n\t\t<div class=\"chunk\">\n\t\t\t<h3>Further info</h3>\n\t\t\t<h4>HTTP module</h4>\n\t\t\t<p>Full-Text RSS can make use of <code>HttpRequestPool</code> or <code>curl_multi</code> to make parallel HTTP requests when processing feeds. If neither are available, it will make sequential requests using <code>file_get_contents</code>.</p>\n\t\t\t<?php \n\t\t\t$http_type = 'file_get_contents';\n\t\t\tif (extension_loaded('http') && class_exists('HttpRequestPool')) {\n\t\t\t\t$http_type = 'HttpRequestPool';\n\t\t\t} elseif ($curl_ok && function_exists('curl_multi_init')) {\n\t\t\t\t$http_type = 'curl_multi';\n\t\t\t}\n\t\t\t?>\n\t\t\t<p class=\"highlight\"><strong><?php echo $http_type; ?></strong> will be used on this server.</p>\n\t\t\t\n\t\t\t<h4>Alternative PHP Cache (APC)</h4>\n\t\t\t<p>Full-Text RSS can make use of APC's memory cache to store site config files (when requested for the first time). This is not required, but if available it may improve performance slightly by reducing disk access.</p>\n\t\t\t<?php\n\t\t\tif (function_exists('apc_add')) {\n\t\t\t\techo '<p class=\"highlight\"><strong>APC is available</strong> on this server.</p>';\n\t\t\t} else {\n\t\t\t\techo '<p class=\"highlight\">APC is not available on this server.</p>';\n\t\t\t}\n\t\t\t?>\n\t\t\t\n\t\t\t<h4>Language detection</h4>\n\t\t\t<p>Full-Text RSS can detect the language of each article processed. This occurs using <a href=\"http://pear.php.net/package/Text_LanguageDetect\">Text_LanguageDetect</a> or <a href=\"https://github.com/lstrojny/php-cld\">PHP-CLD</a> (if available).</p>\n\t\t\t<?php\n\t\t\tif (extension_loaded('cld') && (version_compare(PHP_VERSION, '5.3.0') >= 0)) {\n\t\t\t\techo '<p class=\"highlight\"><strong>PHP-CLD</strong> will be used on this server.</p>';\n\t\t\t} else {\n\t\t\t\techo '<p class=\"highlight\"><strong>Text_LanguageDetect</strong> will be used on this server.</p>';\n\t\t\t}\n\t\t\t?>\n\t\t\t\n\t\t\t<h4>Automatic site config updates</h4>\n\t\t\t<p>Full-Text RSS can be configured to update its site config files (which determine how content should be extracted for certain sites) by downloading the latest set from our GitHub repository. This functionaility is not required, and can be done manually. To configure this to occur automatically, you will need zip support enabled in PHP - we make use of the ZipArchive class.</p>\n\t\t\t<?php\n\t\t\tif (!class_exists('ZipArchive')) {\n\t\t\t\techo '<p class=\"highlight\">ZipArchive is not available on this server. To update the site config files you will need to do it manually by downloading the latest set and uploading it to your server.</p>';\n\t\t\t} else {\n\t\t\t\techo '<p class=\"highlight\"><strong>ZipArchive is available</strong> on this server.</p>';\n\t\t\t}\n\t\t\t?>\t\t\t\n\t\t</div>\n\t\t\n\t\t<div class=\"chunk\">\n\t\t\t<p class=\"footnote\">This compatibility test has been borrowed (and slightly adapted) from the one supplied by <a href=\"http://simplepie.org/\">SimplePie.org</a>. We have kept most of their checks intact as we use SimplePie in our application.</a></p>\n\t\t\t<p class=\"footnote\">Date: <?php echo date('Y-m-d'); ?></p>\n\t\t</div>\n\n\t</div>\n\n</div>\n\n</body>\n</html>"
  },
  {
    "path": "index.php",
    "content": "<?php\nrequire_once(dirname(__FILE__).'/config.php');\n// check for custom index.php (custom_index.php)\nif (!defined('_FF_FTR_INDEX')) {\n\tdefine('_FF_FTR_INDEX', true);\n\tif (file_exists(dirname(__FILE__).'/custom_index.php')) {\n\t\tinclude(dirname(__FILE__).'/custom_index.php');\n\t\texit;\n\t}\n}\n?><!DOCTYPE html>\n<html>\n  <head>\n    <title>Full-Text RSS Feeds | from fivefilters.org</title>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\t\n\t<meta name=\"robots\" content=\"noindex, follow\" />\n\t<link rel=\"stylesheet\" href=\"css/bootstrap.min.css\" type=\"text/css\" media=\"screen\" />\n\t<script type=\"text/javascript\" src=\"js/jquery.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"js/bootstrap-tooltip.js\"></script>\n\t<script type=\"text/javascript\" src=\"js/bootstrap-popover.js\"></script>\n\t<script type=\"text/javascript\" src=\"js/bootstrap-tab.js\"></script>\n\t<script type=\"text/javascript\">\n\tvar baseUrl = 'http://'+window.location.host+window.location.pathname.replace(/(\\/index\\.php|\\/)$/, '');\n\t$(document).ready(function() {\n\t\t// remove http scheme from urls before submitting\n\t\t$('#form').submit(function() {\n\t\t\t$('#url').val($('#url').val().replace(/^http:\\/\\//i, ''));\n\t\t\treturn true;\n\t\t});\n\t\t// popovers\n\t\t$('#url').popover({offset: 10, placement: 'left', trigger: 'focus', html: true});\n\t\t$('#key').popover({offset: 10, placement: 'left', trigger: 'focus', html: true});\n\t\t$('#max').popover({offset: 10, placement: 'left', trigger: 'focus', html: true});\n\t\t$('#links').popover({offset: 10, placement: 'left', trigger: 'focus', html: true});\n\t\t$('#exc').popover({offset: 10, placement: 'left', trigger: 'focus', html: true});\n\t\t// tooltips\n\t\t$('a[rel=tooltip]').tooltip();\n\t});\n\t</script>\n\t<style>\n\thtml, body { background-color: #eee; }\n\tbody { margin: 0; line-height: 1.4em; font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; }\n\tlabel, input, select, textarea { font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; }\n\tli { color: #404040; }\n\tli.active a { font-weight: bold; color: #666 !important; }\n\tform .controls { margin-left: 220px !important; }\n\tlabel { width: 200px !important; }\n\tfieldset legend { padding-left: 220px; line-height: 20px !important; margin-bottom: 10px !important;}\n\t.form-actions { padding-left: 220px !important; }\n\t.popover-inner { width: 205px; }\n\th1 { margin-bottom: 18px; }\n\t</style>\n  </head>\n  <body>\n\t<div class=\"container\" style=\"width: 800px; padding-bottom: 60px;\">\n\t<h1 style=\"padding-top: 5px;\">Full-Text RSS <?php echo _FF_FTR_VERSION; ?> <span style=\"font-size: .7em; font-weight: normal;\">&mdash; from <a href=\"http://fivefilters.org\">FiveFilters.org</a></span></h1>\n    <form method=\"get\" action=\"makefulltextfeed.php\" id=\"form\" class=\"form-horizontal\">\n\t<fieldset>\n\t\t<legend>Create full-text feed from feed or webpage URL</legend>\n\t\t<div class=\"control-group\">\n\t\t\t<label class=\"control-label\" for=\"url\">Enter URL</label>\n\t\t\t<div class=\"controls\"><input type=\"text\" id=\"url\" name=\"url\" style=\"width: 450px;\" title=\"URL\" data-content=\"Typically this is a URL for a partial feed which we transform into a full-text feed. But it can also be a standard web page URL, in which case we'll extract its content and return it in a 1-item feed.\" /></div>\n\t\t</div>\n\t</fieldset>\n\t<fieldset>\n\t<legend>Options</legend>\n\t<?php if (isset($options->api_keys) && !empty($options->api_keys)) { ?>\n\t<div class=\"control-group\">\n\t<label class=\"control-label\" for=\"key\">Access key</label>\n\t<div class=\"controls\">\n\t<input type=\"text\" id=\"key\" name=\"key\" class=\"input-medium\" <?php if ($options->key_required) echo 'required'; ?> title=\"Access Key\" data-content=\"<?php echo ($options->key_required) ? 'An access key is required to generate a feed' : 'If you have an access key, enter it here.'; ?>\" />\n\t</div>\n\t</div>\n\t<?php } ?>\n\t<div class=\"control-group\">\n\t<label class=\"control-label\" for=\"max\">Max items</label>\n\t<div class=\"controls\">\n\t<?php\n\t// echo '<select name=\"max\" id=\"max\" class=\"input-medium\">'\n\t// for ($i = 1; $i <= $options->max_entries; $i++) {\n\t//\tprintf(\"<option value=\\\"%s\\\"%s>%s</option>\\n\", $i, ($i==$options->default_entries) ? ' selected=\"selected\"' : '', $i);\n\t// } \n\t// echo '</select>';\n\tif (!empty($options->api_keys)) {\n\t\t$msg = 'Limit: '.$options->max_entries.' (with key: '.$options->max_entries_with_key.')';\n\t\t$msg_more = 'If you need more items, change <tt>max_entries</tt> (and <tt>max_entries_with_key</tt>) in config.';\n\t} else {\n\t\t$msg = 'Limit: '.$options->max_entries;\n\t\t$msg_more = 'If you need more items, change <tt>max_entries</tt> in config.';\n\t}\n\t?>\t\n\t<input type=\"text\" name=\"max\" id=\"max\" class=\"input-mini\" value=\"<?php echo $options->default_entries; ?>\" title=\"Feed item limit\" data-content=\"Set the maximum number of feed items we should process. The smaller the number, the faster the new feed is produced.<br /><br />If your URL refers to a standard web page, this will have no effect: you will only get 1 item.<br /><br /> <?php echo $msg_more; ?>\" />\n\t<span class=\"help-inline\" style=\"color: #888;\"><?php echo $msg; ?></span>\n\t</div>\n\t</div>\n\t<div class=\"control-group\">\n\t<label class=\"control-label\" for=\"links\">Links</label>\n\t<div class=\"controls\">\n\t<select name=\"links\" id=\"links\" class=\"input-medium\" title=\"Link handling\" data-content=\"By default, links within the content are preserved. Change this field if you'd like links removed, or included as footnotes.\">\n\t\t<option value=\"preserve\" selected=\"selected\">preserve</option>\n\t\t<option value=\"footnotes\">add to footnotes</option>\n\t\t<option value=\"remove\">remove</option>\n\t</select>\n\t</div>\n\t</div>\n\t<?php if ($options->exclude_items_on_fail === 'user') { ?>\n\t<div class=\"control-group\">\n\t<label class=\"control-label\" for=\"exc\">If extraction fails</label>\n\t<div class=\"controls\">\n\t<select name=\"exc\" id=\"exc\" title=\"Item handling when extraction fails\" data-content=\"If extraction fails, we can remove the item from the feed or keep it in.<br /><br />Keeping the item will keep the title, URL and original description (if any) found in the feed. In addition, we insert a message before the original description notifying you that extraction failed.\">\n\t\t<option value=\"\">keep item in feed</option>\n\t\t<option value=\"1\" selected=\"selected\">remove item from feed</option>\n\t</select>\n\t</div>\n\t</div>\n\t<?php } ?>\n\t\n\t<?php if ($options->summary === 'user') { ?>\n\t<div class=\"control-group\">\n\t<label class=\"control-label\" for=\"summary\">Include excerpt</label>\n\t<div class=\"controls\">\n\t<input type=\"checkbox\" name=\"summary\" value=\"1\" id=\"summary\" style=\"margin-top: 7px;\" />\n\t</div>\n\t</div>\n\t<?php } ?>\n\n\t<div class=\"control-group\" style=\"margin-top: -15px;\">\n\t<label class=\"control-label\" for=\"json\">JSON output</label>\n\t<div class=\"controls\">\n\t<input type=\"checkbox\" name=\"format\" value=\"json\" id=\"json\" style=\"margin-top: 7px;\" />\n\t</div>\n\t</div>\n\t\n\t<div class=\"control-group\" style=\"margin-top: -15px;\">\n\t<label class=\"control-label\" for=\"debug\">Debug</label>\n\t<div class=\"controls\">\n\t<input type=\"checkbox\" name=\"debug\" value=\"1\" id=\"debug\" style=\"margin-top: 7px;\" />\n\t</div>\n\t</div>\t\n\t\n\t</fieldset>\n\t<div class=\"form-actions\">\n\t\t<input type=\"submit\" id=\"sudbmit\" name=\"submit\" value=\"Create Feed\" class=\"btn btn-primary\" />\n\t</div>\n\t</form>\n\t\n\t\n\t<ul class=\"nav nav-tabs\">\n\t<li class=\"active\"><a href=\"#start\" data-toggle=\"tab\">Getting Started</a></li>\n\t<li><a href=\"#general\" data-toggle=\"tab\">General Info</a></li>\n\t<li><a href=\"#updates\" data-toggle=\"tab\">Updates</a></li>\n\t<li><a href=\"#license\" data-toggle=\"tab\">License</a></li>\n\t</ul>\n\t\n\t<div class=\"tab-content\">\n\t\n\t<!-- GETTING STARTED TAB -->\n\t\n\t<div class=\"active tab-pane\" id=\"start\">\n\t\n\t<h3>Quick start</h3>\n\t<ol>\n\t\t<li><a href=\"ftr_compatibility_test.php\">Check server compatibility</a> to make sure this server meets the requirements</li>\n\t\t<li>Enter a feed or article URL in the form above and click 'Create Feed' <a href=\"http://help.fivefilters.org/customer/portal/articles/223127-suggested-feeds-and-articles\" rel=\"tooltip\" title=\"Need suggestions? We've got a number of feeds and articles you can try\" class=\"label\">?</a></li>\n\t\t<li>If the generated full-text feed looks okay, copy the URL from your browser's address bar and use it in your news reader or application</li>\n\t\t<li><strong>That's it!</strong> (Although see below if you'd like to customise further.)</li>\n\t</ol>\n\t\n\t<h3>Configure</h3>\n\t<p>In addition to the options above, Full-Text RSS comes with a configuration file which allows you to control how the application works. <a href=\"http://help.fivefilters.org/customer/portal/articles/223410-configure\">Find out more.</a></p>\n\t<p>Features include:</p>\n\t<ul>\n\t\t<li>Site patterns for better control over extraction (<a href=\"http://help.fivefilters.org/customer/portal/articles/223153-site-patterns\">more info</a>)</li>\n\t\t<li>Restrict access to those with an access key and/or to a pre-defined set of URLs</li>\n\t\t<li>Restrict the maximum number of feed items to be processed</li>\n\t\t<li>Prepend or append an HTML fragment to each feed item processed</li>\n\t\t<li>Caching</li>\t\t\n\t</ul>\n\t<p><?php if (!file_exists('custom_config.php')) { ?>To change the configuration, save a copy of <tt>config.php</tt> as <tt>custom_config.php</tt> and make any changes you like to it.<?php } else { ?>To change the configuration, edit <tt>custom_config.php</tt> and make any changes you like.<?php } ?></p>\n\n\t<h3>Manage and update site config files</h3>\n\t<p>For best results, we suggest you update the site config files bundled with Full-Text RSS.</p>\n\t<p>The easiest way to update these is via the <a href=\"admin/\">admin area</a>. (For advanced users, you'll also be able to edit and test the extraction rules contained in the site config files from the admin area.)</p>\n\n\t<h3>Customise this page</h3>\n\t<p>If everything works fine, feel free to modify this page by following the steps below:</p>\n\t<ol>\n\t\t<li>Save a copy of <tt>index.php</tt> as <tt>custom_index.php</tt></li>\n\t\t<li>Edit <tt>custom_index.php</tt></li>\n\t</ol>\n\t<p>Next time you load this page, it will automatically load custom_index.php instead.</p>\n\t\n\t<h3 id=\"support\">Support</h3>\n\t<p>Check our <a href=\"http://help.fivefilters.org\">help centre</a> if you need help. You can also email us at <a href=\"mailto:help@fivefilters.org\">help@fivefilters.org</a>.</p>\n\t\n\t<h3>Thank you!</h3>\n\t<p>Thanks for downloading and setting up Full-Text RSS. This software is developed and maintained by FiveFilters.org. If you find it useful, but have not purchased this from us, please consider supporting us by purchasing from <a href=\"http://fivefilters.org/content-only/\">FiveFilters.org</a>.</p>\n\n\t</div>\n\n\t<!-- GENERAL TAB -->\n\t\n\t<div id=\"general\" class=\"tab-pane\">\n\t\n\t<h3>About</h3>\n\t<p>This is a free software project to enable article extraction from web pages. It can extract content from a standard HTML page and return a 1-item feed or it can transform an existing feed into a full-text feed. It is being developed as part of the <a href=\"http://fivefilters.org\">Five Filters</a> project to promote independent, non-corporate media.</p>\n\n\t<h3>Bookmarklet</h3>\n\t<p>Rather than copying and pasting URLs into this form, you can add the bookmarklet on this page to your browser. Simply drag the link below to your browser's bookmarks toolbar.\n\tThen whenever you'd like a full-text feed, click the bookmarklet.</p>\n\t<p>Drag this: \n\t<script type=\"text/javascript\">\n\tdocument.write('<a class=\"btn info\" style=\"cursor: move;\" onclick=\"alert(\\'drag to bookmarks toolbar\\'); return false;\" href=\"javascript:location.href=\\''+baseUrl+'/makefulltextfeed.php?url=\\'+encodeURIComponent(document.location.href);\">Full-Text RSS</a>');\n\t</script>\n\t<p>Note: This uses the default options and does not include your access key (if configured).</p>\t\n\t\n\t<h3>Free Software</h3>\n\t<p>Note: 'Free' as in 'free speech' (see the <a href=\"https://www.gnu.org/philosophy/free-sw.html\">free software definition</a>)</p>\n\t\n\t<p>If you're the owner of this site and you plan to offer this service to others through your hosted copy, please keep a download link so users can grab a copy of the code if they \n\twant it (you can either offer a free download yourself, or link to the purchase option on fivefilters.org to support us).</p>\n\t\n\t<p>For full details, please refer to the <a href=\"http://www.gnu.org/licenses/agpl-3.0.html\" title=\"AGPLv3\">license</a>.</p>\n\t\n\t<p>If you're not the owner of this site (ie. you're not hosting this yourself), you do not have to rely on an external service if you don't want to. You can <a href=\"http://fivefilters.org/content-only/#download\">download your own copy</a> of Full-Text RSS under the AGPL license.</p>\n\t\n\t<h3 id=\"api\">URL Construction</h3>\n\t<p>To extract content from a web page or to transform an existing partial feed to full text, pass the URL (<a href=\"http://meyerweb.com/eric/tools/dencoder/\">encoded</a>) in the querystring to the following URL:</p>\n\t<ul>\n\t\t<li style=\"font-family: monospace;\"><script type=\"text/javascript\">document.write(baseUrl);</script>/makefulltextfeed.php?url=<strong>[url]</strong></li>\n\t</ul>\n\t\n\t<p>All the parameters in the form above can be passed in this way. Examine the URL in the address bar after you click 'Create Feed' to see the values.</p>\n\t\n\t<h3>Software Components</h3>\n\t<p>Full-Text RSS is written in PHP and relies on the following <strong>primary</strong> components:</p>\n\t<ul>\n\t\t<li><a href=\"http://www.keyvan.net/2010/08/php-readability/\">PHP Readability</a></li>\n\t\t<li><a href=\"http://simplepie.org/\">SimplePie</a></li>\n\t\t<li>FeedWriter</li>\n\t\t<li>Humble HTTP Agent</li>\n\t</ul>\n\t<p>Depending on your configuration, these <strong>secondary</strong> components may also be used:</p> \n\t<ul>\n\t\t<li><a href=\"http://code.google.com/p/html5lib/\">html5lib</a></li>\n\t\t<li><a href=\"http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/\">htmLawed</a></li>\t\t\n\t\t<li><a href=\"http://code.google.com/p/rolling-curl/\">Rolling Curl</a></li>\n\t\t<li><a href=\"http://framework.zend.com/manual/en/zend.cache.introduction.html\">Zend Cache</a></li>\n\t\t<li><a href=\"http://pear.php.net/package/Text_LanguageDetect\">Text_LanguageDetect</a> or <a href=\"https://github.com/lstrojny/php-cld\">PHP-CLD</a> if available</li>\n\t</ul>\n\n\t<h3>System Requirements</h3>\n\t\n\t<p>PHP 5.2 or above is required. A simple shared web hosting account will work fine.\n\tThe code has been tested on Windows and Linux using the Apache web server. If you're a Windows user, you can try it on your own machine using <a href=\"http://www.wampserver.com/en/index.php\">WampServer</a>. It has also been reported as working under IIS, but we have not tested this ourselves.</p>\n\t\n\t<h3 id=\"download\">Download</h3>\n\t<p>Download from <a href=\"http://fivefilters.org/content-only/#download\">fivefilters.org</a> &mdash; old versions are available in our <a href=\"http://code.fivefilters.org\">code repository</a>.</p>\n\n\t</div>\n\t\n\t<!-- UPDATES TAB -->\n\t<div id=\"updates\" class=\"tab-pane\">\n\t<?php \n\t$site_config_version_file = dirname(__FILE__).'/site_config/standard/version.txt';\n\tif (file_exists($site_config_version_file)) {\n\t\t$site_config_version = file_get_contents($site_config_version_file);\n\t}\n\t?>\n\t<p>Your version of Full-Text RSS: <strong><?php echo _FF_FTR_VERSION; ?></strong><br />\n\tYour version of Site Patterns: <strong><?php echo (isset($site_config_version) ? $site_config_version : 'Unknown'); ?></strong>\n\t</p>\n\t<p>To see if you have the latest versions, <a href=\"http://fivefilters.org/content-only/latest_version.php?version=<?php echo urlencode(_FF_FTR_VERSION).'&site_config='.urlencode(@$site_config_version); ?>\">check for updates</a>.</p>\n\t<p>If you've purchased this from FiveFilters.org, you'll receive notification when we release a new version or update the site patterns.</p>\n\t</div>\t\n\t\n\t<!-- LICENSE TAB -->\n\t<div id=\"license\" class=\"tab-pane\">\n\t<p><a href=\"http://en.wikipedia.org/wiki/Affero_General_Public_License\" style=\"border-bottom: none;\"><img src=\"images/agplv3.png\" alt=\"AGPL logo\" /></a></p>\n\t<p>Full-Text RSS is licensed under the <a href=\"http://en.wikipedia.org/wiki/Affero_General_Public_License\">AGPL version 3</a> &mdash; more information about why we use this license can be found on <a href=\"http://fivefilters.org/content-only/http://fivefilters.org/content-only/#license\">FiveFilters.org</a></p> \n\t<p>The software components in this application are licensed as follows...</p>\n\t<ul>\n\t\t<li>PHP Readability: <a href=\"http://www.apache.org/licenses/LICENSE-2.0\">Apache License v2</a></li>\n\t\t<li>SimplePie: <a href=\"http://en.wikipedia.org/wiki/BSD_license\">BSD</a></li>\n\t\t<li>FeedWriter: <a href=\"http://www.gnu.org/licenses/old-licenses/gpl-2.0.html\">GPL v2</a></li>\n\t\t<li>Humble HTTP Agent: <a href=\"http://en.wikipedia.org/wiki/Affero_General_Public_License\">AGPL v3</a></li>\n\t\t<li>Zend: <a href=\"http://framework.zend.com/license/new-bsd\">New BSD</a></li>\n\t\t<li>Rolling Curl: <a href=\"http://www.apache.org/licenses/LICENSE-2.0\">Apache License v2</a></li>\n\t\t<li>html5lib: <a href=\"http://opensource.org/licenses/mit-license.php\">MIT</a></li>\n\t\t<li>htmLawed: <a href=\"http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License\">LGPL v3</a></li>\n\t\t<li>Text_LanguageDetect: <a href=\"http://en.wikipedia.org/wiki/BSD_license\">BSD</a></li>\t\t\n\t</ul>\n\t</div>\n\t\n\t</div>\n  </body>\n</html>"
  },
  {
    "path": "js/bootstrap-popover.js",
    "content": "/* ===========================================================\n * bootstrap-popover.js v2.0.3\n * http://twitter.github.com/bootstrap/javascript.html#popovers\n * ===========================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * =========================================================== */\n\n\n!function ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* POPOVER PUBLIC CLASS DEFINITION\n  * =============================== */\n\n  var Popover = function ( element, options ) {\n    this.init('popover', element, options)\n  }\n\n\n  /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js\n     ========================================== */\n\n  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {\n\n    constructor: Popover\n\n  , setContent: function () {\n      var $tip = this.tip()\n        , title = this.getTitle()\n        , content = this.getContent()\n\n      $tip.find('.popover-title')[this.isHTML(title) ? 'html' : 'text'](title)\n      $tip.find('.popover-content > *')[this.isHTML(content) ? 'html' : 'text'](content)\n\n      $tip.removeClass('fade top bottom left right in')\n    }\n\n  , hasContent: function () {\n      return this.getTitle() || this.getContent()\n    }\n\n  , getContent: function () {\n      var content\n        , $e = this.$element\n        , o = this.options\n\n      content = $e.attr('data-content')\n        || (typeof o.content == 'function' ? o.content.call($e[0]) :  o.content)\n\n      return content\n    }\n\n  , tip: function () {\n      if (!this.$tip) {\n        this.$tip = $(this.options.template)\n      }\n      return this.$tip\n    }\n\n  })\n\n\n /* POPOVER PLUGIN DEFINITION\n  * ======================= */\n\n  $.fn.popover = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('popover')\n        , options = typeof option == 'object' && option\n      if (!data) $this.data('popover', (data = new Popover(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.popover.Constructor = Popover\n\n  $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {\n    placement: 'right'\n  , content: ''\n  , template: '<div class=\"popover\"><div class=\"arrow\"></div><div class=\"popover-inner\"><h3 class=\"popover-title\"></h3><div class=\"popover-content\"><p></p></div></div></div>'\n  })\n\n}(window.jQuery);"
  },
  {
    "path": "js/bootstrap-tab.js",
    "content": "/* ========================================================\n * bootstrap-tab.js v2.0.3\n * http://twitter.github.com/bootstrap/javascript.html#tabs\n * ========================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================== */\n\n\n!function ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* TAB CLASS DEFINITION\n  * ==================== */\n\n  var Tab = function ( element ) {\n    this.element = $(element)\n  }\n\n  Tab.prototype = {\n\n    constructor: Tab\n\n  , show: function () {\n      var $this = this.element\n        , $ul = $this.closest('ul:not(.dropdown-menu)')\n        , selector = $this.attr('data-target')\n        , previous\n        , $target\n        , e\n\n      if (!selector) {\n        selector = $this.attr('href')\n        selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n      }\n\n      if ( $this.parent('li').hasClass('active') ) return\n\n      previous = $ul.find('.active a').last()[0]\n\n      e = $.Event('show', {\n        relatedTarget: previous\n      })\n\n      $this.trigger(e)\n\n      if (e.isDefaultPrevented()) return\n\n      $target = $(selector)\n\n      this.activate($this.parent('li'), $ul)\n      this.activate($target, $target.parent(), function () {\n        $this.trigger({\n          type: 'shown'\n        , relatedTarget: previous\n        })\n      })\n    }\n\n  , activate: function ( element, container, callback) {\n      var $active = container.find('> .active')\n        , transition = callback\n            && $.support.transition\n            && $active.hasClass('fade')\n\n      function next() {\n        $active\n          .removeClass('active')\n          .find('> .dropdown-menu > .active')\n          .removeClass('active')\n\n        element.addClass('active')\n\n        if (transition) {\n          element[0].offsetWidth // reflow for transition\n          element.addClass('in')\n        } else {\n          element.removeClass('fade')\n        }\n\n        if ( element.parent('.dropdown-menu') ) {\n          element.closest('li.dropdown').addClass('active')\n        }\n\n        callback && callback()\n      }\n\n      transition ?\n        $active.one($.support.transition.end, next) :\n        next()\n\n      $active.removeClass('in')\n    }\n  }\n\n\n /* TAB PLUGIN DEFINITION\n  * ===================== */\n\n  $.fn.tab = function ( option ) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('tab')\n      if (!data) $this.data('tab', (data = new Tab(this)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tab.Constructor = Tab\n\n\n /* TAB DATA-API\n  * ============ */\n\n  $(function () {\n    $('body').on('click.tab.data-api', '[data-toggle=\"tab\"], [data-toggle=\"pill\"]', function (e) {\n      e.preventDefault()\n      $(this).tab('show')\n    })\n  })\n\n}(window.jQuery);"
  },
  {
    "path": "js/bootstrap-tooltip.js",
    "content": "/* ===========================================================\n * bootstrap-tooltip.js v2.0.3\n * http://twitter.github.com/bootstrap/javascript.html#tooltips\n * Inspired by the original jQuery.tipsy by Jason Frame\n * ===========================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ========================================================== */\n\n\n!function ($) {\n\n  \"use strict\"; // jshint ;_;\n\n\n /* TOOLTIP PUBLIC CLASS DEFINITION\n  * =============================== */\n\n  var Tooltip = function (element, options) {\n    this.init('tooltip', element, options)\n  }\n\n  Tooltip.prototype = {\n\n    constructor: Tooltip\n\n  , init: function (type, element, options) {\n      var eventIn\n        , eventOut\n\n      this.type = type\n      this.$element = $(element)\n      this.options = this.getOptions(options)\n      this.enabled = true\n\n      if (this.options.trigger != 'manual') {\n        eventIn  = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'\n        eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'\n        this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this))\n        this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this))\n      }\n\n      this.options.selector ?\n        (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :\n        this.fixTitle()\n    }\n\n  , getOptions: function (options) {\n      options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())\n\n      if (options.delay && typeof options.delay == 'number') {\n        options.delay = {\n          show: options.delay\n        , hide: options.delay\n        }\n      }\n\n      return options\n    }\n\n  , enter: function (e) {\n      var self = $(e.currentTarget)[this.type](this._options).data(this.type)\n\n      if (!self.options.delay || !self.options.delay.show) return self.show()\n\n      clearTimeout(this.timeout)\n      self.hoverState = 'in'\n      this.timeout = setTimeout(function() {\n        if (self.hoverState == 'in') self.show()\n      }, self.options.delay.show)\n    }\n\n  , leave: function (e) {\n      var self = $(e.currentTarget)[this.type](this._options).data(this.type)\n\n      if (!self.options.delay || !self.options.delay.hide) return self.hide()\n\n      clearTimeout(this.timeout)\n      self.hoverState = 'out'\n      this.timeout = setTimeout(function() {\n        if (self.hoverState == 'out') self.hide()\n      }, self.options.delay.hide)\n    }\n\n  , show: function () {\n      var $tip\n        , inside\n        , pos\n        , actualWidth\n        , actualHeight\n        , placement\n        , tp\n\n      if (this.hasContent() && this.enabled) {\n        $tip = this.tip()\n        this.setContent()\n\n        if (this.options.animation) {\n          $tip.addClass('fade')\n        }\n\n        placement = typeof this.options.placement == 'function' ?\n          this.options.placement.call(this, $tip[0], this.$element[0]) :\n          this.options.placement\n\n        inside = /in/.test(placement)\n\n        $tip\n          .remove()\n          .css({ top: 0, left: 0, display: 'block' })\n          .appendTo(inside ? this.$element : document.body)\n\n        pos = this.getPosition(inside)\n\n        actualWidth = $tip[0].offsetWidth\n        actualHeight = $tip[0].offsetHeight\n\n        switch (inside ? placement.split(' ')[1] : placement) {\n          case 'bottom':\n            tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}\n            break\n          case 'top':\n            tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}\n            break\n          case 'left':\n            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}\n            break\n          case 'right':\n            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}\n            break\n        }\n\n        $tip\n          .css(tp)\n          .addClass(placement)\n          .addClass('in')\n      }\n    }\n\n  , isHTML: function(text) {\n      // html string detection logic adapted from jQuery\n      return typeof text != 'string'\n        || ( text.charAt(0) === \"<\"\n          && text.charAt( text.length - 1 ) === \">\"\n          && text.length >= 3\n        ) || /^(?:[^<]*<[\\w\\W]+>[^>]*$)/.exec(text)\n    }\n\n  , setContent: function () {\n      var $tip = this.tip()\n        , title = this.getTitle()\n\n      $tip.find('.tooltip-inner')[this.isHTML(title) ? 'html' : 'text'](title)\n      $tip.removeClass('fade in top bottom left right')\n    }\n\n  , hide: function () {\n      var that = this\n        , $tip = this.tip()\n\n      $tip.removeClass('in')\n\n      function removeWithAnimation() {\n        var timeout = setTimeout(function () {\n          $tip.off($.support.transition.end).remove()\n        }, 500)\n\n        $tip.one($.support.transition.end, function () {\n          clearTimeout(timeout)\n          $tip.remove()\n        })\n      }\n\n      $.support.transition && this.$tip.hasClass('fade') ?\n        removeWithAnimation() :\n        $tip.remove()\n    }\n\n  , fixTitle: function () {\n      var $e = this.$element\n      if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {\n        $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')\n      }\n    }\n\n  , hasContent: function () {\n      return this.getTitle()\n    }\n\n  , getPosition: function (inside) {\n      return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {\n        width: this.$element[0].offsetWidth\n      , height: this.$element[0].offsetHeight\n      })\n    }\n\n  , getTitle: function () {\n      var title\n        , $e = this.$element\n        , o = this.options\n\n      title = $e.attr('data-original-title')\n        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)\n\n      return title\n    }\n\n  , tip: function () {\n      return this.$tip = this.$tip || $(this.options.template)\n    }\n\n  , validate: function () {\n      if (!this.$element[0].parentNode) {\n        this.hide()\n        this.$element = null\n        this.options = null\n      }\n    }\n\n  , enable: function () {\n      this.enabled = true\n    }\n\n  , disable: function () {\n      this.enabled = false\n    }\n\n  , toggleEnabled: function () {\n      this.enabled = !this.enabled\n    }\n\n  , toggle: function () {\n      this[this.tip().hasClass('in') ? 'hide' : 'show']()\n    }\n\n  }\n\n\n /* TOOLTIP PLUGIN DEFINITION\n  * ========================= */\n\n  $.fn.tooltip = function ( option ) {\n    return this.each(function () {\n      var $this = $(this)\n        , data = $this.data('tooltip')\n        , options = typeof option == 'object' && option\n      if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tooltip.Constructor = Tooltip\n\n  $.fn.tooltip.defaults = {\n    animation: true\n  , placement: 'top'\n  , selector: false\n  , template: '<div class=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>'\n  , trigger: 'hover'\n  , title: ''\n  , delay: 0\n  }\n\n}(window.jQuery);"
  },
  {
    "path": "libraries/Zend/Cache/Backend/ExtendedInterface.php",
    "content": "<?php\n/**\n * Zend Framework\n *\n * LICENSE\n *\n * This source file is subject to the new BSD license that is bundled\n * with this package in the file LICENSE.txt.\n * It is also available through the world-wide-web at this URL:\n * http://framework.zend.com/license/new-bsd\n * If you did not receive a copy of the license and are unable to\n * obtain it through the world-wide-web, please send an email\n * to license@zend.com so we can send you a copy immediately.\n *\n * @category   Zend\n * @package    Zend_Cache\n * @subpackage Zend_Cache_Backend\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n * @version    $Id: ExtendedInterface.php 24593 2012-01-05 20:35:02Z matthew $\n */\n\n/**\n * @see Zend_Cache_Backend_Interface\n */\n//require_once 'Zend/Cache/Backend/Interface.php';\nrequire_once dirname(__FILE__).'/Interface.php';\n\n/**\n * @package    Zend_Cache\n * @subpackage Zend_Cache_Backend\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n */\ninterface Zend_Cache_Backend_ExtendedInterface extends Zend_Cache_Backend_Interface\n{\n\n    /**\n     * Return an array of stored cache ids\n     *\n     * @return array array of stored cache ids (string)\n     */\n    public function getIds();\n\n    /**\n     * Return an array of stored tags\n     *\n     * @return array array of stored tags (string)\n     */\n    public function getTags();\n\n    /**\n     * Return an array of stored cache ids which match given tags\n     *\n     * In case of multiple tags, a logical AND is made between tags\n     *\n     * @param array $tags array of tags\n     * @return array array of matching cache ids (string)\n     */\n    public function getIdsMatchingTags($tags = array());\n\n    /**\n     * Return an array of stored cache ids which don't match given tags\n     *\n     * In case of multiple tags, a logical OR is made between tags\n     *\n     * @param array $tags array of tags\n     * @return array array of not matching cache ids (string)\n     */\n    public function getIdsNotMatchingTags($tags = array());\n\n    /**\n     * Return an array of stored cache ids which match any given tags\n     *\n     * In case of multiple tags, a logical AND is made between tags\n     *\n     * @param array $tags array of tags\n     * @return array array of any matching cache ids (string)\n     */\n    public function getIdsMatchingAnyTags($tags = array());\n\n    /**\n     * Return the filling percentage of the backend storage\n     *\n     * @return int integer between 0 and 100\n     */\n    public function getFillingPercentage();\n\n    /**\n     * Return an array of metadatas for the given cache id\n     *\n     * The array must include these keys :\n     * - expire : the expire timestamp\n     * - tags : a string array of tags\n     * - mtime : timestamp of last modification time\n     *\n     * @param string $id cache id\n     * @return array array of metadatas (false if the cache id is not found)\n     */\n    public function getMetadatas($id);\n\n    /**\n     * Give (if possible) an extra lifetime to the given cache id\n     *\n     * @param string $id cache id\n     * @param int $extraLifetime\n     * @return boolean true if ok\n     */\n    public function touch($id, $extraLifetime);\n\n    /**\n     * Return an associative array of capabilities (booleans) of the backend\n     *\n     * The array must include these keys :\n     * - automatic_cleaning (is automating cleaning necessary)\n     * - tags (are tags supported)\n     * - expired_read (is it possible to read expired cache records\n     *                 (for doNotTestCacheValidity option for example))\n     * - priority does the backend deal with priority when saving\n     * - infinite_lifetime (is infinite lifetime can work with this backend)\n     * - get_list (is it possible to get the list of cache ids and the complete list of tags)\n     *\n     * @return array associative of with capabilities\n     */\n    public function getCapabilities();\n\n}\n"
  },
  {
    "path": "libraries/Zend/Cache/Backend/File.php",
    "content": "<?php\n/**\n * Zend Framework\n *\n * LICENSE\n *\n * This source file is subject to the new BSD license that is bundled\n * with this package in the file LICENSE.txt.\n * It is also available through the world-wide-web at this URL:\n * http://framework.zend.com/license/new-bsd\n * If you did not receive a copy of the license and are unable to\n * obtain it through the world-wide-web, please send an email\n * to license@zend.com so we can send you a copy immediately.\n *\n * @category   Zend\n * @package    Zend_Cache\n * @subpackage Zend_Cache_Backend\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n * @version    $Id: File.php 24844 2012-05-31 19:01:36Z rob $\n */\n\n/**\n * @see Zend_Cache_Backend_Interface\n */\n//require_once 'Zend/Cache/Backend/ExtendedInterface.php';\nrequire_once dirname(__FILE__).'/ExtendedInterface.php';\n\n/**\n * @see Zend_Cache_Backend\n */\n//require_once 'Zend/Cache/Backend.php';\nrequire_once realpath(dirname(__FILE__).'/..').DIRECTORY_SEPARATOR.'Backend.php';\n\n\n\n/**\n * @package    Zend_Cache\n * @subpackage Zend_Cache_Backend\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n */\nclass Zend_Cache_Backend_File extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface\n{\n    /**\n     * Available options\n     *\n     * =====> (string) cache_dir :\n     * - Directory where to put the cache files\n     *\n     * =====> (boolean) file_locking :\n     * - Enable / disable file_locking\n     * - Can avoid cache corruption under bad circumstances but it doesn't work on multithread\n     * webservers and on NFS filesystems for example\n     *\n     * =====> (boolean) read_control :\n     * - Enable / disable read control\n     * - If enabled, a control key is embeded in cache file and this key is compared with the one\n     * calculated after the reading.\n     *\n     * =====> (string) read_control_type :\n     * - Type of read control (only if read control is enabled). Available values are :\n     *   'md5' for a md5 hash control (best but slowest)\n     *   'crc32' for a crc32 hash control (lightly less safe but faster, better choice)\n     *   'adler32' for an adler32 hash control (excellent choice too, faster than crc32)\n     *   'strlen' for a length only test (fastest)\n     *\n     * =====> (int) hashed_directory_level :\n     * - Hashed directory level\n     * - Set the hashed directory structure level. 0 means \"no hashed directory\n     * structure\", 1 means \"one level of directory\", 2 means \"two levels\"...\n     * This option can speed up the cache only when you have many thousands of\n     * cache file. Only specific benchs can help you to choose the perfect value\n     * for you. Maybe, 1 or 2 is a good start.\n     *\n     * =====> (int) hashed_directory_umask :\n     * - deprecated\n     * - Permissions for hashed directory structure\n     *\n     * =====> (int) hashed_directory_perm :\n     * - Permissions for hashed directory structure\n     *\n     * =====> (string) file_name_prefix :\n     * - prefix for cache files\n     * - be really carefull with this option because a too generic value in a system cache dir\n     *   (like /tmp) can cause disasters when cleaning the cache\n     *\n     * =====> (int) cache_file_umask :\n     * - deprecated\n     * - Permissions for cache files\n     *\n     * =====> (int) cache_file_perm :\n     * - Permissions for cache files\n     *\n     * =====> (int) metatadatas_array_max_size :\n     * - max size for the metadatas array (don't change this value unless you\n     *   know what you are doing)\n     *\n     * @var array available options\n     */\n    protected $_options = array(\n        'cache_dir' => null,\n        'file_locking' => true,\n        'read_control' => true,\n        'read_control_type' => 'crc32',\n        'hashed_directory_level' => 0,\n        'hashed_directory_perm' => 0700,\n        'file_name_prefix' => 'zend_cache',\n        'cache_file_perm' => 0600,\n        'metadatas_array_max_size' => 100\n    );\n\n    /**\n     * Array of metadatas (each item is an associative array)\n     *\n     * @var array\n     */\n    protected $_metadatasArray = array();\n\n\n    /**\n     * Constructor\n     *\n     * @param  array $options associative array of options\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    public function __construct(array $options = array())\n    {\n        parent::__construct($options);\n        if ($this->_options['cache_dir'] !== null) { // particular case for this option\n            $this->setCacheDir($this->_options['cache_dir']);\n        } else {\n            $this->setCacheDir(self::getTmpDir() . DIRECTORY_SEPARATOR, false);\n        }\n        if (isset($this->_options['file_name_prefix'])) { // particular case for this option\n            if (!preg_match('~^[a-zA-Z0-9_]+$~D', $this->_options['file_name_prefix'])) {\n                Zend_Cache::throwException('Invalid file_name_prefix : must use only [a-zA-Z0-9_]');\n            }\n        }\n        if ($this->_options['metadatas_array_max_size'] < 10) {\n            Zend_Cache::throwException('Invalid metadatas_array_max_size, must be > 10');\n        }\n\n        if (isset($options['hashed_directory_umask'])) {\n            // See #ZF-12047\n            trigger_error(\"'hashed_directory_umask' is deprecated -> please use 'hashed_directory_perm' instead\", E_USER_NOTICE);\n            if (!isset($options['hashed_directory_perm'])) {\n                $options['hashed_directory_perm'] = $options['hashed_directory_umask'];\n            }\n        }\n        if (isset($options['hashed_directory_perm']) && is_string($options['hashed_directory_perm'])) {\n            // See #ZF-4422\n            $this->_options['hashed_directory_perm'] = octdec($this->_options['hashed_directory_perm']);\n        }\n\n        if (isset($options['cache_file_umask'])) {\n            // See #ZF-12047\n            trigger_error(\"'cache_file_umask' is deprecated -> please use 'cache_file_perm' instead\", E_USER_NOTICE);\n            if (!isset($options['cache_file_perm'])) {\n                $options['cache_file_perm'] = $options['cache_file_umask'];\n            }\n        }\n        if (isset($options['cache_file_perm']) && is_string($options['cache_file_perm'])) {\n            // See #ZF-4422\n            $this->_options['cache_file_perm'] = octdec($this->_options['cache_file_perm']);\n        }\n    }\n\n    /**\n     * Set the cache_dir (particular case of setOption() method)\n     *\n     * @param  string  $value\n     * @param  boolean $trailingSeparator If true, add a trailing separator is necessary\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    public function setCacheDir($value, $trailingSeparator = true)\n    {\n        if (!is_dir($value)) {\n            Zend_Cache::throwException(sprintf('cache_dir \"%s\" must be a directory', $value));\n        }\n        if (!is_writable($value)) {\n            Zend_Cache::throwException(sprintf('cache_dir \"%s\" is not writable', $value));\n        }\n        if ($trailingSeparator) {\n            // add a trailing DIRECTORY_SEPARATOR if necessary\n            $value = rtrim(realpath($value), '\\\\/') . DIRECTORY_SEPARATOR;\n        }\n        $this->_options['cache_dir'] = $value;\n    }\n\n    /**\n     * Test if a cache is available for the given id and (if yes) return it (false else)\n     *\n     * @param string $id cache id\n     * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested\n     * @return string|false cached datas\n     */\n    public function load($id, $doNotTestCacheValidity = false)\n    {\n        if (!($this->_test($id, $doNotTestCacheValidity))) {\n            // The cache is not hit !\n            return false;\n        }\n        $metadatas = $this->_getMetadatas($id);\n        $file = $this->_file($id);\n        $data = $this->_fileGetContents($file);\n        if ($this->_options['read_control']) {\n            $hashData = $this->_hash($data, $this->_options['read_control_type']);\n            $hashControl = $metadatas['hash'];\n            if ($hashData != $hashControl) {\n                // Problem detected by the read control !\n                $this->_log('Zend_Cache_Backend_File::load() / read_control : stored hash and computed hash do not match');\n                $this->remove($id);\n                return false;\n            }\n        }\n        return $data;\n    }\n\n    /**\n     * Test if a cache is available or not (for the given id)\n     *\n     * @param string $id cache id\n     * @return mixed false (a cache is not available) or \"last modified\" timestamp (int) of the available cache record\n     */\n    public function test($id)\n    {\n        clearstatcache();\n        return $this->_test($id, false);\n    }\n\n    /**\n     * Save some string datas into a cache record\n     *\n     * Note : $data is always \"string\" (serialization is done by the\n     * core not by the backend)\n     *\n     * @param  string $data             Datas to cache\n     * @param  string $id               Cache id\n     * @param  array  $tags             Array of strings, the cache record will be tagged by each string entry\n     * @param  int    $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)\n     * @return boolean true if no problem\n     */\n    public function save($data, $id, $tags = array(), $specificLifetime = false)\n    {\n        clearstatcache();\n        $file = $this->_file($id);\n        $path = $this->_path($id);\n        if ($this->_options['hashed_directory_level'] > 0) {\n            if (!is_writable($path)) {\n                // maybe, we just have to build the directory structure\n                $this->_recursiveMkdirAndChmod($id);\n            }\n            if (!is_writable($path)) {\n                return false;\n            }\n        }\n        if ($this->_options['read_control']) {\n            $hash = $this->_hash($data, $this->_options['read_control_type']);\n        } else {\n            $hash = '';\n        }\n        $metadatas = array(\n            'hash' => $hash,\n            'mtime' => time(),\n            'expire' => $this->_expireTime($this->getLifetime($specificLifetime)),\n            'tags' => $tags\n        );\n        $res = $this->_setMetadatas($id, $metadatas);\n        if (!$res) {\n            $this->_log('Zend_Cache_Backend_File::save() / error on saving metadata');\n            return false;\n        }\n        $res = $this->_filePutContents($file, $data);\n        return $res;\n    }\n\n    /**\n     * Remove a cache record\n     *\n     * @param  string $id cache id\n     * @return boolean true if no problem\n     */\n    public function remove($id)\n    {\n        $file = $this->_file($id);\n        $boolRemove   = $this->_remove($file);\n        $boolMetadata = $this->_delMetadatas($id);\n        return $boolMetadata && $boolRemove;\n    }\n\n    /**\n     * Clean some cache records\n     *\n     * Available modes are :\n     *\n     * Zend_Cache::CLEANING_MODE_ALL (default)    => remove all cache entries ($tags is not used)\n     * Zend_Cache::CLEANING_MODE_OLD              => remove too old cache entries ($tags is not used)\n     * Zend_Cache::CLEANING_MODE_MATCHING_TAG     => remove cache entries matching all given tags\n     *                                               ($tags can be an array of strings or a single string)\n     * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}\n     *                                               ($tags can be an array of strings or a single string)\n     * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags\n     *                                               ($tags can be an array of strings or a single string)\n     *\n     * @param string $mode clean mode\n     * @param tags array $tags array of tags\n     * @return boolean true if no problem\n     */\n    public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())\n    {\n        // We use this protected method to hide the recursive stuff\n        clearstatcache();\n        return $this->_clean($this->_options['cache_dir'], $mode, $tags);\n    }\n\n    /**\n     * Return an array of stored cache ids\n     *\n     * @return array array of stored cache ids (string)\n     */\n    public function getIds()\n    {\n        return $this->_get($this->_options['cache_dir'], 'ids', array());\n    }\n\n    /**\n     * Return an array of stored tags\n     *\n     * @return array array of stored tags (string)\n     */\n    public function getTags()\n    {\n        return $this->_get($this->_options['cache_dir'], 'tags', array());\n    }\n\n    /**\n     * Return an array of stored cache ids which match given tags\n     *\n     * In case of multiple tags, a logical AND is made between tags\n     *\n     * @param array $tags array of tags\n     * @return array array of matching cache ids (string)\n     */\n    public function getIdsMatchingTags($tags = array())\n    {\n        return $this->_get($this->_options['cache_dir'], 'matching', $tags);\n    }\n\n    /**\n     * Return an array of stored cache ids which don't match given tags\n     *\n     * In case of multiple tags, a logical OR is made between tags\n     *\n     * @param array $tags array of tags\n     * @return array array of not matching cache ids (string)\n     */\n    public function getIdsNotMatchingTags($tags = array())\n    {\n        return $this->_get($this->_options['cache_dir'], 'notMatching', $tags);\n    }\n\n    /**\n     * Return an array of stored cache ids which match any given tags\n     *\n     * In case of multiple tags, a logical AND is made between tags\n     *\n     * @param array $tags array of tags\n     * @return array array of any matching cache ids (string)\n     */\n    public function getIdsMatchingAnyTags($tags = array())\n    {\n        return $this->_get($this->_options['cache_dir'], 'matchingAny', $tags);\n    }\n\n    /**\n     * Return the filling percentage of the backend storage\n     *\n     * @throws Zend_Cache_Exception\n     * @return int integer between 0 and 100\n     */\n    public function getFillingPercentage()\n    {\n        $free = disk_free_space($this->_options['cache_dir']);\n        $total = disk_total_space($this->_options['cache_dir']);\n        if ($total == 0) {\n            Zend_Cache::throwException('can\\'t get disk_total_space');\n        } else {\n            if ($free >= $total) {\n                return 100;\n            }\n            return ((int) (100. * ($total - $free) / $total));\n        }\n    }\n\n    /**\n     * Return an array of metadatas for the given cache id\n     *\n     * The array must include these keys :\n     * - expire : the expire timestamp\n     * - tags : a string array of tags\n     * - mtime : timestamp of last modification time\n     *\n     * @param string $id cache id\n     * @return array array of metadatas (false if the cache id is not found)\n     */\n    public function getMetadatas($id)\n    {\n        $metadatas = $this->_getMetadatas($id);\n        if (!$metadatas) {\n            return false;\n        }\n        if (time() > $metadatas['expire']) {\n            return false;\n        }\n        return array(\n            'expire' => $metadatas['expire'],\n            'tags' => $metadatas['tags'],\n            'mtime' => $metadatas['mtime']\n        );\n    }\n\n    /**\n     * Give (if possible) an extra lifetime to the given cache id\n     *\n     * @param string $id cache id\n     * @param int $extraLifetime\n     * @return boolean true if ok\n     */\n    public function touch($id, $extraLifetime)\n    {\n        $metadatas = $this->_getMetadatas($id);\n        if (!$metadatas) {\n            return false;\n        }\n        if (time() > $metadatas['expire']) {\n            return false;\n        }\n        $newMetadatas = array(\n            'hash' => $metadatas['hash'],\n            'mtime' => time(),\n            'expire' => $metadatas['expire'] + $extraLifetime,\n            'tags' => $metadatas['tags']\n        );\n        $res = $this->_setMetadatas($id, $newMetadatas);\n        if (!$res) {\n            return false;\n        }\n        return true;\n    }\n\n    /**\n     * Return an associative array of capabilities (booleans) of the backend\n     *\n     * The array must include these keys :\n     * - automatic_cleaning (is automating cleaning necessary)\n     * - tags (are tags supported)\n     * - expired_read (is it possible to read expired cache records\n     *                 (for doNotTestCacheValidity option for example))\n     * - priority does the backend deal with priority when saving\n     * - infinite_lifetime (is infinite lifetime can work with this backend)\n     * - get_list (is it possible to get the list of cache ids and the complete list of tags)\n     *\n     * @return array associative of with capabilities\n     */\n    public function getCapabilities()\n    {\n        return array(\n            'automatic_cleaning' => true,\n            'tags' => true,\n            'expired_read' => true,\n            'priority' => false,\n            'infinite_lifetime' => true,\n            'get_list' => true\n        );\n    }\n\n    /**\n     * PUBLIC METHOD FOR UNIT TESTING ONLY !\n     *\n     * Force a cache record to expire\n     *\n     * @param string $id cache id\n     */\n    public function ___expire($id)\n    {\n        $metadatas = $this->_getMetadatas($id);\n        if ($metadatas) {\n            $metadatas['expire'] = 1;\n            $this->_setMetadatas($id, $metadatas);\n        }\n    }\n\n    /**\n     * Get a metadatas record\n     *\n     * @param  string $id  Cache id\n     * @return array|false Associative array of metadatas\n     */\n    protected function _getMetadatas($id)\n    {\n        if (isset($this->_metadatasArray[$id])) {\n            return $this->_metadatasArray[$id];\n        } else {\n            $metadatas = $this->_loadMetadatas($id);\n            if (!$metadatas) {\n                return false;\n            }\n            $this->_setMetadatas($id, $metadatas, false);\n            return $metadatas;\n        }\n    }\n\n    /**\n     * Set a metadatas record\n     *\n     * @param  string $id        Cache id\n     * @param  array  $metadatas Associative array of metadatas\n     * @param  boolean $save     optional pass false to disable saving to file\n     * @return boolean True if no problem\n     */\n    protected function _setMetadatas($id, $metadatas, $save = true)\n    {\n        if (count($this->_metadatasArray) >= $this->_options['metadatas_array_max_size']) {\n            $n = (int) ($this->_options['metadatas_array_max_size'] / 10);\n            $this->_metadatasArray = array_slice($this->_metadatasArray, $n);\n        }\n        if ($save) {\n            $result = $this->_saveMetadatas($id, $metadatas);\n            if (!$result) {\n                return false;\n            }\n        }\n        $this->_metadatasArray[$id] = $metadatas;\n        return true;\n    }\n\n    /**\n     * Drop a metadata record\n     *\n     * @param  string $id Cache id\n     * @return boolean True if no problem\n     */\n    protected function _delMetadatas($id)\n    {\n        if (isset($this->_metadatasArray[$id])) {\n            unset($this->_metadatasArray[$id]);\n        }\n        $file = $this->_metadatasFile($id);\n        return $this->_remove($file);\n    }\n\n    /**\n     * Clear the metadatas array\n     *\n     * @return void\n     */\n    protected function _cleanMetadatas()\n    {\n        $this->_metadatasArray = array();\n    }\n\n    /**\n     * Load metadatas from disk\n     *\n     * @param  string $id Cache id\n     * @return array|false Metadatas associative array\n     */\n    protected function _loadMetadatas($id)\n    {\n        $file = $this->_metadatasFile($id);\n        $result = $this->_fileGetContents($file);\n        if (!$result) {\n            return false;\n        }\n        $tmp = @unserialize($result);\n        return $tmp;\n    }\n\n    /**\n     * Save metadatas to disk\n     *\n     * @param  string $id        Cache id\n     * @param  array  $metadatas Associative array\n     * @return boolean True if no problem\n     */\n    protected function _saveMetadatas($id, $metadatas)\n    {\n        $file = $this->_metadatasFile($id);\n        $result = $this->_filePutContents($file, serialize($metadatas));\n        if (!$result) {\n            return false;\n        }\n        return true;\n    }\n\n    /**\n     * Make and return a file name (with path) for metadatas\n     *\n     * @param  string $id Cache id\n     * @return string Metadatas file name (with path)\n     */\n    protected function _metadatasFile($id)\n    {\n        $path = $this->_path($id);\n        $fileName = $this->_idToFileName('internal-metadatas---' . $id);\n        return $path . $fileName;\n    }\n\n    /**\n     * Check if the given filename is a metadatas one\n     *\n     * @param  string $fileName File name\n     * @return boolean True if it's a metadatas one\n     */\n    protected function _isMetadatasFile($fileName)\n    {\n        $id = $this->_fileNameToId($fileName);\n        if (substr($id, 0, 21) == 'internal-metadatas---') {\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * Remove a file\n     *\n     * If we can't remove the file (because of locks or any problem), we will touch\n     * the file to invalidate it\n     *\n     * @param  string $file Complete file path\n     * @return boolean True if ok\n     */\n    protected function _remove($file)\n    {\n        if (!is_file($file)) {\n            return false;\n        }\n        if (!@unlink($file)) {\n            # we can't remove the file (because of locks or any problem)\n            $this->_log(\"Zend_Cache_Backend_File::_remove() : we can't remove $file\");\n            return false;\n        }\n        return true;\n    }\n\n    /**\n     * Clean some cache records (protected method used for recursive stuff)\n     *\n     * Available modes are :\n     * Zend_Cache::CLEANING_MODE_ALL (default)    => remove all cache entries ($tags is not used)\n     * Zend_Cache::CLEANING_MODE_OLD              => remove too old cache entries ($tags is not used)\n     * Zend_Cache::CLEANING_MODE_MATCHING_TAG     => remove cache entries matching all given tags\n     *                                               ($tags can be an array of strings or a single string)\n     * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}\n     *                                               ($tags can be an array of strings or a single string)\n     * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags\n     *                                               ($tags can be an array of strings or a single string)\n     *\n     * @param  string $dir  Directory to clean\n     * @param  string $mode Clean mode\n     * @param  array  $tags Array of tags\n     * @throws Zend_Cache_Exception\n     * @return boolean True if no problem\n     */\n    protected function _clean($dir, $mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())\n    {\n        if (!is_dir($dir)) {\n            return false;\n        }\n        $result = true;\n        $prefix = $this->_options['file_name_prefix'];\n        $glob = @glob($dir . $prefix . '--*');\n        if ($glob === false) {\n            // On some systems it is impossible to distinguish between empty match and an error.\n            return true;\n        }\n        foreach ($glob as $file)  {\n            if (is_file($file)) {\n                $fileName = basename($file);\n                if ($this->_isMetadatasFile($fileName)) {\n                    // in CLEANING_MODE_ALL, we drop anything, even remainings old metadatas files\n                    if ($mode != Zend_Cache::CLEANING_MODE_ALL) {\n                        continue;\n                    }\n                }\n                $id = $this->_fileNameToId($fileName);\n                $metadatas = $this->_getMetadatas($id);\n                if ($metadatas === FALSE) {\n                    $metadatas = array('expire' => 1, 'tags' => array());\n                }\n                switch ($mode) {\n                    case Zend_Cache::CLEANING_MODE_ALL:\n                        $res = $this->remove($id);\n                        if (!$res) {\n                            // in this case only, we accept a problem with the metadatas file drop\n                            $res = $this->_remove($file);\n                        }\n                        $result = $result && $res;\n                        break;\n                    case Zend_Cache::CLEANING_MODE_OLD:\n                        if (time() > $metadatas['expire']) {\n                            $result = $this->remove($id) && $result;\n                        }\n                        break;\n                    case Zend_Cache::CLEANING_MODE_MATCHING_TAG:\n                        $matching = true;\n                        foreach ($tags as $tag) {\n                            if (!in_array($tag, $metadatas['tags'])) {\n                                $matching = false;\n                                break;\n                            }\n                        }\n                        if ($matching) {\n                            $result = $this->remove($id) && $result;\n                        }\n                        break;\n                    case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:\n                        $matching = false;\n                        foreach ($tags as $tag) {\n                            if (in_array($tag, $metadatas['tags'])) {\n                                $matching = true;\n                                break;\n                            }\n                        }\n                        if (!$matching) {\n                            $result = $this->remove($id) && $result;\n                        }\n                        break;\n                    case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:\n                        $matching = false;\n                        foreach ($tags as $tag) {\n                            if (in_array($tag, $metadatas['tags'])) {\n                                $matching = true;\n                                break;\n                            }\n                        }\n                        if ($matching) {\n                            $result = $this->remove($id) && $result;\n                        }\n                        break;\n                    default:\n                        Zend_Cache::throwException('Invalid mode for clean() method');\n                        break;\n                }\n            }\n            if ((is_dir($file)) and ($this->_options['hashed_directory_level']>0)) {\n                // Recursive call\n                $result = $this->_clean($file . DIRECTORY_SEPARATOR, $mode, $tags) && $result;\n                if ($mode == Zend_Cache::CLEANING_MODE_ALL) {\n                    // we try to drop the structure too\n                    @rmdir($file);\n                }\n            }\n        }\n        return $result;\n    }\n\n    protected function _get($dir, $mode, $tags = array())\n    {\n        if (!is_dir($dir)) {\n            return false;\n        }\n        $result = array();\n        $prefix = $this->_options['file_name_prefix'];\n        $glob = @glob($dir . $prefix . '--*');\n        if ($glob === false) {\n            // On some systems it is impossible to distinguish between empty match and an error.\n            return array();\n        }\n        foreach ($glob as $file)  {\n            if (is_file($file)) {\n                $fileName = basename($file);\n                $id = $this->_fileNameToId($fileName);\n                $metadatas = $this->_getMetadatas($id);\n                if ($metadatas === FALSE) {\n                    continue;\n                }\n                if (time() > $metadatas['expire']) {\n                    continue;\n                }\n                switch ($mode) {\n                    case 'ids':\n                        $result[] = $id;\n                        break;\n                    case 'tags':\n                        $result = array_unique(array_merge($result, $metadatas['tags']));\n                        break;\n                    case 'matching':\n                        $matching = true;\n                        foreach ($tags as $tag) {\n                            if (!in_array($tag, $metadatas['tags'])) {\n                                $matching = false;\n                                break;\n                            }\n                        }\n                        if ($matching) {\n                            $result[] = $id;\n                        }\n                        break;\n                    case 'notMatching':\n                        $matching = false;\n                        foreach ($tags as $tag) {\n                            if (in_array($tag, $metadatas['tags'])) {\n                                $matching = true;\n                                break;\n                            }\n                        }\n                        if (!$matching) {\n                            $result[] = $id;\n                        }\n                        break;\n                    case 'matchingAny':\n                        $matching = false;\n                        foreach ($tags as $tag) {\n                            if (in_array($tag, $metadatas['tags'])) {\n                                $matching = true;\n                                break;\n                            }\n                        }\n                        if ($matching) {\n                            $result[] = $id;\n                        }\n                        break;\n                    default:\n                        Zend_Cache::throwException('Invalid mode for _get() method');\n                        break;\n                }\n            }\n            if ((is_dir($file)) and ($this->_options['hashed_directory_level']>0)) {\n                // Recursive call\n                $recursiveRs =  $this->_get($file . DIRECTORY_SEPARATOR, $mode, $tags);\n                if ($recursiveRs === false) {\n                    $this->_log('Zend_Cache_Backend_File::_get() / recursive call : can\\'t list entries of \"'.$file.'\"');\n                } else {\n                    $result = array_unique(array_merge($result, $recursiveRs));\n                }\n            }\n        }\n        return array_unique($result);\n    }\n\n    /**\n     * Compute & return the expire time\n     *\n     * @return int expire time (unix timestamp)\n     */\n    protected function _expireTime($lifetime)\n    {\n        if ($lifetime === null) {\n            return 9999999999;\n        }\n        return time() + $lifetime;\n    }\n\n    /**\n     * Make a control key with the string containing datas\n     *\n     * @param  string $data        Data\n     * @param  string $controlType Type of control 'md5', 'crc32' or 'strlen'\n     * @throws Zend_Cache_Exception\n     * @return string Control key\n     */\n    protected function _hash($data, $controlType)\n    {\n        switch ($controlType) {\n        case 'md5':\n            return md5($data);\n        case 'crc32':\n            return crc32($data);\n        case 'strlen':\n            return strlen($data);\n        case 'adler32':\n            return hash('adler32', $data);\n        default:\n            Zend_Cache::throwException(\"Incorrect hash function : $controlType\");\n        }\n    }\n\n    /**\n     * Transform a cache id into a file name and return it\n     *\n     * @param  string $id Cache id\n     * @return string File name\n     */\n    protected function _idToFileName($id)\n    {\n        $prefix = $this->_options['file_name_prefix'];\n        $result = $prefix . '---' . $id;\n        return $result;\n    }\n\n    /**\n     * Make and return a file name (with path)\n     *\n     * @param  string $id Cache id\n     * @return string File name (with path)\n     */\n    protected function _file($id)\n    {\n        $path = $this->_path($id);\n        $fileName = $this->_idToFileName($id);\n        return $path . $fileName;\n    }\n\n    /**\n     * Return the complete directory path of a filename (including hashedDirectoryStructure)\n     *\n     * @param  string $id Cache id\n     * @param  boolean $parts if true, returns array of directory parts instead of single string\n     * @return string Complete directory path\n     */\n    protected function _path($id, $parts = false)\n    {\n        $partsArray = array();\n        $root = $this->_options['cache_dir'];\n        $prefix = $this->_options['file_name_prefix'];\n        if ($this->_options['hashed_directory_level']>0) {\n            $hash = hash('adler32', $id);\n            for ($i=0 ; $i < $this->_options['hashed_directory_level'] ; $i++) {\n                $root = $root . $prefix . '--' . substr($hash, 0, $i + 1) . DIRECTORY_SEPARATOR;\n                $partsArray[] = $root;\n            }\n        }\n        if ($parts) {\n            return $partsArray;\n        } else {\n            return $root;\n        }\n    }\n\n    /**\n     * Make the directory strucuture for the given id\n     *\n     * @param string $id cache id\n     * @return boolean true\n     */\n    protected function _recursiveMkdirAndChmod($id)\n    {\n        if ($this->_options['hashed_directory_level'] <=0) {\n            return true;\n        }\n        $partsArray = $this->_path($id, true);\n        foreach ($partsArray as $part) {\n            if (!is_dir($part)) {\n                @mkdir($part, $this->_options['hashed_directory_perm']);\n                @chmod($part, $this->_options['hashed_directory_perm']); // see #ZF-320 (this line is required in some configurations)\n            }\n        }\n        return true;\n    }\n\n    /**\n     * Test if the given cache id is available (and still valid as a cache record)\n     *\n     * @param  string  $id                     Cache id\n     * @param  boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested\n     * @return boolean|mixed false (a cache is not available) or \"last modified\" timestamp (int) of the available cache record\n     */\n    protected function _test($id, $doNotTestCacheValidity)\n    {\n        $metadatas = $this->_getMetadatas($id);\n        if (!$metadatas) {\n            return false;\n        }\n        if ($doNotTestCacheValidity || (time() <= $metadatas['expire'])) {\n            return $metadatas['mtime'];\n        }\n        return false;\n    }\n\n    /**\n     * Return the file content of the given file\n     *\n     * @param  string $file File complete path\n     * @return string File content (or false if problem)\n     */\n    protected function _fileGetContents($file)\n    {\n        $result = false;\n        if (!is_file($file)) {\n            return false;\n        }\n        $f = @fopen($file, 'rb');\n        if ($f) {\n            if ($this->_options['file_locking']) @flock($f, LOCK_SH);\n            $result = stream_get_contents($f);\n            if ($this->_options['file_locking']) @flock($f, LOCK_UN);\n            @fclose($f);\n        }\n        return $result;\n    }\n\n    /**\n     * Put the given string into the given file\n     *\n     * @param  string $file   File complete path\n     * @param  string $string String to put in file\n     * @return boolean true if no problem\n     */\n    protected function _filePutContents($file, $string)\n    {\n        $result = false;\n        $f = @fopen($file, 'ab+');\n        if ($f) {\n            if ($this->_options['file_locking']) @flock($f, LOCK_EX);\n            fseek($f, 0);\n            ftruncate($f, 0);\n            $tmp = @fwrite($f, $string);\n            if (!($tmp === FALSE)) {\n                $result = true;\n            }\n            @fclose($f);\n        }\n        @chmod($file, $this->_options['cache_file_perm']);\n        return $result;\n    }\n\n    /**\n     * Transform a file name into cache id and return it\n     *\n     * @param  string $fileName File name\n     * @return string Cache id\n     */\n    protected function _fileNameToId($fileName)\n    {\n        $prefix = $this->_options['file_name_prefix'];\n        return preg_replace('~^' . $prefix . '---(.*)$~', '$1', $fileName);\n    }\n\n}\n"
  },
  {
    "path": "libraries/Zend/Cache/Backend/Interface.php",
    "content": "<?php\n/**\n * Zend Framework\n *\n * LICENSE\n *\n * This source file is subject to the new BSD license that is bundled\n * with this package in the file LICENSE.txt.\n * It is also available through the world-wide-web at this URL:\n * http://framework.zend.com/license/new-bsd\n * If you did not receive a copy of the license and are unable to\n * obtain it through the world-wide-web, please send an email\n * to license@zend.com so we can send you a copy immediately.\n *\n * @category   Zend\n * @package    Zend_Cache\n * @subpackage Zend_Cache_Backend\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n * @version    $Id: Interface.php 24593 2012-01-05 20:35:02Z matthew $\n */\n\n\n/**\n * @package    Zend_Cache\n * @subpackage Zend_Cache_Backend\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n */\ninterface Zend_Cache_Backend_Interface\n{\n    /**\n     * Set the frontend directives\n     *\n     * @param array $directives assoc of directives\n     */\n    public function setDirectives($directives);\n\n    /**\n     * Test if a cache is available for the given id and (if yes) return it (false else)\n     *\n     * Note : return value is always \"string\" (unserialization is done by the core not by the backend)\n     *\n     * @param  string  $id                     Cache id\n     * @param  boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested\n     * @return string|false cached datas\n     */\n    public function load($id, $doNotTestCacheValidity = false);\n\n    /**\n     * Test if a cache is available or not (for the given id)\n     *\n     * @param  string $id cache id\n     * @return mixed|false (a cache is not available) or \"last modified\" timestamp (int) of the available cache record\n     */\n    public function test($id);\n\n    /**\n     * Save some string datas into a cache record\n     *\n     * Note : $data is always \"string\" (serialization is done by the\n     * core not by the backend)\n     *\n     * @param  string $data            Datas to cache\n     * @param  string $id              Cache id\n     * @param  array $tags             Array of strings, the cache record will be tagged by each string entry\n     * @param  int   $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)\n     * @return boolean true if no problem\n     */\n    public function save($data, $id, $tags = array(), $specificLifetime = false);\n\n    /**\n     * Remove a cache record\n     *\n     * @param  string $id Cache id\n     * @return boolean True if no problem\n     */\n    public function remove($id);\n\n    /**\n     * Clean some cache records\n     *\n     * Available modes are :\n     * Zend_Cache::CLEANING_MODE_ALL (default)    => remove all cache entries ($tags is not used)\n     * Zend_Cache::CLEANING_MODE_OLD              => remove too old cache entries ($tags is not used)\n     * Zend_Cache::CLEANING_MODE_MATCHING_TAG     => remove cache entries matching all given tags\n     *                                               ($tags can be an array of strings or a single string)\n     * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}\n     *                                               ($tags can be an array of strings or a single string)\n     * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags\n     *                                               ($tags can be an array of strings or a single string)\n     *\n     * @param  string $mode Clean mode\n     * @param  array  $tags Array of tags\n     * @return boolean true if no problem\n     */\n    public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array());\n\n}\n"
  },
  {
    "path": "libraries/Zend/Cache/Backend.php",
    "content": "<?php\n/**\n * Zend Framework\n *\n * LICENSE\n *\n * This source file is subject to the new BSD license that is bundled\n * with this package in the file LICENSE.txt.\n * It is also available through the world-wide-web at this URL:\n * http://framework.zend.com/license/new-bsd\n * If you did not receive a copy of the license and are unable to\n * obtain it through the world-wide-web, please send an email\n * to license@zend.com so we can send you a copy immediately.\n *\n * @category   Zend\n * @package    Zend_Cache\n * @subpackage Zend_Cache_Backend\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n * @version    $Id: Backend.php 24989 2012-06-21 07:24:13Z mabe $\n */\n\n\n/**\n * @package    Zend_Cache\n * @subpackage Zend_Cache_Backend\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n */\nclass Zend_Cache_Backend\n{\n    /**\n     * Frontend or Core directives\n     *\n     * =====> (int) lifetime :\n     * - Cache lifetime (in seconds)\n     * - If null, the cache is valid forever\n     *\n     * =====> (int) logging :\n     * - if set to true, a logging is activated throw Zend_Log\n     *\n     * @var array directives\n     */\n    protected $_directives = array(\n        'lifetime' => 3600,\n        'logging'  => false,\n        'logger'   => null\n    );\n\n    /**\n     * Available options\n     *\n     * @var array available options\n     */\n    protected $_options = array();\n\n    /**\n     * Constructor\n     *\n     * @param  array $options Associative array of options\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    public function __construct(array $options = array())\n    {\n        while (list($name, $value) = each($options)) {\n            $this->setOption($name, $value);\n        }\n    }\n\n    /**\n     * Set the frontend directives\n     *\n     * @param  array $directives Assoc of directives\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    public function setDirectives($directives)\n    {\n        if (!is_array($directives)) Zend_Cache::throwException('Directives parameter must be an array');\n        while (list($name, $value) = each($directives)) {\n            if (!is_string($name)) {\n                Zend_Cache::throwException(\"Incorrect option name : $name\");\n            }\n            $name = strtolower($name);\n            if (array_key_exists($name, $this->_directives)) {\n                $this->_directives[$name] = $value;\n            }\n\n        }\n\n        $this->_loggerSanity();\n    }\n\n    /**\n     * Set an option\n     *\n     * @param  string $name\n     * @param  mixed  $value\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    public function setOption($name, $value)\n    {\n        if (!is_string($name)) {\n            Zend_Cache::throwException(\"Incorrect option name : $name\");\n        }\n        $name = strtolower($name);\n        if (array_key_exists($name, $this->_options)) {\n            $this->_options[$name] = $value;\n        }\n    }\n\n    /**\n     * Returns an option\n     *\n     * @param string $name Optional, the options name to return\n     * @throws Zend_Cache_Exceptions\n     * @return mixed\n     */\n    public function getOption($name)\n    {\n        $name = strtolower($name);\n\n        if (array_key_exists($name, $this->_options)) {\n            return $this->_options[$name];\n        }\n\n        if (array_key_exists($name, $this->_directives)) {\n            return $this->_directives[$name];\n        }\n\n        Zend_Cache::throwException(\"Incorrect option name : {$name}\");\n    }\n\n    /**\n     * Get the life time\n     *\n     * if $specificLifetime is not false, the given specific life time is used\n     * else, the global lifetime is used\n     *\n     * @param  int $specificLifetime\n     * @return int Cache life time\n     */\n    public function getLifetime($specificLifetime)\n    {\n        if ($specificLifetime === false) {\n            return $this->_directives['lifetime'];\n        }\n        return $specificLifetime;\n    }\n\n    /**\n     * Return true if the automatic cleaning is available for the backend\n     *\n     * DEPRECATED : use getCapabilities() instead\n     *\n     * @deprecated\n     * @return boolean\n     */\n    public function isAutomaticCleaningAvailable()\n    {\n        return true;\n    }\n\n    /**\n     * Determine system TMP directory and detect if we have read access\n     *\n     * inspired from Zend_File_Transfer_Adapter_Abstract\n     *\n     * @return string\n     * @throws Zend_Cache_Exception if unable to determine directory\n     */\n    public function getTmpDir()\n    {\n        $tmpdir = array();\n        foreach (array($_ENV, $_SERVER) as $tab) {\n            foreach (array('TMPDIR', 'TEMP', 'TMP', 'windir', 'SystemRoot') as $key) {\n                if (isset($tab[$key]) && is_string($tab[$key])) {\n                    if (($key == 'windir') or ($key == 'SystemRoot')) {\n                        $dir = realpath($tab[$key] . '\\\\temp');\n                    } else {\n                        $dir = realpath($tab[$key]);\n                    }\n                    if ($this->_isGoodTmpDir($dir)) {\n                        return $dir;\n                    }\n                }\n            }\n        }\n        $upload = ini_get('upload_tmp_dir');\n        if ($upload) {\n            $dir = realpath($upload);\n            if ($this->_isGoodTmpDir($dir)) {\n                return $dir;\n            }\n        }\n        if (function_exists('sys_get_temp_dir')) {\n            $dir = sys_get_temp_dir();\n            if ($this->_isGoodTmpDir($dir)) {\n                return $dir;\n            }\n        }\n        // Attemp to detect by creating a temporary file\n        $tempFile = tempnam(md5(uniqid(rand(), TRUE)), '');\n        if ($tempFile) {\n            $dir = realpath(dirname($tempFile));\n            unlink($tempFile);\n            if ($this->_isGoodTmpDir($dir)) {\n                return $dir;\n            }\n        }\n        if ($this->_isGoodTmpDir('/tmp')) {\n            return '/tmp';\n        }\n        if ($this->_isGoodTmpDir('\\\\temp')) {\n            return '\\\\temp';\n        }\n        Zend_Cache::throwException('Could not determine temp directory, please specify a cache_dir manually');\n    }\n\n    /**\n     * Verify if the given temporary directory is readable and writable\n     *\n     * @param string $dir temporary directory\n     * @return boolean true if the directory is ok\n     */\n    protected function _isGoodTmpDir($dir)\n    {\n        if (is_readable($dir)) {\n            if (is_writable($dir)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * Make sure if we enable logging that the Zend_Log class\n     * is available.\n     * Create a default log object if none is set.\n     *\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    protected function _loggerSanity()\n    {\n        if (!isset($this->_directives['logging']) || !$this->_directives['logging']) {\n            return;\n        }\n\n        if (isset($this->_directives['logger'])) {\n            if ($this->_directives['logger'] instanceof Zend_Log) {\n                return;\n            }\n            Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.');\n        }\n\n        // Create a default logger to the standard output stream\n        require_once 'Zend/Log.php';\n        require_once 'Zend/Log/Writer/Stream.php';\n        require_once 'Zend/Log/Filter/Priority.php';\n        $logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));\n        $logger->addFilter(new Zend_Log_Filter_Priority(Zend_Log::WARN, '<='));\n        $this->_directives['logger'] = $logger;\n    }\n\n    /**\n     * Log a message at the WARN (4) priority.\n     *\n     * @param  string $message\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    protected function _log($message, $priority = 4)\n    {\n        if (!$this->_directives['logging']) {\n            return;\n        }\n\n        if (!isset($this->_directives['logger'])) {\n            Zend_Cache::throwException('Logging is enabled but logger is not set.');\n        }\n        $logger = $this->_directives['logger'];\n        if (!$logger instanceof Zend_Log) {\n            Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.');\n        }\n        $logger->log($message, $priority);\n    }\n}\n"
  },
  {
    "path": "libraries/Zend/Cache/Core.php",
    "content": "<?php\n/**\n * Zend Framework\n *\n * LICENSE\n *\n * This source file is subject to the new BSD license that is bundled\n * with this package in the file LICENSE.txt.\n * It is also available through the world-wide-web at this URL:\n * http://framework.zend.com/license/new-bsd\n * If you did not receive a copy of the license and are unable to\n * obtain it through the world-wide-web, please send an email\n * to license@zend.com so we can send you a copy immediately.\n *\n * @category   Zend\n * @package    Zend_Cache\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n * @version    $Id: Core.php 24989 2012-06-21 07:24:13Z mabe $\n */\n\n\n/**\n * @package    Zend_Cache\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n */\nclass Zend_Cache_Core\n{\n    /**\n     * Messages\n     */\n    const BACKEND_NOT_SUPPORTS_TAG = 'tags are not supported by the current backend';\n    const BACKEND_NOT_IMPLEMENTS_EXTENDED_IF = 'Current backend doesn\\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available';\n\n    /**\n     * Backend Object\n     *\n     * @var Zend_Cache_Backend_Interface $_backend\n     */\n    protected $_backend = null;\n\n    /**\n     * Available options\n     *\n     * ====> (boolean) write_control :\n     * - Enable / disable write control (the cache is read just after writing to detect corrupt entries)\n     * - Enable write control will lightly slow the cache writing but not the cache reading\n     * Write control can detect some corrupt cache files but maybe it's not a perfect control\n     *\n     * ====> (boolean) caching :\n     * - Enable / disable caching\n     * (can be very useful for the debug of cached scripts)\n     *\n     * =====> (string) cache_id_prefix :\n     * - prefix for cache ids (namespace)\n     *\n     * ====> (boolean) automatic_serialization :\n     * - Enable / disable automatic serialization\n     * - It can be used to save directly datas which aren't strings (but it's slower)\n     *\n     * ====> (int) automatic_cleaning_factor :\n     * - Disable / Tune the automatic cleaning process\n     * - The automatic cleaning process destroy too old (for the given life time)\n     *   cache files when a new cache file is written :\n     *     0               => no automatic cache cleaning\n     *     1               => systematic cache cleaning\n     *     x (integer) > 1 => automatic cleaning randomly 1 times on x cache write\n     *\n     * ====> (int) lifetime :\n     * - Cache lifetime (in seconds)\n     * - If null, the cache is valid forever.\n     *\n     * ====> (boolean) logging :\n     * - If set to true, logging is activated (but the system is slower)\n     *\n     * ====> (boolean) ignore_user_abort\n     * - If set to true, the core will set the ignore_user_abort PHP flag inside the\n     *   save() method to avoid cache corruptions in some cases (default false)\n     *\n     * @var array $_options available options\n     */\n    protected $_options = array(\n        'write_control'             => true,\n        'caching'                   => true,\n        'cache_id_prefix'           => null,\n        'automatic_serialization'   => false,\n        'automatic_cleaning_factor' => 10,\n        'lifetime'                  => 3600,\n        'logging'                   => false,\n        'logger'                    => null,\n        'ignore_user_abort'         => false\n    );\n\n    /**\n     * Array of options which have to be transfered to backend\n     *\n     * @var array $_directivesList\n     */\n    protected static $_directivesList = array('lifetime', 'logging', 'logger');\n\n    /**\n     * Not used for the core, just a sort a hint to get a common setOption() method (for the core and for frontends)\n     *\n     * @var array $_specificOptions\n     */\n    protected $_specificOptions = array();\n\n    /**\n     * Last used cache id\n     *\n     * @var string $_lastId\n     */\n    private $_lastId = null;\n\n    /**\n     * True if the backend implements Zend_Cache_Backend_ExtendedInterface\n     *\n     * @var boolean $_extendedBackend\n     */\n    protected $_extendedBackend = false;\n\n    /**\n     * Array of capabilities of the backend (only if it implements Zend_Cache_Backend_ExtendedInterface)\n     *\n     * @var array\n     */\n    protected $_backendCapabilities = array();\n\n    /**\n     * Constructor\n     *\n     * @param  array|Zend_Config $options Associative array of options or Zend_Config instance\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    public function __construct($options = array())\n    {\n        if ($options instanceof Zend_Config) {\n            $options = $options->toArray();\n        }\n        if (!is_array($options)) {\n            Zend_Cache::throwException(\"Options passed were not an array\"\n            . \" or Zend_Config instance.\");\n        }\n        while (list($name, $value) = each($options)) {\n            $this->setOption($name, $value);\n        }\n        $this->_loggerSanity();\n    }\n\n    /**\n     * Set options using an instance of type Zend_Config\n     *\n     * @param Zend_Config $config\n     * @return Zend_Cache_Core\n     */\n    public function setConfig(Zend_Config $config)\n    {\n        $options = $config->toArray();\n        while (list($name, $value) = each($options)) {\n            $this->setOption($name, $value);\n        }\n        return $this;\n    }\n\n    /**\n     * Set the backend\n     *\n     * @param  Zend_Cache_Backend $backendObject\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    public function setBackend(Zend_Cache_Backend $backendObject)\n    {\n        $this->_backend= $backendObject;\n        // some options (listed in $_directivesList) have to be given\n        // to the backend too (even if they are not \"backend specific\")\n        $directives = array();\n        foreach (Zend_Cache_Core::$_directivesList as $directive) {\n            $directives[$directive] = $this->_options[$directive];\n        }\n        $this->_backend->setDirectives($directives);\n        if (in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_backend))) {\n            $this->_extendedBackend = true;\n            $this->_backendCapabilities = $this->_backend->getCapabilities();\n        }\n\n    }\n\n    /**\n     * Returns the backend\n     *\n     * @return Zend_Cache_Backend backend object\n     */\n    public function getBackend()\n    {\n        return $this->_backend;\n    }\n\n    /**\n     * Public frontend to set an option\n     *\n     * There is an additional validation (relatively to the protected _setOption method)\n     *\n     * @param  string $name  Name of the option\n     * @param  mixed  $value Value of the option\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    public function setOption($name, $value)\n    {\n        if (!is_string($name)) {\n            Zend_Cache::throwException(\"Incorrect option name!\");\n        }\n        $name = strtolower($name);\n        if (array_key_exists($name, $this->_options)) {\n            // This is a Core option\n            $this->_setOption($name, $value);\n            return;\n        }\n        if (array_key_exists($name, $this->_specificOptions)) {\n            // This a specic option of this frontend\n            $this->_specificOptions[$name] = $value;\n            return;\n        }\n    }\n\n    /**\n     * Public frontend to get an option value\n     *\n     * @param  string $name  Name of the option\n     * @throws Zend_Cache_Exception\n     * @return mixed option value\n     */\n    public function getOption($name)\n    {\n        $name = strtolower($name);\n\n        if (array_key_exists($name, $this->_options)) {\n            // This is a Core option\n            return $this->_options[$name];\n        }\n\n        if (array_key_exists($name, $this->_specificOptions)) {\n            // This a specic option of this frontend\n            return $this->_specificOptions[$name];\n        }\n\n        Zend_Cache::throwException(\"Incorrect option name : $name\");\n    }\n\n    /**\n     * Set an option\n     *\n     * @param  string $name  Name of the option\n     * @param  mixed  $value Value of the option\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    private function _setOption($name, $value)\n    {\n        if (!is_string($name) || !array_key_exists($name, $this->_options)) {\n            Zend_Cache::throwException(\"Incorrect option name : $name\");\n        }\n        if ($name == 'lifetime' && empty($value)) {\n            $value = null;\n        }\n        $this->_options[$name] = $value;\n    }\n\n    /**\n     * Force a new lifetime\n     *\n     * The new value is set for the core/frontend but for the backend too (directive)\n     *\n     * @param  int $newLifetime New lifetime (in seconds)\n     * @return void\n     */\n    public function setLifetime($newLifetime)\n    {\n        $this->_options['lifetime'] = $newLifetime;\n        $this->_backend->setDirectives(array(\n            'lifetime' => $newLifetime\n        ));\n    }\n\n    /**\n     * Test if a cache is available for the given id and (if yes) return it (false else)\n     *\n     * @param  string  $id                     Cache id\n     * @param  boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested\n     * @param  boolean $doNotUnserialize       Do not serialize (even if automatic_serialization is true) => for internal use\n     * @return mixed|false Cached datas\n     */\n    public function load($id, $doNotTestCacheValidity = false, $doNotUnserialize = false)\n    {\n        if (!$this->_options['caching']) {\n            return false;\n        }\n        $id = $this->_id($id); // cache id may need prefix\n        $this->_lastId = $id;\n        self::_validateIdOrTag($id);\n\n        $this->_log(\"Zend_Cache_Core: load item '{$id}'\", 7);\n        $data = $this->_backend->load($id, $doNotTestCacheValidity);\n        if ($data===false) {\n            // no cache available\n            return false;\n        }\n        if ((!$doNotUnserialize) && $this->_options['automatic_serialization']) {\n            // we need to unserialize before sending the result\n            return unserialize($data);\n        }\n        return $data;\n    }\n\n    /**\n     * Test if a cache is available for the given id\n     *\n     * @param  string $id Cache id\n     * @return int|false Last modified time of cache entry if it is available, false otherwise\n     */\n    public function test($id)\n    {\n        if (!$this->_options['caching']) {\n            return false;\n        }\n        $id = $this->_id($id); // cache id may need prefix\n        self::_validateIdOrTag($id);\n        $this->_lastId = $id;\n\n        $this->_log(\"Zend_Cache_Core: test item '{$id}'\", 7);\n        return $this->_backend->test($id);\n    }\n\n    /**\n     * Save some data in a cache\n     *\n     * @param  mixed $data           Data to put in cache (can be another type than string if automatic_serialization is on)\n     * @param  string $id             Cache id (if not set, the last cache id will be used)\n     * @param  array $tags           Cache tags\n     * @param  int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)\n     * @param  int   $priority         integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends\n     * @throws Zend_Cache_Exception\n     * @return boolean True if no problem\n     */\n    public function save($data, $id = null, $tags = array(), $specificLifetime = false, $priority = 8)\n    {\n        if (!$this->_options['caching']) {\n            return true;\n        }\n        if ($id === null) {\n            $id = $this->_lastId;\n        } else {\n            $id = $this->_id($id);\n        }\n        self::_validateIdOrTag($id);\n        self::_validateTagsArray($tags);\n        if ($this->_options['automatic_serialization']) {\n            // we need to serialize datas before storing them\n            $data = serialize($data);\n        } else {\n            if (!is_string($data)) {\n                Zend_Cache::throwException(\"Datas must be string or set automatic_serialization = true\");\n            }\n        }\n\n        // automatic cleaning\n        if ($this->_options['automatic_cleaning_factor'] > 0) {\n            $rand = rand(1, $this->_options['automatic_cleaning_factor']);\n            if ($rand==1) {\n                //  new way                 || deprecated way\n                if ($this->_extendedBackend || method_exists($this->_backend, 'isAutomaticCleaningAvailable')) {\n                    $this->_log(\"Zend_Cache_Core::save(): automatic cleaning running\", 7);\n                    $this->clean(Zend_Cache::CLEANING_MODE_OLD);\n                } else {\n                    $this->_log(\"Zend_Cache_Core::save(): automatic cleaning is not available/necessary with current backend\", 4);\n                }\n            }\n        }\n\n        $this->_log(\"Zend_Cache_Core: save item '{$id}'\", 7);\n        if ($this->_options['ignore_user_abort']) {\n            $abort = ignore_user_abort(true);\n        }\n        if (($this->_extendedBackend) && ($this->_backendCapabilities['priority'])) {\n            $result = $this->_backend->save($data, $id, $tags, $specificLifetime, $priority);\n        } else {\n            $result = $this->_backend->save($data, $id, $tags, $specificLifetime);\n        }\n        if ($this->_options['ignore_user_abort']) {\n            ignore_user_abort($abort);\n        }\n\n        if (!$result) {\n            // maybe the cache is corrupted, so we remove it !\n            $this->_log(\"Zend_Cache_Core::save(): failed to save item '{$id}' -> removing it\", 4);\n            $this->_backend->remove($id);\n            return false;\n        }\n\n        if ($this->_options['write_control']) {\n            $data2 = $this->_backend->load($id, true);\n            if ($data!=$data2) {\n                $this->_log(\"Zend_Cache_Core::save(): write control of item '{$id}' failed -> removing it\", 4);\n                $this->_backend->remove($id);\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * Remove a cache\n     *\n     * @param  string $id Cache id to remove\n     * @return boolean True if ok\n     */\n    public function remove($id)\n    {\n        if (!$this->_options['caching']) {\n            return true;\n        }\n        $id = $this->_id($id); // cache id may need prefix\n        self::_validateIdOrTag($id);\n\n        $this->_log(\"Zend_Cache_Core: remove item '{$id}'\", 7);\n        return $this->_backend->remove($id);\n    }\n\n    /**\n     * Clean cache entries\n     *\n     * Available modes are :\n     * 'all' (default)  => remove all cache entries ($tags is not used)\n     * 'old'            => remove too old cache entries ($tags is not used)\n     * 'matchingTag'    => remove cache entries matching all given tags\n     *                     ($tags can be an array of strings or a single string)\n     * 'notMatchingTag' => remove cache entries not matching one of the given tags\n     *                     ($tags can be an array of strings or a single string)\n     * 'matchingAnyTag' => remove cache entries matching any given tags\n     *                     ($tags can be an array of strings or a single string)\n     *\n     * @param  string       $mode\n     * @param  array|string $tags\n     * @throws Zend_Cache_Exception\n     * @return boolean True if ok\n     */\n    public function clean($mode = 'all', $tags = array())\n    {\n        if (!$this->_options['caching']) {\n            return true;\n        }\n        if (!in_array($mode, array(Zend_Cache::CLEANING_MODE_ALL,\n                                   Zend_Cache::CLEANING_MODE_OLD,\n                                   Zend_Cache::CLEANING_MODE_MATCHING_TAG,\n                                   Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG,\n                                   Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG))) {\n            Zend_Cache::throwException('Invalid cleaning mode');\n        }\n        self::_validateTagsArray($tags);\n\n        return $this->_backend->clean($mode, $tags);\n    }\n\n    /**\n     * Return an array of stored cache ids which match given tags\n     *\n     * In case of multiple tags, a logical AND is made between tags\n     *\n     * @param array $tags array of tags\n     * @return array array of matching cache ids (string)\n     */\n    public function getIdsMatchingTags($tags = array())\n    {\n        if (!$this->_extendedBackend) {\n            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);\n        }\n        if (!($this->_backendCapabilities['tags'])) {\n            Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);\n        }\n\n        $ids = $this->_backend->getIdsMatchingTags($tags);\n\n        // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)\n        if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {\n            $prefix    = & $this->_options['cache_id_prefix'];\n            $prefixLen = strlen($prefix);\n            foreach ($ids as &$id) {\n                if (strpos($id, $prefix) === 0) {\n                    $id = substr($id, $prefixLen);\n                }\n            }\n        }\n\n        return $ids;\n    }\n\n    /**\n     * Return an array of stored cache ids which don't match given tags\n     *\n     * In case of multiple tags, a logical OR is made between tags\n     *\n     * @param array $tags array of tags\n     * @return array array of not matching cache ids (string)\n     */\n    public function getIdsNotMatchingTags($tags = array())\n    {\n        if (!$this->_extendedBackend) {\n            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);\n        }\n        if (!($this->_backendCapabilities['tags'])) {\n            Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);\n        }\n\n        $ids = $this->_backend->getIdsNotMatchingTags($tags);\n\n        // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)\n        if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {\n            $prefix    = & $this->_options['cache_id_prefix'];\n            $prefixLen = strlen($prefix);\n            foreach ($ids as &$id) {\n                if (strpos($id, $prefix) === 0) {\n                    $id = substr($id, $prefixLen);\n                }\n            }\n        }\n\n        return $ids;\n    }\n\n    /**\n     * Return an array of stored cache ids which match any given tags\n     *\n     * In case of multiple tags, a logical OR is made between tags\n     *\n     * @param array $tags array of tags\n     * @return array array of matching any cache ids (string)\n     */\n    public function getIdsMatchingAnyTags($tags = array())\n    {\n        if (!$this->_extendedBackend) {\n            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);\n        }\n        if (!($this->_backendCapabilities['tags'])) {\n            Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);\n        }\n\n        $ids = $this->_backend->getIdsMatchingAnyTags($tags);\n\n        // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)\n        if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {\n            $prefix    = & $this->_options['cache_id_prefix'];\n            $prefixLen = strlen($prefix);\n            foreach ($ids as &$id) {\n                if (strpos($id, $prefix) === 0) {\n                    $id = substr($id, $prefixLen);\n                }\n            }\n        }\n\n        return $ids;\n    }\n\n    /**\n     * Return an array of stored cache ids\n     *\n     * @return array array of stored cache ids (string)\n     */\n    public function getIds()\n    {\n        if (!$this->_extendedBackend) {\n            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);\n        }\n\n        $ids = $this->_backend->getIds();\n\n        // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)\n        if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {\n            $prefix    = & $this->_options['cache_id_prefix'];\n            $prefixLen = strlen($prefix);\n            foreach ($ids as &$id) {\n                if (strpos($id, $prefix) === 0) {\n                    $id = substr($id, $prefixLen);\n                }\n            }\n        }\n\n        return $ids;\n    }\n\n    /**\n     * Return an array of stored tags\n     *\n     * @return array array of stored tags (string)\n     */\n    public function getTags()\n    {\n        if (!$this->_extendedBackend) {\n            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);\n        }\n        if (!($this->_backendCapabilities['tags'])) {\n            Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);\n        }\n        return $this->_backend->getTags();\n    }\n\n    /**\n     * Return the filling percentage of the backend storage\n     *\n     * @return int integer between 0 and 100\n     */\n    public function getFillingPercentage()\n    {\n        if (!$this->_extendedBackend) {\n            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);\n        }\n        return $this->_backend->getFillingPercentage();\n    }\n\n    /**\n     * Return an array of metadatas for the given cache id\n     *\n     * The array will include these keys :\n     * - expire : the expire timestamp\n     * - tags : a string array of tags\n     * - mtime : timestamp of last modification time\n     *\n     * @param string $id cache id\n     * @return array array of metadatas (false if the cache id is not found)\n     */\n    public function getMetadatas($id)\n    {\n        if (!$this->_extendedBackend) {\n            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);\n        }\n        $id = $this->_id($id); // cache id may need prefix\n        return $this->_backend->getMetadatas($id);\n    }\n\n    /**\n     * Give (if possible) an extra lifetime to the given cache id\n     *\n     * @param string $id cache id\n     * @param int $extraLifetime\n     * @return boolean true if ok\n     */\n    public function touch($id, $extraLifetime)\n    {\n        if (!$this->_extendedBackend) {\n            Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);\n        }\n        $id = $this->_id($id); // cache id may need prefix\n\n        $this->_log(\"Zend_Cache_Core: touch item '{$id}'\", 7);\n        return $this->_backend->touch($id, $extraLifetime);\n    }\n\n    /**\n     * Validate a cache id or a tag (security, reliable filenames, reserved prefixes...)\n     *\n     * Throw an exception if a problem is found\n     *\n     * @param  string $string Cache id or tag\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    protected static function _validateIdOrTag($string)\n    {\n        if (!is_string($string)) {\n            Zend_Cache::throwException('Invalid id or tag : must be a string');\n        }\n        if (substr($string, 0, 9) == 'internal-') {\n            Zend_Cache::throwException('\"internal-*\" ids or tags are reserved');\n        }\n        if (!preg_match('~^[a-zA-Z0-9_]+$~D', $string)) {\n            Zend_Cache::throwException(\"Invalid id or tag '$string' : must use only [a-zA-Z0-9_]\");\n        }\n    }\n\n    /**\n     * Validate a tags array (security, reliable filenames, reserved prefixes...)\n     *\n     * Throw an exception if a problem is found\n     *\n     * @param  array $tags Array of tags\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    protected static function _validateTagsArray($tags)\n    {\n        if (!is_array($tags)) {\n            Zend_Cache::throwException('Invalid tags array : must be an array');\n        }\n        foreach($tags as $tag) {\n            self::_validateIdOrTag($tag);\n        }\n        reset($tags);\n    }\n\n    /**\n     * Make sure if we enable logging that the Zend_Log class\n     * is available.\n     * Create a default log object if none is set.\n     *\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    protected function _loggerSanity()\n    {\n        if (!isset($this->_options['logging']) || !$this->_options['logging']) {\n            return;\n        }\n\n        if (isset($this->_options['logger']) && $this->_options['logger'] instanceof Zend_Log) {\n            return;\n        }\n\n        // Create a default logger to the standard output stream\n        require_once 'Zend/Log.php';\n        require_once 'Zend/Log/Writer/Stream.php';\n        require_once 'Zend/Log/Filter/Priority.php';\n        $logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));\n        $logger->addFilter(new Zend_Log_Filter_Priority(Zend_Log::WARN, '<='));\n        $this->_options['logger'] = $logger;\n    }\n\n    /**\n     * Log a message at the WARN (4) priority.\n     *\n     * @param string $message\n     * @throws Zend_Cache_Exception\n     * @return void\n     */\n    protected function _log($message, $priority = 4)\n    {\n        if (!$this->_options['logging']) {\n            return;\n        }\n        if (!(isset($this->_options['logger']) || $this->_options['logger'] instanceof Zend_Log)) {\n            Zend_Cache::throwException('Logging is enabled but logger is not set');\n        }\n        $logger = $this->_options['logger'];\n        $logger->log($message, $priority);\n    }\n\n    /**\n     * Make and return a cache id\n     *\n     * Checks 'cache_id_prefix' and returns new id with prefix or simply the id if null\n     *\n     * @param  string $id Cache id\n     * @return string Cache id (with or without prefix)\n     */\n    protected function _id($id)\n    {\n        if (($id !== null) && isset($this->_options['cache_id_prefix'])) {\n            return $this->_options['cache_id_prefix'] . $id; // return with prefix\n        }\n        return $id; // no prefix, just return the $id passed\n    }\n\n}\n"
  },
  {
    "path": "libraries/Zend/Cache/Exception.php",
    "content": "<?php\n/**\n * Zend Framework\n *\n * LICENSE\n *\n * This source file is subject to the new BSD license that is bundled\n * with this package in the file LICENSE.txt.\n * It is also available through the world-wide-web at this URL:\n * http://framework.zend.com/license/new-bsd\n * If you did not receive a copy of the license and are unable to\n * obtain it through the world-wide-web, please send an email\n * to license@zend.com so we can send you a copy immediately.\n *\n * @category   Zend\n * @package    Zend_Cache\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n * @version    $Id: Exception.php 24593 2012-01-05 20:35:02Z matthew $\n */\n\n/**\n * @see Zend_Exception\n */\nrequire_once 'Zend/Exception.php';\n\n/**\n * @package    Zend_Cache\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n */\nclass Zend_Cache_Exception extends Zend_Exception {}\n"
  },
  {
    "path": "libraries/Zend/Cache.php",
    "content": "<?php\n/**\n * Zend Framework\n *\n * LICENSE\n *\n * This source file is subject to the new BSD license that is bundled\n * with this package in the file LICENSE.txt.\n * It is also available through the world-wide-web at this URL:\n * http://framework.zend.com/license/new-bsd\n * If you did not receive a copy of the license and are unable to\n * obtain it through the world-wide-web, please send an email\n * to license@zend.com so we can send you a copy immediately.\n *\n * @category   Zend\n * @package    Zend_Cache\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n * @version    $Id: Cache.php 24656 2012-02-26 06:02:53Z adamlundrigan $\n */\n\n\n/**\n * @package    Zend_Cache\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n */\nabstract class Zend_Cache\n{\n\n    /**\n     * Standard frontends\n     *\n     * @var array\n     */\n    public static $standardFrontends = array('Core', 'Output', 'Class', 'File', 'Function', 'Page');\n\n    /**\n     * Standard backends\n     *\n     * @var array\n     */\n    public static $standardBackends = array('File', 'Sqlite', 'Memcached', 'Libmemcached', 'Apc', 'ZendPlatform',\n                                            'Xcache', 'TwoLevels', 'WinCache', 'ZendServer_Disk', 'ZendServer_ShMem');\n\n    /**\n     * Standard backends which implement the ExtendedInterface\n     *\n     * @var array\n     */\n    public static $standardExtendedBackends = array('File', 'Apc', 'TwoLevels', 'Memcached', 'Libmemcached', 'Sqlite', 'WinCache');\n\n    /**\n     * Only for backward compatibility (may be removed in next major release)\n     *\n     * @var array\n     * @deprecated\n     */\n    public static $availableFrontends = array('Core', 'Output', 'Class', 'File', 'Function', 'Page');\n\n    /**\n     * Only for backward compatibility (may be removed in next major release)\n     *\n     * @var array\n     * @deprecated\n     */\n    public static $availableBackends = array('File', 'Sqlite', 'Memcached', 'Libmemcached', 'Apc', 'ZendPlatform', 'Xcache', 'WinCache', 'TwoLevels');\n\n    /**\n     * Consts for clean() method\n     */\n    const CLEANING_MODE_ALL              = 'all';\n    const CLEANING_MODE_OLD              = 'old';\n    const CLEANING_MODE_MATCHING_TAG     = 'matchingTag';\n    const CLEANING_MODE_NOT_MATCHING_TAG = 'notMatchingTag';\n    const CLEANING_MODE_MATCHING_ANY_TAG = 'matchingAnyTag';\n\n    /**\n     * Factory\n     *\n     * @param mixed  $frontend        frontend name (string) or Zend_Cache_Frontend_ object\n     * @param mixed  $backend         backend name (string) or Zend_Cache_Backend_ object\n     * @param array  $frontendOptions associative array of options for the corresponding frontend constructor\n     * @param array  $backendOptions  associative array of options for the corresponding backend constructor\n     * @param boolean $customFrontendNaming if true, the frontend argument is used as a complete class name ; if false, the frontend argument is used as the end of \"Zend_Cache_Frontend_[...]\" class name\n     * @param boolean $customBackendNaming if true, the backend argument is used as a complete class name ; if false, the backend argument is used as the end of \"Zend_Cache_Backend_[...]\" class name\n     * @param boolean $autoload if true, there will no require_once for backend and frontend (useful only for custom backends/frontends)\n     * @throws Zend_Cache_Exception\n     * @return Zend_Cache_Core|Zend_Cache_Frontend\n     */\n    public static function factory($frontend, $backend, $frontendOptions = array(), $backendOptions = array(), $customFrontendNaming = false, $customBackendNaming = false, $autoload = false)\n    {\n        if (is_string($backend)) {\n            $backendObject = self::_makeBackend($backend, $backendOptions, $customBackendNaming, $autoload);\n        } else {\n            if ((is_object($backend)) && (in_array('Zend_Cache_Backend_Interface', class_implements($backend)))) {\n                $backendObject = $backend;\n            } else {\n                self::throwException('backend must be a backend name (string) or an object which implements Zend_Cache_Backend_Interface');\n            }\n        }\n        if (is_string($frontend)) {\n            $frontendObject = self::_makeFrontend($frontend, $frontendOptions, $customFrontendNaming, $autoload);\n        } else {\n            if (is_object($frontend)) {\n                $frontendObject = $frontend;\n            } else {\n                self::throwException('frontend must be a frontend name (string) or an object');\n            }\n        }\n        $frontendObject->setBackend($backendObject);\n        return $frontendObject;\n    }\n\n    /**\n     * Backend Constructor\n     *\n     * @param string  $backend\n     * @param array   $backendOptions\n     * @param boolean $customBackendNaming\n     * @param boolean $autoload\n     * @return Zend_Cache_Backend\n     */\n    public static function _makeBackend($backend, $backendOptions, $customBackendNaming = false, $autoload = false)\n    {\n        if (!$customBackendNaming) {\n            $backend  = self::_normalizeName($backend);\n        }\n        if (in_array($backend, Zend_Cache::$standardBackends)) {\n            // we use a standard backend\n            $backendClass = 'Zend_Cache_Backend_' . $backend;\n            // security controls are explicit\n            require_once realpath(dirname(__FILE__).'/..').DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php';\n        } else {\n            // we use a custom backend\n            if (!preg_match('~^[\\w\\\\\\\\]+$~D', $backend)) {\n                Zend_Cache::throwException(\"Invalid backend name [$backend]\");\n            }\n            if (!$customBackendNaming) {\n                // we use this boolean to avoid an API break\n                $backendClass = 'Zend_Cache_Backend_' . $backend;\n            } else {\n                $backendClass = $backend;\n            }\n            if (!$autoload) {\n                $file = str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php';\n                if (!(self::_isReadable($file))) {\n                    self::throwException(\"file $file not found in include_path\");\n                }\n                require_once $file;\n            }\n        }\n        return new $backendClass($backendOptions);\n    }\n\n    /**\n     * Frontend Constructor\n     *\n     * @param string  $frontend\n     * @param array   $frontendOptions\n     * @param boolean $customFrontendNaming\n     * @param boolean $autoload\n     * @return Zend_Cache_Core|Zend_Cache_Frontend\n     */\n    public static function _makeFrontend($frontend, $frontendOptions = array(), $customFrontendNaming = false, $autoload = false)\n    {\n        if (!$customFrontendNaming) {\n            $frontend = self::_normalizeName($frontend);\n        }\n        if (in_array($frontend, self::$standardFrontends)) {\n            // we use a standard frontend\n            // For perfs reasons, with frontend == 'Core', we can interact with the Core itself\n            $frontendClass = 'Zend_Cache_' . ($frontend != 'Core' ? 'Frontend_' : '') . $frontend;\n            // security controls are explicit\n            require_once realpath(dirname(__FILE__).'/..').DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $frontendClass) . '.php';\n        } else {\n            // we use a custom frontend\n            if (!preg_match('~^[\\w\\\\\\\\]+$~D', $frontend)) {\n                Zend_Cache::throwException(\"Invalid frontend name [$frontend]\");\n            }\n            if (!$customFrontendNaming) {\n                // we use this boolean to avoid an API break\n                $frontendClass = 'Zend_Cache_Frontend_' . $frontend;\n            } else {\n                $frontendClass = $frontend;\n            }\n            if (!$autoload) {\n                $file = str_replace('_', DIRECTORY_SEPARATOR, $frontendClass) . '.php';\n                if (!(self::_isReadable($file))) {\n                    self::throwException(\"file $file not found in include_path\");\n                }\n                require_once $file;\n            }\n        }\n        return new $frontendClass($frontendOptions);\n    }\n\n    /**\n     * Throw an exception\n     *\n     * Note : for perf reasons, the \"load\" of Zend/Cache/Exception is dynamic\n     * @param  string $msg  Message for the exception\n     * @throws Zend_Cache_Exception\n     */\n    public static function throwException($msg, Exception $e = null)\n    {\n        // For perfs reasons, we use this dynamic inclusion\n        require_once 'Zend/Cache/Exception.php';\n        throw new Zend_Cache_Exception($msg, 0, $e);\n    }\n\n    /**\n     * Normalize frontend and backend names to allow multiple words TitleCased\n     *\n     * @param  string $name  Name to normalize\n     * @return string\n     */\n    protected static function _normalizeName($name)\n    {\n        $name = ucfirst(strtolower($name));\n        $name = str_replace(array('-', '_', '.'), ' ', $name);\n        $name = ucwords($name);\n        $name = str_replace(' ', '', $name);\n        if (stripos($name, 'ZendServer') === 0) {\n            $name = 'ZendServer_' . substr($name, strlen('ZendServer'));\n        }\n\n        return $name;\n    }\n\n    /**\n     * Returns TRUE if the $filename is readable, or FALSE otherwise.\n     * This function uses the PHP include_path, where PHP's is_readable()\n     * does not.\n     *\n     * Note : this method comes from Zend_Loader (see #ZF-2891 for details)\n     *\n     * @param string   $filename\n     * @return boolean\n     */\n    private static function _isReadable($filename)\n    {\n        if (!$fh = @fopen($filename, 'r', true)) {\n            return false;\n        }\n        @fclose($fh);\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "libraries/Zend/Exception.php",
    "content": "<?php\n/**\n * Zend Framework\n *\n * LICENSE\n *\n * This source file is subject to the new BSD license that is bundled\n * with this package in the file LICENSE.txt.\n * It is also available through the world-wide-web at this URL:\n * http://framework.zend.com/license/new-bsd\n * If you did not receive a copy of the license and are unable to\n * obtain it through the world-wide-web, please send an email\n * to license@zend.com so we can send you a copy immediately.\n *\n * @category   Zend\n * @package    Zend\n * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n * @license    http://framework.zend.com/license/new-bsd     New BSD License\n * @version    $Id: Exception.php 24593 2012-01-05 20:35:02Z matthew $\n */\n\n/**\n* @category   Zend\n* @package    Zend\n* @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)\n* @license    http://framework.zend.com/license/new-bsd     New BSD License\n*/\nclass Zend_Exception extends Exception\n{\n    /**\n     * @var null|Exception\n     */\n    private $_previous = null;\n\n    /**\n     * Construct the exception\n     *\n     * @param  string $msg\n     * @param  int $code\n     * @param  Exception $previous\n     * @return void\n     */\n    public function __construct($msg = '', $code = 0, Exception $previous = null)\n    {\n        if (version_compare(PHP_VERSION, '5.3.0', '<')) {\n            parent::__construct($msg, (int) $code);\n            $this->_previous = $previous;\n        } else {\n            parent::__construct($msg, (int) $code, $previous);\n        }\n    }\n\n    /**\n     * Overloading\n     *\n     * For PHP < 5.3.0, provides access to the getPrevious() method.\n     *\n     * @param  string $method\n     * @param  array $args\n     * @return mixed\n     */\n    public function __call($method, array $args)\n    {\n        if ('getprevious' == strtolower($method)) {\n            return $this->_getPrevious();\n        }\n        return null;\n    }\n\n    /**\n     * String representation of the exception\n     *\n     * @return string\n     */\n    public function __toString()\n    {\n        if (version_compare(PHP_VERSION, '5.3.0', '<')) {\n            if (null !== ($e = $this->getPrevious())) {\n                return $e->__toString()\n                       . \"\\n\\nNext \"\n                       . parent::__toString();\n            }\n        }\n        return parent::__toString();\n    }\n\n    /**\n     * Returns previous Exception\n     *\n     * @return Exception|null\n     */\n    protected function _getPrevious()\n    {\n        return $this->_previous;\n    }\n}\n"
  },
  {
    "path": "libraries/content-extractor/ContentExtractor.php",
    "content": "<?php\n/**\n * Content Extractor\n * \n * Uses patterns specified in site config files and auto detection (hNews/PHP Readability) \n * to extract content from HTML files.\n * \n * @version 1.0\n * @date 2013-02-05\n * @author Keyvan Minoukadeh\n * @copyright 2013 Keyvan Minoukadeh\n * @license http://www.gnu.org/licenses/agpl-3.0.html AGPL v3\n */\n\nclass ContentExtractor\n{\n\tprotected $html;\n\tprotected $config;\n\tprotected $title;\n\tprotected $author = array();\n\tprotected $language;\n\tprotected $date;\n\tprotected $body;\n\tprotected $success = false;\n\tprotected $nextPageUrl;\n\tpublic $allowedParsers = array('libxml', 'html5lib');\n\tpublic $fingerprints = array();\n\tpublic $readability;\n\tpublic $debug = false;\n\tpublic $debugVerbose = false;\n\n\tfunction __construct($path, $fallback=null) {\n\t\tSiteConfig::set_config_path($path, $fallback);\t\n\t}\n\t\n\tprotected function debug($msg) {\n\t\tif ($this->debug) {\n\t\t\t$mem = round(memory_get_usage()/1024, 2);\n\t\t\t$memPeak = round(memory_get_peak_usage()/1024, 2);\n\t\t\techo '* ',$msg,\"<br />\";\n\t\t\tif ($this->debugVerbose) echo ' - mem used: ',$mem,\" (peak: $memPeak)\";\n\t\t\techo \"\\n\";\n\t\t\tob_flush();\n\t\t\tflush();\n\t\t}\n\t}\n\t\n\tpublic function reset() {\n\t\t$this->html = null;\n\t\t$this->readability = null;\n\t\t$this->config = null;\n\t\t$this->title = null;\n\t\t$this->body = null;\n\t\t$this->author = array();\n\t\t$this->language = null;\n\t\t$this->date = null;\n\t\t$this->nextPageUrl = null;\n\t\t$this->success = false;\n\t}\n\n\tpublic function findHostUsingFingerprints($html) {\n\t\t$this->debug('Checking fingerprints...');\n\t\t$head = substr($html, 0, 8000);\n\t\tforeach ($this->fingerprints as $_fp => $_fphost) {\n\t\t\t$lookin = 'html';\n\t\t\tif (is_array($_fphost)) {\n\t\t\t\tif (isset($_fphost['head']) && $_fphost['head']) {\n\t\t\t\t\t$lookin = 'head';\n\t\t\t\t}\n\t\t\t\t$_fphost = $_fphost['hostname'];\n\t\t\t}\n\t\t\tif (strpos($$lookin, $_fp) !== false) {\n\t\t\t\t$this->debug(\"Found match: $_fphost\");\n\t\t\t\treturn $_fphost;\n\t\t\t}\n\t\t}\n\t\t$this->debug('No fingerprint matches');\n\t\treturn false;\n\t}\n\t\n\t// returns SiteConfig instance (joined in order: exact match, wildcard, fingerprint, global, default)\n\tpublic function buildSiteConfig($url, $html='', $add_to_cache=true) {\n\t\t// extract host name\n\t\t$host = @parse_url($url, PHP_URL_HOST);\n\t\t$host = strtolower($host);\n\t\tif (substr($host, 0, 4) == 'www.') $host = substr($host, 4);\n\t\t// is merged version already cached?\n\t\tif (SiteConfig::is_cached(\"$host.merged\")) {\n\t\t\t$this->debug(\"Returning cached and merged site config for $host\");\n\t\t\treturn SiteConfig::build(\"$host.merged\");\n\t\t}\n\t\t// let's build from site_config/custom/ and standard/\n\t\t$config = SiteConfig::build($host);\n\t\tif ($add_to_cache && $config && !SiteConfig::is_cached(\"$host\")) {\n\t\t\tSiteConfig::add_to_cache($host, $config);\n\t\t}\n\t\t// if no match, use defaults\n\t\tif (!$config) $config = new SiteConfig();\n\t\t// load fingerprint config?\n\t\tif ($config->autodetect_on_failure()) {\n\t\t\t// check HTML for fingerprints\n\t\t\tif (!empty($this->fingerprints) && ($_fphost = $this->findHostUsingFingerprints($html))) {\n\t\t\t\tif ($config_fingerprint = SiteConfig::build($_fphost)) {\n\t\t\t\t\t$this->debug(\"Appending site config settings from $_fphost (fingerprint match)\");\n\t\t\t\t\t$config->append($config_fingerprint);\n\t\t\t\t\tif ($add_to_cache && !SiteConfig::is_cached($_fphost)) {\n\t\t\t\t\t\t//$config_fingerprint->cache_in_apc = true;\n\t\t\t\t\t\tSiteConfig::add_to_cache($_fphost, $config_fingerprint);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// load global config?\n\t\tif ($config->autodetect_on_failure()) {\n\t\t\tif ($config_global = SiteConfig::build('global', true)) {\n\t\t\t\t$this->debug('Appending site config settings from global.txt');\n\t\t\t\t$config->append($config_global);\n\t\t\t\tif ($add_to_cache && !SiteConfig::is_cached('global')) {\n\t\t\t\t\t//$config_global->cache_in_apc = true;\n\t\t\t\t\tSiteConfig::add_to_cache('global', $config_global);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// store copy of merged config\n\t\tif ($add_to_cache) {\n\t\t\t// do not store in APC if wildcard match\n\t\t\t$use_apc = ($host == $config->cache_key);\n\t\t\t$config->cache_key = null;\n\t\t\tSiteConfig::add_to_cache(\"$host.merged\", $config, $use_apc);\n\t\t}\n\t\treturn $config;\n\t}\n\t\n\t// returns true on success, false on failure\n\t// $smart_tidy indicates that if tidy is used and no results are produced, we will\n\t// try again without it. Tidy helps us deal with PHP's patchy HTML parsing most of the time\n\t// but it has problems of its own which we try to avoid with this option.\n\tpublic function process($html, $url, $smart_tidy=true) {\n\t\t$this->reset();\n\t\t$this->config = $this->buildSiteConfig($url, $html);\n\t\t\n\t\t// do string replacements\n\t\tif (!empty($this->config->find_string)) {\n\t\t\tif (count($this->config->find_string) == count($this->config->replace_string)) {\n\t\t\t\t$html = str_replace($this->config->find_string, $this->config->replace_string, $html, $_count);\n\t\t\t\t$this->debug(\"Strings replaced: $_count (find_string and/or replace_string)\");\n\t\t\t} else {\n\t\t\t\t$this->debug('Skipped string replacement - incorrect number of find-replace strings in site config');\n\t\t\t}\n\t\t\tunset($_count);\n\t\t}\n\n\t\t// load and parse html\n\t\t$_parser = $this->config->parser();\n\t\tif (!in_array($_parser, $this->allowedParsers)) {\n\t\t\t$this->debug(\"HTML parser $_parser not listed, using libxml instead\");\n\t\t\t$_parser = 'libxml';\n\t\t}\n\t\t$this->debug(\"Attempting to parse HTML with $_parser\");\n\t\t$this->readability = new Readability($html, $url, $_parser, $this->config->tidy() && $smart_tidy);\n\t\t$tidied = $this->readability->tidied;\n\t\t\n\t\t// we use xpath to find elements in the given HTML document; see http://en.wikipedia.org/wiki/XPath_1.0\n\t\t$xpath = new DOMXPath($this->readability->dom);\n\n\t\t// skip entries (using xpath expressions)\n\t\tforeach ($this->config->skip_entry as $pattern) {\n\t\t\t$elems = @$xpath->evaluate($pattern, $this->readability->dom);\n\t\t\t// check for matches\n\t\t\tif (is_string($elems) || ($elems instanceof DOMNodeList && $elems->length > 0)) {\n\t\t\t\t$this->debug('Skipping entry on pattern.');\n\t\t\t\t$this->debug(\"...XPath match: $pattern\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// try to get next page link\n\t\tforeach ($this->config->next_page_link as $pattern) {\n\t\t\t$elems = @$xpath->evaluate($pattern, $this->readability->dom);\n\t\t\tif (is_string($elems)) {\n\t\t\t\t$this->nextPageUrl = trim($elems);\n\t\t\t\tbreak;\n\t\t\t} elseif ($elems instanceof DOMNodeList && $elems->length > 0) {\n\t\t\t\tforeach ($elems as $item) {\n\t\t\t\t\tif ($item instanceof DOMElement && $item->hasAttribute('href')) {\n\t\t\t\t\t\t$this->nextPageUrl = $item->getAttribute('href');\n\t\t\t\t\t\tbreak 2;\n\t\t\t\t\t} elseif ($item instanceof DOMAttr && $item->value) {\n\t\t\t\t\t\t$this->nextPageUrl = $item->value;\n\t\t\t\t\t\tbreak 2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t// try to get title\n\t\tforeach ($this->config->title as $pattern) {\n\t\t\t// $this->debug(\"Trying to get title $pattern\");\n\t\t\t$elems = @$xpath->evaluate($pattern, $this->readability->dom);\n\t\t\tif (is_string($elems)) {\n\t\t\t\t$this->title = trim($elems);\n\t\t\t\t$this->debug('Title expression evaluated as string: '.$this->title);\n\t\t\t\t$this->debug(\"...XPath match: $pattern\");\n\t\t\t\tbreak;\n\t\t\t} elseif ($elems instanceof DOMNodeList && $elems->length > 0) {\n\t\t\t\t$this->title = $elems->item(0)->textContent;\n\t\t\t\t$this->debug('Title matched: '.$this->title);\n\t\t\t\t$this->debug(\"...XPath match: $pattern\");\n\t\t\t\t// remove title from document\n\t\t\t\ttry {\n\t\t\t\t\t@$elems->item(0)->parentNode->removeChild($elems->item(0));\n\t\t\t\t} catch (DOMException $e) {\n\t\t\t\t\t// do nothing\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// try to get author (if it hasn't already been set)\n\t\tif (empty($this->author)) {\n\t\t\tforeach ($this->config->author as $pattern) {\n\t\t\t\t$elems = @$xpath->evaluate($pattern, $this->readability->dom);\n\t\t\t\tif (is_string($elems)) {\n\t\t\t\t\tif (trim($elems) != '') {\n\t\t\t\t\t\t$this->author[] = trim($elems);\n\t\t\t\t\t\t$this->debug('Author expression evaluated as string: '.trim($elems));\n\t\t\t\t\t\t$this->debug(\"...XPath match: $pattern\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} elseif ($elems instanceof DOMNodeList && $elems->length > 0) {\n\t\t\t\t\tforeach ($elems as $elem) {\n\t\t\t\t\t\tif (!isset($elem->parentNode)) continue;\n\t\t\t\t\t\t$this->author[] = trim($elem->textContent);\n\t\t\t\t\t\t$this->debug('Author matched: '.trim($elem->textContent));\n\t\t\t\t\t}\n\t\t\t\t\tif (!empty($this->author)) {\n\t\t\t\t\t\t$this->debug(\"...XPath match: $pattern\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t// try to get language\n\t\t$_lang_xpath = array('//html[@lang]/@lang', '//body[@lang]/@lang', '//meta[@name=\"DC.language\"]/@content');\n\t\tforeach ($_lang_xpath as $pattern) {\n\t\t\t$elems = @$xpath->evaluate($pattern, $this->readability->dom);\n\t\t\tif (is_string($elems)) {\n\t\t\t\tif (trim($elems) != '') {\n\t\t\t\t\t$this->language = trim($elems);\n\t\t\t\t\t$this->debug('Language matched: '.$this->language);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} elseif ($elems instanceof DOMNodeList && $elems->length > 0) {\n\t\t\t\tforeach ($elems as $elem) {\n\t\t\t\t\tif (!isset($elem->parentNode)) continue;\n\t\t\t\t\t$this->language = trim($elem->textContent);\n\t\t\t\t\t$this->debug('Language matched: '.$this->language);\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\tif ($this->language) break;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// try to get date\n\t\tforeach ($this->config->date as $pattern) {\n\t\t\t$elems = @$xpath->evaluate($pattern, $this->readability->dom);\n\t\t\tif (is_string($elems)) {\n\t\t\t\t$this->date = strtotime(trim($elems, \"; \\t\\n\\r\\0\\x0B\"));\t\t\t\t\n\t\t\t} elseif ($elems instanceof DOMNodeList && $elems->length > 0) {\n\t\t\t\t$this->date = $elems->item(0)->textContent;\n\t\t\t\t$this->date = strtotime(trim($this->date, \"; \\t\\n\\r\\0\\x0B\"));\n\t\t\t\t// remove date from document\n\t\t\t\t// $elems->item(0)->parentNode->removeChild($elems->item(0));\n\t\t\t}\n\t\t\tif (!$this->date) {\n\t\t\t\t$this->date = null;\n\t\t\t} else {\n\t\t\t\t$this->debug('Date matched: '.date('Y-m-d H:i:s', $this->date));\n\t\t\t\t$this->debug(\"...XPath match: $pattern\");\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// strip elements (using xpath expressions)\n\t\tforeach ($this->config->strip as $pattern) {\n\t\t\t$elems = @$xpath->query($pattern, $this->readability->dom);\n\t\t\t// check for matches\n\t\t\tif ($elems && $elems->length > 0) {\n\t\t\t\t$this->debug('Stripping '.$elems->length.' elements (strip)');\n\t\t\t\tfor ($i=$elems->length-1; $i >= 0; $i--) {\n\t\t\t\t\t$elems->item($i)->parentNode->removeChild($elems->item($i));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t// strip elements (using id and class attribute values)\n\t\tforeach ($this->config->strip_id_or_class as $string) {\n\t\t\t$string = strtr($string, array(\"'\"=>'', '\"'=>''));\n\t\t\t$elems = @$xpath->query(\"//*[contains(@class, '$string') or contains(@id, '$string')]\", $this->readability->dom);\n\t\t\t// check for matches\n\t\t\tif ($elems && $elems->length > 0) {\n\t\t\t\t$this->debug('Stripping '.$elems->length.' elements (strip_id_or_class)');\n\t\t\t\tfor ($i=$elems->length-1; $i >= 0; $i--) {\n\t\t\t\t\t$elems->item($i)->parentNode->removeChild($elems->item($i));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t// strip images (using src attribute values)\n\t\tforeach ($this->config->strip_image_src as $string) {\n\t\t\t$string = strtr($string, array(\"'\"=>'', '\"'=>''));\n\t\t\t$elems = @$xpath->query(\"//img[contains(@src, '$string')]\", $this->readability->dom);\n\t\t\t// check for matches\n\t\t\tif ($elems && $elems->length > 0) {\n\t\t\t\t$this->debug('Stripping '.$elems->length.' image elements');\n\t\t\t\tfor ($i=$elems->length-1; $i >= 0; $i--) {\n\t\t\t\t\t$elems->item($i)->parentNode->removeChild($elems->item($i));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// strip elements using Readability.com and Instapaper.com ignore class names\n\t\t// .entry-unrelated and .instapaper_ignore\n\t\t// See https://www.readability.com/publishers/guidelines/#view-plainGuidelines\n\t\t// and http://blog.instapaper.com/post/730281947\n\t\t$elems = @$xpath->query(\"//*[contains(concat(' ',normalize-space(@class),' '),' entry-unrelated ') or contains(concat(' ',normalize-space(@class),' '),' instapaper_ignore ')]\", $this->readability->dom);\n\t\t// check for matches\n\t\tif ($elems && $elems->length > 0) {\n\t\t\t$this->debug('Stripping '.$elems->length.' .entry-unrelated,.instapaper_ignore elements');\n\t\t\tfor ($i=$elems->length-1; $i >= 0; $i--) {\n\t\t\t\t$elems->item($i)->parentNode->removeChild($elems->item($i));\n\t\t\t}\n\t\t}\n\t\t\n\t\t// strip elements that contain style 'display: none' or 'visibility:hidden'\n\t\t$elems = @$xpath->query(\"//*[contains(@style,'display:none') or contains(@style,'visibility:hidden')]\", $this->readability->dom);\n\t\t// check for matches\n\t\tif ($elems && $elems->length > 0) {\n\t\t\t$this->debug('Stripping '.$elems->length.' elements with inline display:none or visibility:hidden style');\n\t\t\tfor ($i=$elems->length-1; $i >= 0; $i--) {\n\t\t\t\t$elems->item($i)->parentNode->removeChild($elems->item($i));\n\t\t\t}\n\t\t}\n\t\t\n\t\t// try to get body\n\t\tforeach ($this->config->body as $pattern) {\n\t\t\t$elems = @$xpath->query($pattern, $this->readability->dom);\n\t\t\t$this->debug(\"Matched $elems->length content element(s)\");\n\t\t\t// check for matches\n\t\t\tif ($elems && $elems->length > 0) {\n\t\t\t\t$this->debug('Body matched');\n\t\t\t\t$this->debug(\"...XPath match: $pattern\");\n\t\t\t\tif ($elems->length == 1) {\t\t\t\t\n\t\t\t\t\t$this->body = $elems->item(0);\n\t\t\t\t\t// prune (clean up elements that may not be content)\n\t\t\t\t\tif ($this->config->prune()) {\n\t\t\t\t\t\t$this->debug('...pruning content');\n\t\t\t\t\t\t$this->readability->prepArticle($this->body);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\t$this->body = $this->readability->dom->createElement('div');\n\t\t\t\t\t$this->debug($elems->length.' body elems found');\n\t\t\t\t\t$len = 0;\n\t\t\t\t\tforeach ($elems as $elem) {\n\t\t\t\t\t\tif (!isset($elem->parentNode)) continue;\n\t\t\t\t\t\t$isDescendant = false;\n\t\t\t\t\t\tforeach ($this->body->childNodes as $parent) {\n\t\t\t\t\t\t\tif ($this->isDescendant($parent, $elem)) {\n\t\t\t\t\t\t\t\t$isDescendant = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ($isDescendant) {\n\t\t\t\t\t\t\t$this->debug('...element is child of another body element, skipping.');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// prune (clean up elements that may not be content)\n\t\t\t\t\t\t\tif ($this->config->prune()) {\n\t\t\t\t\t\t\t\t$this->debug('...pruning content');\n\t\t\t\t\t\t\t\t$this->readability->prepArticle($elem);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ($elem) {\n\t\t\t\t\t\t\t\t$len++;\n\t\t\t\t\t\t\t\t$this->body->appendChild($elem);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t$this->debug('...'.$len.' elements added to body');\n\t\t\t\t\tunset($len);\n\t\t\t\t\tif ($this->body->hasChildNodes()) break;\n\t\t\t\t}\n\t\t\t}\n\t\t}\t\t\n\t\t\n\t\t// auto detect?\n\t\t$detect_title = $detect_body = $detect_author = $detect_date = false;\n\t\t// detect title?\n\t\tif (!isset($this->title)) {\n\t\t\tif (empty($this->config->title) || $this->config->autodetect_on_failure()) {\n\t\t\t\t$detect_title = true;\n\t\t\t}\n\t\t}\n\t\t// detect body?\n\t\tif (!isset($this->body)) {\n\t\t\tif (empty($this->config->body) || $this->config->autodetect_on_failure()) {\n\t\t\t\t$detect_body = true;\n\t\t\t}\n\t\t}\n\t\t// detect author?\n\t\tif (empty($this->author)) {\n\t\t\tif (empty($this->config->author) || $this->config->autodetect_on_failure()) {\n\t\t\t\t$detect_author = true;\n\t\t\t}\n\t\t}\n\t\t// detect date?\n\t\tif (!isset($this->date)) {\n\t\t\tif (empty($this->config->date) || $this->config->autodetect_on_failure()) {\n\t\t\t\t$detect_date = true;\n\t\t\t}\n\t\t}\n\n\t\t// check for hNews\n\t\tif ($detect_title || $detect_body) {\n\t\t\t// check for hentry\n\t\t\t$elems = @$xpath->query(\"//*[contains(concat(' ',normalize-space(@class),' '),' hentry ')]\", $this->readability->dom);\n\t\t\tif ($elems && $elems->length > 0) {\n\t\t\t\t$this->debug('hNews: found hentry');\n\t\t\t\t$hentry = $elems->item(0);\n\t\t\t\t\n\t\t\t\tif ($detect_title) {\n\t\t\t\t\t// check for entry-title\n\t\t\t\t\t$elems = @$xpath->query(\".//*[contains(concat(' ',normalize-space(@class),' '),' entry-title ')]\", $hentry);\n\t\t\t\t\tif ($elems && $elems->length > 0) {\n\t\t\t\t\t\t$this->title = $elems->item(0)->textContent;\n\t\t\t\t\t\t$this->debug('hNews: found entry-title: '.$this->title);\n\t\t\t\t\t\t// remove title from document\n\t\t\t\t\t\t$elems->item(0)->parentNode->removeChild($elems->item(0));\n\t\t\t\t\t\t$detect_title = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ($detect_date) {\n\t\t\t\t\t// check for time element with pubdate attribute\n\t\t\t\t\t$elems = @$xpath->query(\".//time[@pubdate] | .//abbr[contains(concat(' ',normalize-space(@class),' '),' published ')]\", $hentry);\n\t\t\t\t\tif ($elems && $elems->length > 0) {\n\t\t\t\t\t\t$this->date = strtotime(trim($elems->item(0)->textContent));\n\t\t\t\t\t\t// remove date from document\n\t\t\t\t\t\t//$elems->item(0)->parentNode->removeChild($elems->item(0));\n\t\t\t\t\t\tif ($this->date) {\n\t\t\t\t\t\t\t$this->debug('hNews: found publication date: '.date('Y-m-d H:i:s', $this->date));\n\t\t\t\t\t\t\t$detect_date = false;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$this->date = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ($detect_author) {\n\t\t\t\t\t// check for time element with pubdate attribute\n\t\t\t\t\t$elems = @$xpath->query(\".//*[contains(concat(' ',normalize-space(@class),' '),' vcard ') and (contains(concat(' ',normalize-space(@class),' '),' author ') or contains(concat(' ',normalize-space(@class),' '),' byline '))]\", $hentry);\n\t\t\t\t\tif ($elems && $elems->length > 0) {\n\t\t\t\t\t\t$author = $elems->item(0);\n\t\t\t\t\t\t$fn = @$xpath->query(\".//*[contains(concat(' ',normalize-space(@class),' '),' fn ')]\", $author);\n\t\t\t\t\t\tif ($fn && $fn->length > 0) {\n\t\t\t\t\t\t\tforeach ($fn as $_fn) {\n\t\t\t\t\t\t\t\tif (trim($_fn->textContent) != '') {\n\t\t\t\t\t\t\t\t\t$this->author[] = trim($_fn->textContent);\n\t\t\t\t\t\t\t\t\t$this->debug('hNews: found author: '.trim($_fn->textContent));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (trim($author->textContent) != '') {\n\t\t\t\t\t\t\t\t$this->author[] = trim($author->textContent);\n\t\t\t\t\t\t\t\t$this->debug('hNews: found author: '.trim($author->textContent));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$detect_author = empty($this->author);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// check for entry-content.\n\t\t\t\t// according to hAtom spec, if there are multiple elements marked entry-content,\n\t\t\t\t// we include all of these in the order they appear - see http://microformats.org/wiki/hatom#Entry_Content\n\t\t\t\tif ($detect_body) {\n\t\t\t\t\t$elems = @$xpath->query(\".//*[contains(concat(' ',normalize-space(@class),' '),' entry-content ')]\", $hentry);\n\t\t\t\t\tif ($elems && $elems->length > 0) {\n\t\t\t\t\t\t$this->debug('hNews: found entry-content');\n\t\t\t\t\t\tif ($elems->length == 1) {\n\t\t\t\t\t\t\t// what if it's empty? (some sites misuse hNews - place their content outside an empty entry-content element)\n\t\t\t\t\t\t\t$e = $elems->item(0);\n\t\t\t\t\t\t\tif (strcasecmp($e->tagName, 'img') == 0 || (trim($e->textContent) != '')) {\n\t\t\t\t\t\t\t\t$this->body = $elems->item(0);\n\t\t\t\t\t\t\t\t// prune (clean up elements that may not be content)\n\t\t\t\t\t\t\t\tif ($this->config->prune()) {\n\t\t\t\t\t\t\t\t\t$this->debug('Pruning content');\n\t\t\t\t\t\t\t\t\t$this->readability->prepArticle($this->body);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t$detect_body = false;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t$this->debug('hNews: skipping entry-content - appears not to contain content');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tunset($e);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$this->body = $this->readability->dom->createElement('div');\n\t\t\t\t\t\t\t$this->debug($elems->length.' entry-content elems found');\n\t\t\t\t\t\t\tforeach ($elems as $elem) {\n\t\t\t\t\t\t\t\tif (!isset($elem->parentNode)) continue;\n\t\t\t\t\t\t\t\t$isDescendant = false;\n\t\t\t\t\t\t\t\tforeach ($this->body->childNodes as $parent) {\n\t\t\t\t\t\t\t\t\tif ($this->isDescendant($parent, $elem)) {\n\t\t\t\t\t\t\t\t\t\t$isDescendant = true;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ($isDescendant) {\n\t\t\t\t\t\t\t\t\t$this->debug('Element is child of another body element, skipping.');\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// prune (clean up elements that may not be content)\n\t\t\t\t\t\t\t\t\tif ($this->config->prune()) {\n\t\t\t\t\t\t\t\t\t\t$this->debug('Pruning content');\n\t\t\t\t\t\t\t\t\t\t$this->readability->prepArticle($elem);\n\t\t\t\t\t\t\t\t\t}\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t$this->debug('Element added to body');\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t$this->body->appendChild($elem);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$detect_body = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// check for elements marked with instapaper_title\n\t\tif ($detect_title) {\n\t\t\t// check for instapaper_title\n\t\t\t$elems = @$xpath->query(\"//*[contains(concat(' ',normalize-space(@class),' '),' instapaper_title ')]\", $this->readability->dom);\n\t\t\tif ($elems && $elems->length > 0) {\n\t\t\t\t$this->title = $elems->item(0)->textContent;\n\t\t\t\t$this->debug('Title found (.instapaper_title): '.$this->title);\n\t\t\t\t// remove title from document\n\t\t\t\t$elems->item(0)->parentNode->removeChild($elems->item(0));\n\t\t\t\t$detect_title = false;\n\t\t\t}\n\t\t}\n\t\t// check for elements marked with instapaper_body\n\t\tif ($detect_body) {\n\t\t\t$elems = @$xpath->query(\"//*[contains(concat(' ',normalize-space(@class),' '),' instapaper_body ')]\", $this->readability->dom);\n\t\t\tif ($elems && $elems->length > 0) {\n\t\t\t\t$this->debug('body found (.instapaper_body)');\n\t\t\t\t$this->body = $elems->item(0);\n\t\t\t\t// prune (clean up elements that may not be content)\n\t\t\t\tif ($this->config->prune()) {\n\t\t\t\t\t$this->debug('Pruning content');\n\t\t\t\t\t$this->readability->prepArticle($this->body);\n\t\t\t\t}\n\t\t\t\t$detect_body = false;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Find author in rel=\"author\" marked element\n\t\t// We only use this if there's exactly one.\n\t\t// If there's more than one, it could indicate more than\n\t\t// one author, but it could also indicate that we're processing\n\t\t// a page listing different articles with different authors.\n\t\tif ($detect_author) {\n\t\t\t$elems = @$xpath->query(\"//a[contains(concat(' ',normalize-space(@rel),' '),' author ')]\", $this->readability->dom);\n\t\t\tif ($elems && $elems->length == 1) {\n\t\t\t\t$author = trim($elems->item(0)->textContent);\n\t\t\t\tif ($author != '') {\n\t\t\t\t\t$this->debug(\"Author found (rel=\\\"author\\\"): $author\");\n\t\t\t\t\t$this->author[] = $author;\n\t\t\t\t\t$detect_author = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Find date in pubdate marked time element\n\t\t// For the same reason given above, we only use this\n\t\t// if there's exactly one element.\n\t\tif ($detect_date) {\n\t\t\t$elems = @$xpath->query(\"//time[@pubdate]\", $this->readability->dom);\n\t\t\tif ($elems && $elems->length == 1) {\n\t\t\t\t$this->date = strtotime(trim($elems->item(0)->textContent));\n\t\t\t\t// remove date from document\n\t\t\t\t//$elems->item(0)->parentNode->removeChild($elems->item(0));\n\t\t\t\tif ($this->date) {\n\t\t\t\t\t$this->debug('Date found (pubdate marked time element): '.date('Y-m-d H:i:s', $this->date));\n\t\t\t\t\t$detect_date = false;\n\t\t\t\t} else {\n\t\t\t\t\t$this->date = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// still missing title or body, so we detect using Readability\n\t\tif ($detect_title || $detect_body) {\n\t\t\t$this->debug('Using Readability');\n\t\t\t// clone body if we're only using Readability for title (otherwise it may interfere with body element)\n\t\t\tif (isset($this->body)) $this->body = $this->body->cloneNode(true);\n\t\t\t$success = $this->readability->init();\n\t\t}\n\n\t\tif ($detect_title) {\n\t\t\t$this->title = $this->readability->getTitle()->textContent;\n\t\t\t$this->debug(\"Detected title \\\"$this->title\\\"\");\n\t\t}\n\t\tif ($detect_body && $success) {\n\t\t\t$this->debug('Detecting body');\n\t\t\t$this->body = $this->readability->getContent();\n\t\t\tif ($this->body->childNodes->length == 1 && $this->body->firstChild->nodeType === XML_ELEMENT_NODE) {\n\t\t\t\t$this->body = $this->body->firstChild;\n\t\t\t}\n\t\t\t// prune (clean up elements that may not be content)\n\t\t\tif ($this->config->prune()) {\n\t\t\t\t$this->debug('Pruning content');\n\t\t\t\t$this->readability->prepArticle($this->body);\n\t\t\t}\n\t\t}\n\t\tif (isset($this->body)) {\n\t\t\t// remove scripts\n\t\t\t$this->readability->removeScripts($this->body);\n\t\t\t// remove any h1-h6 elements that appear as first thing in the body\n\t\t\t// and which match our title\n\t\t\tif (isset($this->title) && ($this->title != '')) {\n\t\t\t\t$firstChild = $this->body->firstChild;\n\t\t\t\twhile ($firstChild->nodeType && ($firstChild->nodeType !== XML_ELEMENT_NODE)) {\n\t\t\t\t\t$firstChild = $firstChild->nextSibling;\n\t\t\t\t}\n\t\t\t\tif (($firstChild->nodeType === XML_ELEMENT_NODE)\n\t\t\t\t\t&& in_array(strtolower($firstChild->tagName), array('h1', 'h2', 'h3', 'h4', 'h5', 'h6'))\n\t\t\t\t\t&& (strtolower(trim($firstChild->textContent)) == strtolower(trim($this->title)))) {\n\t\t\t\t\t\t$this->body->removeChild($firstChild);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// prevent self-closing iframes\n\t\t\t$elems = $this->body->getElementsByTagName('iframe');\n\t\t\tfor ($i = $elems->length-1; $i >= 0; $i--) {\n\t\t\t\t$e = $elems->item($i);\n\t\t\t\tif (!$e->hasChildNodes()) {\n\t\t\t\t\t$e->appendChild($this->body->ownerDocument->createTextNode('[embedded content]'));\n\t\t\t\t}\n\t\t\t}\n\t\t\t// remove image lazy loading - WordPress plugin http://wordpress.org/extend/plugins/lazy-load/\n\t\t\t// the plugin replaces the src attribute to point to a 1x1 gif and puts the original src\n\t\t\t// inside the data-lazy-src attribute. It also places the original image inside a noscript element \n\t\t\t// next to the amended one.\n\t\t\t$elems = @$xpath->query(\"//img[@data-lazy-src]|//img[@data-src]\", $this->body);\n\t\t\tfor ($i = $elems->length-1; $i >= 0; $i--) {\n\t\t\t\t$e = $elems->item($i);\n\t\t\t\t// let's see if we can grab image from noscript\n\t\t\t\tif ($e->nextSibling !== null && $e->nextSibling->nodeName === 'noscript') {\n\t\t\t\t\t$_new_elem = $e->ownerDocument->createDocumentFragment();\n\t\t\t\t\t@$_new_elem->appendXML($e->nextSibling->innerHTML);\n\t\t\t\t\t$e->nextSibling->parentNode->replaceChild($_new_elem, $e->nextSibling);\n\t\t\t\t\t$e->parentNode->removeChild($e);\n\t\t\t\t} else {\n\t\t\t\t\t// Use data[-lazy]-src as src value\n\t\t\t\t\t$src = $e->getAttribute('data-lazy-src');\n\t\t\t\t\t$e->removeAttribute('data-lazy-src');\n\t\t\t\t\tif (!$src) {\n\t\t\t\t\t\t$src = $e->getAttribute('data-src');\n\t\t\t\t\t\t$e->removeAttribute('data-src');\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t\t$e->setAttribute('src', $src);\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t\t$this->success = true;\n\t\t}\n\n\t\t// if we've had no success and we've used tidy, there's a chance\n\t\t// that tidy has messed up. So let's try again without tidy...\n\t\tif (!$this->success && $tidied && $smart_tidy) {\n\t\t\t$this->debug('Trying again without tidy');\n\t\t\tunset($this->readability, $this->body, $xpath);\n\t\t\treturn $this->process($original_html, $url, false);\n\t\t}\n\n\t\tif ($this->success && $this->config->images_to_datauri()) {\n\t\t\t$this->debug('Converting images to data-URI');\n\t\t\t$this->readability->imageCache->cacheFromDocument($this->body);\n\t\t}\n\n\t\treturn $this->success;\n\t}\n\t\n\tprivate function isDescendant(DOMElement $parent, DOMElement $child) {\n\t\t$node = $child->parentNode;\n\t\twhile ($node != null) {\n\t\t\tif ($node->isSameNode($parent))\treturn true;\n\t\t\t$node = $node->parentNode;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic function getContent() {\n\t\treturn $this->body;\n\t}\n\t\n\tpublic function getTitle() {\n\t\treturn $this->title;\n\t}\n\t\n\tpublic function getAuthors() {\n\t\treturn $this->author;\n\t}\n\t\n\tpublic function getLanguage() {\n\t\treturn $this->language;\n\t}\n\t\n\tpublic function getDate() {\n\t\treturn $this->date;\n\t}\n\t\n\tpublic function getSiteConfig() {\n\t\treturn $this->config;\n\t}\n\t\n\tpublic function getNextPageUrl() {\n\t\treturn $this->nextPageUrl;\n\t}\n}"
  },
  {
    "path": "libraries/content-extractor/SiteConfig.php",
    "content": "<?php\n/**\n * Site Config\n * \n * Each instance of this class should hold extraction patterns and other directives\n * for a website. See ContentExtractor class to see how it's used.\n * \n * @version 0.8\n * @date 2013-04-16\n * @author Keyvan Minoukadeh\n * @copyright 2013 Keyvan Minoukadeh\n * @license http://www.gnu.org/licenses/agpl-3.0.html AGPL v3\n */\n\nclass SiteConfig\n{\n\t// Use first matching element as title (0 or more xpath expressions)\n\tpublic $title = array();\n\t\n\t// Use first matching element as body (0 or more xpath expressions)\n\tpublic $body = array();\n\t\n\t// Skips entries matching these xpath expressions (0 or more)\n\tpublic $skip_entry = array();\n\n\t// Use first matching element as author (0 or more xpath expressions)\n\tpublic $author = array();\n\t\n\t// Use first matching element as date (0 or more xpath expressions)\n\tpublic $date = array();\n\t\n\t// Strip elements matching these xpath expressions (0 or more)\n\tpublic $strip = array();\n\t\n\t// Strip elements which contain these strings (0 or more) in the id or class attribute \n\tpublic $strip_id_or_class = array();\n\t\n\t// Strip images which contain these strings (0 or more) in the src attribute \n\tpublic $strip_image_src = array();\n\t\n\t// Additional HTTP headers to send\n\t// NOT YET USED\n\tpublic $http_header = array();\n\t\n\t// Process HTML with tidy before creating DOM (bool or null if undeclared)\n\tpublic $tidy = null;\n\t\n\tprotected $default_tidy = true; // used if undeclared\n\t\n\t// Autodetect title/body if xpath expressions fail to produce results.\n\t// Note that this applies to title and body separately, ie. \n\t//   * if we get a body match but no title match, this option will determine whether we autodetect title \n\t//   * if neither match, this determines whether we autodetect title and body.\n\t// Also note that this only applies when there is at least one xpath expression in title or body, ie.\n\t//   * if title and body are both empty (no xpath expressions), this option has no effect (both title and body will be auto-detected)\n\t//   * if there's an xpath expression for title and none for body, body will be auto-detected and this option will determine whether we auto-detect title if the xpath expression for it fails to produce results.\n\t// Usage scenario: you want to extract something specific from a set of URLs, e.g. a table, and if the table is not found, you want to ignore the entry completely. Auto-detection is unlikely to succeed here, so you construct your patterns and set this option to false. Another scenario may be a site where auto-detection has proven to fail (or worse, picked up the wrong content).\n\t// bool or null if undeclared\n\tpublic $autodetect_on_failure = null;\n\tprotected $default_autodetect_on_failure = true; // used if undeclared\n\t\n\t// Clean up content block - attempt to remove elements that appear to be superfluous\n\t// bool or null if undeclared\n\tpublic $prune = null;\n\tprotected $default_prune = true; // used if undeclared\n\n\t// Converts images to data-URI format\n\tpublic $images_to_datauri = null;\n\tprotected $default_images_to_datauri = false; // used if undeclared\n\t\n\t// Test URL - if present, can be used to test the config above\n\tpublic $test_url = array();\n\t\n\t// Single-page link - should identify a link element or URL pointing to the page holding the entire article\n\t// This is useful for sites which split their articles across multiple pages. Links to such pages tend to \n\t// display the first page with links to the other pages at the bottom. Often there is also a link to a page\n\t// which displays the entire article on one page (e.g. 'print view').\n\t// This should be an XPath expression identifying the link to that page. If present and we find a match,\n\t// we will retrieve that page and the rest of the options in this config will be applied to the new page.\n\tpublic $single_page_link = array();\n\t\n\tpublic $next_page_link = array();\n\t\n\t// Single-page link in feed? - same as above, but patterns applied to item description HTML taken from feed\n\tpublic $single_page_link_in_feed = array();\n\t\n\t// Which parser to use for turning raw HTML into a DOMDocument (either 'libxml' or 'html5lib')\n\t// string or null if undeclared\n\tpublic $parser = null;\n\tprotected $default_parser = 'libxml'; // used if undeclared\n\t\n\t// Strings to search for in HTML before processing begins (used with $replace_string)\n\tpublic $find_string = array();\n\t// Strings to replace those found in $find_string before HTML processing begins\n\tpublic $replace_string = array();\n\t\n\t// the options below cannot be set in the config files which this class represents\n\t\n\t//public $cache_in_apc = false; // used to decide if we should cache in apc or not\n\tpublic $cache_key = null;\n\tpublic static $debug = false;\n\tprotected static $apc = false;\n\tprotected static $config_path;\n\tprotected static $config_path_fallback;\n\tprotected static $config_cache = array();\n\tconst HOSTNAME_REGEX = '/^(([a-zA-Z0-9-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9-]*[A-Za-z0-9])$/';\n\t\n\tprotected static function debug($msg) {\n\t\tif (self::$debug) {\n\t\t\t//$mem = round(memory_get_usage()/1024, 2);\n\t\t\t//$memPeak = round(memory_get_peak_usage()/1024, 2);\n\t\t\techo '* ',$msg,\"<br />\";\n\t\t\t//echo ' - mem used: ',$mem,\" (peak: $memPeak)\\n\";\n\t\t\techo \"\\n\";\n\t\t\tob_flush();\n\t\t\tflush();\n\t\t}\n\t}\n\t\n\t// enable APC caching of certain site config files?\n\t// If enabled the following site config files will be \n\t// cached in APC cache (when requested for first time):\n\t// * anything in site_config/custom/ and its corresponding file in site_config/standard/\n\t// * the site config files associated with HTML fingerprints\n\t// * the global site config file\n\t// returns true if enabled, false otherwise\n\tpublic static function use_apc($apc=true) {\n\t\tif (!function_exists('apc_add')) {\n\t\t\tif ($apc) self::debug('APC will not be used (function apc_add does not exist)');\n\t\t\treturn false;\n\t\t}\n\t\tself::$apc = $apc;\n\t\treturn $apc;\n\t}\n\t\n\t// return bool or null\n\tpublic function tidy($use_default=true) {\n\t\tif ($use_default) return (isset($this->tidy)) ? $this->tidy : $this->default_tidy;\n\t\treturn $this->tidy;\n\t}\n\t\n\t// return bool or null\n\tpublic function prune($use_default=true) {\n\t\tif ($use_default) return (isset($this->prune)) ? $this->prune : $this->default_prune;\n\t\treturn $this->prune;\n\t}\n\n\t// return bool or null\n\tpublic function images_to_datauri($use_default=true) {\n\t\tif ($use_default) return (isset($this->images_to_datauri)) ? $this->images_to_datauri : $this->default_images_to_datauri;\n\t\treturn $this->images_to_datauri;\n\t}\n\t\n\t// return string or null\n\tpublic function parser($use_default=true) {\n\t\tif ($use_default) return (isset($this->parser)) ? $this->parser : $this->default_parser;\n\t\treturn $this->parser;\n\t}\n\n\t// return bool or null\n\tpublic function autodetect_on_failure($use_default=true) {\n\t\tif ($use_default) return (isset($this->autodetect_on_failure)) ? $this->autodetect_on_failure : $this->default_autodetect_on_failure;\n\t\treturn $this->autodetect_on_failure;\n\t}\n\t\n\tpublic static function set_config_path($path, $fallback=null) {\n\t\tself::$config_path = $path;\n\t\tself::$config_path_fallback = $fallback;\n\t}\n\t\n\tpublic static function add_to_cache($key, SiteConfig $config, $use_apc=true) {\n\t\t$key = strtolower($key);\n\t\tif (substr($key, 0, 4) == 'www.') $key = substr($key, 4);\n\t\tif ($config->cache_key) $key = $config->cache_key;\n\t\tself::$config_cache[$key] = $config;\n\t\tif (self::$apc && $use_apc) {\n\t\t\tself::debug(\"Adding site config to APC cache with key sc.$key\");\n\t\t\tapc_add(\"sc.$key\", $config);\n\t\t}\n\t\tself::debug(\"Cached site config with key $key\");\n\t}\n\t\n\tpublic static function is_cached($key) {\n\t\t$key = strtolower($key);\n\t\tif (substr($key, 0, 4) == 'www.') $key = substr($key, 4);\n\t\tif (array_key_exists($key, self::$config_cache)) {\n\t\t\treturn true;\n\t\t} elseif (self::$apc && (bool)apc_fetch(\"sc.$key\")) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\tpublic function append(SiteConfig $newconfig) {\n\t\t// check for commands where we accept multiple statements (no test_url)\n\t\tforeach (array('skip_entry', 'title', 'body', 'author', 'date', 'strip', 'strip_id_or_class', 'strip_image_src', 'single_page_link', 'single_page_link_in_feed', 'next_page_link', 'http_header') as $var) {\n\t\t\t$this->$var = array_unique(array_merge($this->$var, $newconfig->$var));\n\t\t}\n\t\t// check for single statement commands; we do not overwrite existing non null values\n\t\tforeach (array('tidy', 'prune', 'parser', 'autodetect_on_failure') as $var) {\n\t\t\tif ($this->$var === null) $this->$var = $newconfig->$var;\n\t\t}\n\t\t// treat find_string and replace_string separately (don't apply array_unique) (thanks fabrizio!)\n\t\tforeach (array('find_string', 'replace_string') as $var) {\n\t\t\t$this->$var = array_merge($this->$var, $newconfig->$var);\n\t\t}\n\t}\n\t\n\t// returns SiteConfig instance if an appropriate one is found, false otherwise\n\t// if $exact_host_match is true, we will not look for wildcard config matches\n\t// by default if host is 'test.example.org' we will look for and load '.example.org.txt' if it exists\n\tpublic static function build($host, $exact_host_match=false) {\n\t\t$host = strtolower($host);\n\t\tif (substr($host, 0, 4) == 'www.') $host = substr($host, 4);\n\t\tif (!$host || (strlen($host) > 200) || !preg_match(self::HOSTNAME_REGEX, ltrim($host, '.'))) return false;\n\t\t// check for site configuration\n\t\t$try = array($host);\n\t\t// should we look for wildcard matches \n\t\tif (!$exact_host_match) {\n\t\t\t$split = explode('.', $host);\n\t\t\tif (count($split) > 1) {\n\t\t\t\tarray_shift($split);\n\t\t\t\t$try[] = '.'.implode('.', $split);\n\t\t\t}\n\t\t}\n\t\t\n\t\t// look for site config file in primary folder\n\t\tself::debug(\". looking for site config for $host in primary folder\");\n\t\tforeach ($try as $h) {\n\t\t\tif (array_key_exists($h, self::$config_cache)) {\n\t\t\t\tself::debug(\"... site config for $h already loaded in this request\");\n\t\t\t\treturn self::$config_cache[$h];\n\t\t\t} elseif (self::$apc && ($sconfig = apc_fetch(\"sc.$h\"))) {\n\t\t\t\tself::debug(\"... site config for $h in APC cache\");\n\t\t\t\treturn $sconfig;\n\t\t\t} elseif (file_exists(self::$config_path.\"/$h.txt\")) {\n\t\t\t\tself::debug(\"... found site config ($h.txt)\");\n\t\t\t\t$file_primary = self::$config_path.\"/$h.txt\";\n\t\t\t\t$matched_name = $h;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// if we found site config, process it\n\t\tif (isset($file_primary)) {\n\t\t\t$config_lines = file($file_primary, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);\n\t\t\tif (!$config_lines || !is_array($config_lines)) return false;\n\t\t\t$config = self::build_from_array($config_lines);\n\t\t\t// if APC caching is available and enabled, mark this for cache\n\t\t\t//$config->cache_in_apc = true;\n\t\t\t$config->cache_key = $matched_name;\n\t\t\t\n\t\t\t// if autodetec on failure is off (on by default) we do not need to look\n\t\t\t// in secondary folder\n\t\t\tif (!$config->autodetect_on_failure()) {\n\t\t\t\tself::debug('... autodetect on failure is disabled (no other site config files will be loaded)');\n\t\t\t\treturn $config;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// look for site config file in secondary folder\n\t\tif (isset(self::$config_path_fallback)) {\n\t\t\tself::debug(\". looking for site config for $host in secondary folder\");\n\t\t\tforeach ($try as $h) {\n\t\t\t\tif (file_exists(self::$config_path_fallback.\"/$h.txt\")) {\n\t\t\t\t\tself::debug(\"... found site config in secondary folder ($h.txt)\");\n\t\t\t\t\t$file_secondary = self::$config_path_fallback.\"/$h.txt\";\n\t\t\t\t\t$matched_name = $h;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!isset($file_secondary)) {\n\t\t\t\tself::debug(\"... no site config match in secondary folder\");\n\t\t\t}\n\t\t}\n\t\t\n\t\t// return false if no config file found\n\t\tif (!isset($file_primary) && !isset($file_secondary)) {\n\t\t\tself::debug(\"... no site config match for $host\");\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\t// return primary config if secondary not found\n\t\tif (!isset($file_secondary) && isset($config)) {\n\t\t\treturn $config;\n\t\t}\n\t\t\n\t\t// process secondary config file\n\t\t$config_lines = file($file_secondary, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);\n\t\tif (!$config_lines || !is_array($config_lines)) {\n\t\t\t// failed to process secondary\n\t\t\tif (isset($config)) {\n\t\t\t\t// return primary config\n\t\t\t\treturn $config;\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// merge with primary and return\n\t\tif (isset($config)) {\n\t\t\tself::debug('. merging config files');\n\t\t\t$config->append(self::build_from_array($config_lines));\n\t\t\treturn $config;\n\t\t} else {\n\t\t\t// return just secondary\n\t\t\t$config = self::build_from_array($config_lines);\n\t\t\t// if APC caching is available and enabled, mark this for cache\n\t\t\t//$config->cache_in_apc = true;\n\t\t\t$config->cache_key = $matched_name;\n\t\t\treturn $config;\n\t\t}\n\t}\n\t\n\tpublic static function build_from_array(array $lines) {\n\t\t$config = new SiteConfig();\n\t\tforeach ($lines as $line) {\n\t\t\t$line = trim($line);\n\t\t\t\n\t\t\t// skip comments, empty lines\n\t\t\tif ($line == '' || $line[0] == '#') continue;\n\t\t\t\n\t\t\t// get command\n\t\t\t$command = explode(':', $line, 2);\n\t\t\t// if there's no colon ':', skip this line\n\t\t\tif (count($command) != 2) continue;\n\t\t\t$val = trim($command[1]);\n\t\t\t$command = trim($command[0]);\n\t\t\tif ($command == '' || $val == '') continue;\n\t\t\t\n\t\t\t// check for commands where we accept multiple statements\n\t\t\tif (in_array($command, array('skip_entry', 'title', 'body', 'author', 'date', 'strip', 'strip_id_or_class', 'strip_image_src', 'single_page_link', 'single_page_link_in_feed', 'next_page_link', 'http_header', 'test_url', 'find_string', 'replace_string'))) {\n\t\t\t\tarray_push($config->$command, $val);\n\t\t\t// check for single statement commands that evaluate to true or false\n\t\t\t} elseif (in_array($command, array('images_to_datauri', 'tidy', 'prune', 'autodetect_on_failure'))) {\n\t\t\t\t$config->$command = ($val == 'yes' || $val == 'true');\n\t\t\t// check for single statement commands stored as strings\n\t\t\t} elseif (in_array($command, array('parser'))) {\n\t\t\t\t$config->$command = $val;\n\t\t\t// check for replace_string(find): replace\n\t\t\t} elseif ((substr($command, -1) == ')') && preg_match('!^([a-z0-9_]+)\\((.*?)\\)$!i', $command, $match)) {\n\t\t\t\tif (in_array($match[1], array('replace_string'))) {\n\t\t\t\t\t$command = $match[1];\n\t\t\t\t\tarray_push($config->find_string, $match[2]);\n\t\t\t\t\tarray_push($config->$command, $val);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn $config;\n\t}\n}"
  },
  {
    "path": "libraries/feedwriter/FeedItem.php",
    "content": "<?php\n /**\n * Univarsel Feed Writer\n * \n * FeedItem class - Used as feed element in FeedWriter class\n *\n * @package         UnivarselFeedWriter\n * @author          Anis uddin Ahmad <anisniit@gmail.com>\n * @link            http://www.ajaxray.com/projects/rss\n */\n class FeedItem\n {\n\tprivate $elements = array();    //Collection of feed elements\n\tprivate $version;\n\t\n\t/**\n\t* Constructor \n\t* \n\t* @param    contant     (RSS1/RSS2/ATOM) RSS2 is default. \n\t*/ \n\tfunction __construct($version = RSS2)\n\t{    \n\t\t$this->version = $version;\n\t}\n\n\t/**\n\t* Set element (overwrites existing elements with $elementName)\n\t* \n\t* @access   public\n\t* @param    srting  The tag name of an element\n\t* @param    srting  The content of tag\n\t* @param    array   Attributes(if any) in 'attrName' => 'attrValue' format\n\t* @return   void\n\t*/\n\tpublic function setElement($elementName, $content, $attributes = null)\n\t{\n\t\tif (isset($this->elements[$elementName])) {\n\t\t\tunset($this->elements[$elementName]);\n\t\t}\n\t\t$this->addElement($elementName, $content, $attributes);\n\t}\t\n\t\n\t/**\n\t* Add an element to elements array\n\t* \n\t* @access   public\n\t* @param    srting  The tag name of an element\n\t* @param    srting  The content of tag\n\t* @param    array   Attributes(if any) in 'attrName' => 'attrValue' format\n\t* @return   void\n\t*/\n\tpublic function addElement($elementName, $content, $attributes = null)\n\t{\n\t\t$i = 0;\n\t\tif (isset($this->elements[$elementName])) {\n\t\t\t$i = count($this->elements[$elementName]);\n\t\t} else {\n\t\t\t$this->elements[$elementName] = array();\n\t\t}\n\t\t$this->elements[$elementName][$i]['name']       = $elementName;\n\t\t$this->elements[$elementName][$i]['content']    = $content;\n\t\t$this->elements[$elementName][$i]['attributes'] = $attributes;\n\t}\n\t\n\t/**\n\t* Set multiple feed elements from an array. \n\t* Elements which have attributes cannot be added by this method\n\t* \n\t* @access   public\n\t* @param    array   array of elements in 'tagName' => 'tagContent' format.\n\t* @return   void\n\t*/\n\tpublic function addElementArray($elementArray)\n\t{\n\t\tif(! is_array($elementArray)) return;\n\t\tforeach ($elementArray as $elementName => $content) \n\t\t{\n\t\t\t$this->addElement($elementName, $content);\n\t\t}\n\t}\n\t\n\t/**\n\t* Return the collection of elements in this feed item\n\t* \n\t* @access   public\n\t* @return   array\n\t*/\n\tpublic function getElements()\n\t{\n\t\treturn $this->elements;\n\t}\n\t\n\t// Wrapper functions ------------------------------------------------------\n\t\n\t/**\n\t* Set the 'dscription' element of feed item\n\t* \n\t* @access   public\n\t* @param    string  The content of 'description' element\n\t* @return   void\n\t*/\n\tpublic function setDescription($description) \n\t{\n\t\t$tag = ($this->version == ATOM)? 'summary' : 'description'; \n\t\t$this->setElement($tag, $description);\n\t}\n\t\n\t/**\n\t* @desc     Set the 'title' element of feed item\n\t* @access   public\n\t* @param    string  The content of 'title' element\n\t* @return   void\n\t*/\n\tpublic function setTitle($title) \n\t{\n\t\t$this->setElement('title', $title);  \t\n\t}\n\t\n\t/**\n\t* Set the 'date' element of feed item\n\t* \n\t* @access   public\n\t* @param    string  The content of 'date' element\n\t* @return   void\n\t*/\n\tpublic function setDate($date) \n\t{\n\t\tif(! is_numeric($date))\n\t\t{\n\t\t\t$date = strtotime($date);\n\t\t}\n\t\t\n\t\tif($this->version == ATOM)\n\t\t{\n\t\t\t$tag    = 'updated';\n\t\t\t$value  = date(DATE_ATOM, $date);\n\t\t}        \n\t\telseif($this->version == RSS2) \n\t\t{\n\t\t\t$tag    = 'pubDate';\n\t\t\t$value  = date(DATE_RSS, $date);\n\t\t}\n\t\telse                                \n\t\t{\n\t\t\t$tag    = 'dc:date';\n\t\t\t$value  = date(\"Y-m-d\", $date);\n\t\t}\n\t\t\n\t\t$this->setElement($tag, $value);    \n\t}\n\t\n\t/**\n\t* Set the 'link' element of feed item\n\t* \n\t* @access   public\n\t* @param    string  The content of 'link' element\n\t* @return   void\n\t*/\n\tpublic function setLink($link) \n\t{\n\t\tif($this->version == RSS2 || $this->version == RSS1)\n\t\t{\n\t\t\t$this->setElement('link', $link);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->setElement('link','',array('href'=>$link));\n\t\t\t$this->setElement('id', FeedWriter::uuid($link,'urn:uuid:'));\n\t\t} \n\t\t\n\t}\n\t\n\t/**\n\t* Set the 'encloser' element of feed item\n\t* For RSS 2.0 only\n\t* \n\t* @access   public\n\t* @param    string  The url attribute of encloser tag\n\t* @param    string  The length attribute of encloser tag\n\t* @param    string  The type attribute of encloser tag\n\t* @return   void\n\t*/\n\tpublic function setEncloser($url, $length, $type)\n\t{\n\t\t$attributes = array('url'=>$url, 'length'=>$length, 'type'=>$type);\n\t\t$this->setElement('enclosure','',$attributes);\n\t}\n\t\n } // end of class FeedItem\n?>\n"
  },
  {
    "path": "libraries/feedwriter/FeedWriter.php",
    "content": "<?php\ndefine('RSS2', 1, true);\ndefine('JSON', 2, true);\ndefine('JSONP', 3, true);\n\n /**\n * Univarsel Feed Writer class\n *\n * Genarate RSS2 or JSON (original: RSS 1.0, RSS2.0 and ATOM Feed)\n *\n * Modified for FiveFilters.org's Full-Text RSS project\n * to allow for inclusion of hubs, JSON output. \n * Stripped RSS1 and ATOM support.\n *                             \n * @package     UnivarselFeedWriter\n * @author      Anis uddin Ahmad <anisniit@gmail.com>\n * @link        http://www.ajaxray.com/projects/rss\n */\n class FeedWriter\n {\n\t private $self          = null;     // self URL - http://feed2.w3.org/docs/warning/MissingAtomSelfLink.html\n\t private $hubs          = array();  // PubSubHubbub hubs\n\t private $channels      = array();  // Collection of channel elements\n\t private $items         = array();  // Collection of items as object of FeedItem class.\n\t private $data          = array();  // Store some other version wise data\n\t private $CDATAEncoding = array();  // The tag names which have to encoded as CDATA\n\t private $xsl\t\t\t= null;\t\t// stylesheet to render RSS (used by Chrome)\n\t private $json\t\t\t= null;\t\t// JSON object\n\t \n\t private $version   = null; \n\t\n\t/**\n\t* Constructor\n\t* \n\t* @param    constant    the version constant (RSS2 or JSON).       \n\t*/ \n\tfunction __construct($version = RSS2)\n\t{\t\n\t\t$this->version = $version;\n\t\t\t\n\t\t// Setting default value for assential channel elements\n\t\t$this->channels['title']        = $version . ' Feed';\n\t\t$this->channels['link']         = 'http://www.ajaxray.com/blog';\n\t\t\t\t\n\t\t//Tag names to encode in CDATA\n\t\t$this->CDATAEncoding = array('description', 'content:encoded', 'content', 'subtitle', 'summary');\n\t}\n\t\n\tpublic function setFormat($format) {\n\t\t$this->version = $format;\n\t}\n\n\t// Start # public functions ---------------------------------------------\n\t\n\t/**\n\t* Set a channel element\n\t* @access   public\n\t* @param    srting  name of the channel tag\n\t* @param    string  content of the channel tag\n\t* @return   void\n\t*/\n\tpublic function setChannelElement($elementName, $content)\n\t{\n\t\t$this->channels[$elementName] = $content ;\n\t}\n\t\n\t/**\n\t* Set multiple channel elements from an array. Array elements \n\t* should be 'channelName' => 'channelContent' format.\n\t* \n\t* @access   public\n\t* @param    array   array of channels\n\t* @return   void\n\t*/\n\tpublic function setChannelElementsFromArray($elementArray)\n\t{\n\t\tif(! is_array($elementArray)) return;\n\t\tforeach ($elementArray as $elementName => $content) \n\t\t{\n\t\t\t$this->setChannelElement($elementName, $content);\n\t\t}\n\t}\n\t\n\t/**\n\t* Genarate the actual RSS/JSON file\n\t* \n\t* @access   public\n\t* @return   void\n\t*/ \n\tpublic function genarateFeed()\n\t{\n\t\tif ($this->version == RSS2) {\n\t\t\theader('Content-type: text/xml; charset=UTF-8');\n\t\t\t// this line prevents Chrome 20 from prompting download\n\t\t\t// used by Google: https://news.google.com/news/feeds?ned=us&topic=b&output=rss\n\t\t\theader('X-content-type-options: nosniff');\n\t\t} elseif ($this->version == JSON) {\n\t\t\theader('Content-type: application/json; charset=UTF-8');\n\t\t\t$this->json = new stdClass();\n\t\t} elseif ($this->version == JSONP) {\n\t\t\theader('Content-type: application/javascript; charset=UTF-8');\n\t\t\t$this->json = new stdClass();\n\t\t}\n\t\t$this->printHead();\n\t\t$this->printChannels();\n\t\t$this->printItems();\n\t\t$this->printTale();\n\t\tif ($this->version == JSON || $this->version == JSONP) {\n\t\t\techo json_encode($this->json);\n\t\t}\n\t}\n\t\n\tpublic function &getItems()\n\t{\n\t\treturn $this->items;\n\t}\n\t\n\t/**\n\t* Create a new FeedItem.\n\t* \n\t* @access   public\n\t* @return   object  instance of FeedItem class\n\t*/\n\tpublic function createNewItem()\n\t{\n\t\t$Item = new FeedItem($this->version);\n\t\treturn $Item;\n\t}\n\t\n\t/**\n\t* Add a FeedItem to the main class\n\t* \n\t* @access   public\n\t* @param    object  instance of FeedItem class\n\t* @return   void\n\t*/\n\tpublic function addItem($feedItem)\n\t{\n\t\t$this->items[] = $feedItem;    \n\t}\n\t\n\t// Wrapper functions -------------------------------------------------------------------\n\t\n\t/**\n\t* Set the 'title' channel element\n\t* \n\t* @access   public\n\t* @param    srting  value of 'title' channel tag\n\t* @return   void\n\t*/\n\tpublic function setTitle($title)\n\t{\n\t\t$this->setChannelElement('title', $title);\n\t}\n\t\n\t/**\n\t* Add a hub to the channel element\n\t* \n\t* @access   public\n\t* @param    string URL\n\t* @return   void\n\t*/\n\tpublic function addHub($hub)\n\t{\n\t\t$this->hubs[] = $hub;    \n\t}\n\t\n\t/**\n\t* Set XSL URL\n\t* \n\t* @access   public\n\t* @param    string URL\n\t* @return   void\n\t*/\n\tpublic function setXsl($xsl)\n\t{\n\t\t$this->xsl = $xsl;    \n\t}\t\n\t\n\t/**\n\t* Set self URL\n\t* \n\t* @access   public\n\t* @param    string URL\n\t* @return   void\n\t*/\n\tpublic function setSelf($self)\n\t{\n\t\t$this->self = $self;    \n\t}\t\n\t\n\t/**\n\t* Set the 'description' channel element\n\t* \n\t* @access   public\n\t* @param    srting  value of 'description' channel tag\n\t* @return   void\n\t*/\n\tpublic function setDescription($desciption)\n\t{\n\t\t$tag = ($this->version == ATOM)? 'subtitle' : 'description'; \n\t\t$this->setChannelElement($tag, $desciption);\n\t}\n\t\n\t/**\n\t* Set the 'link' channel element\n\t* \n\t* @access   public\n\t* @param    srting  value of 'link' channel tag\n\t* @return   void\n\t*/\n\tpublic function setLink($link)\n\t{\n\t\t$this->setChannelElement('link', $link);\n\t}\n\t\n\t/**\n\t* Set the 'image' channel element\n\t* \n\t* @access   public\n\t* @param    srting  title of image\n\t* @param    srting  link url of the imahe\n\t* @param    srting  path url of the image\n\t* @return   void\n\t*/\n\tpublic function setImage($title, $link, $url)\n\t{\n\t\t$this->setChannelElement('image', array('title'=>$title, 'link'=>$link, 'url'=>$url));\n\t}\n\t\n\t// End # public functions ----------------------------------------------\n\t\n\t// Start # private functions ----------------------------------------------\n\t\n\t/**\n\t* Prints the xml and rss namespace\n\t* \n\t* @access   private\n\t* @return   void\n\t*/\n\tprivate function printHead()\n\t{\n\t\tif ($this->version == RSS2)\n\t\t{\n\t\t\t$out  = '<?xml version=\"1.0\" encoding=\"utf-8\"?>'.\"\\n\";\n\t\t\tif ($this->xsl) $out .= '<?xml-stylesheet type=\"text/xsl\" href=\"'.htmlspecialchars($this->xsl).'\"?>' . PHP_EOL;\n\t\t\t$out .= '<rss version=\"2.0\" xmlns:content=\"http://purl.org/rss/1.0/modules/content/\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:media=\"http://search.yahoo.com/mrss/\">' . PHP_EOL;\n\t\t\techo $out;\n\t\t}\n\t\telseif ($this->version == JSON || $this->version == JSONP)\n\t\t{\n\t\t\t$this->json->rss = array('@attributes' => array('version' => '2.0'));\n\t\t}\n\t}\n\t\n\t/**\n\t* Closes the open tags at the end of file\n\t* \n\t* @access   private\n\t* @return   void\n\t*/\n\tprivate function printTale()\n\t{\n\t\tif ($this->version == RSS2)\n\t\t{\n\t\t\techo '</channel>',PHP_EOL,'</rss>'; \n\t\t}    \n\t\t// do nothing for JSON\n\t}\n\n\t/**\n\t* Creates a single node as xml format\n\t* \n\t* @access   private\n\t* @param    string  name of the tag\n\t* @param    mixed   tag value as string or array of nested tags in 'tagName' => 'tagValue' format\n\t* @param    array   Attributes(if any) in 'attrName' => 'attrValue' format\n\t* @return   string  formatted xml tag\n\t*/\n\tprivate function makeNode($tagName, $tagContent, $attributes = null)\n\t{        \n\t\tif ($this->version == RSS2)\n\t\t{\n\t\t\t$nodeText = '';\n\t\t\t$attrText = '';\n\t\t\tif (is_array($attributes))\n\t\t\t{\n\t\t\t\tforeach ($attributes as $key => $value) \n\t\t\t\t{\n\t\t\t\t\t$attrText .= \" $key=\\\"$value\\\" \";\n\t\t\t\t}\n\t\t\t}\n\t\t\t$nodeText .= \"<{$tagName}{$attrText}>\";\n\t\t\tif (is_array($tagContent))\n\t\t\t{ \n\t\t\t\tforeach ($tagContent as $key => $value) \n\t\t\t\t{\n\t\t\t\t\t$nodeText .= $this->makeNode($key, $value);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//$nodeText .= (in_array($tagName, $this->CDATAEncoding))? $tagContent : htmlentities($tagContent);\n\t\t\t\t$nodeText .= htmlspecialchars($tagContent);\n\t\t\t}           \n\t\t\t//$nodeText .= (in_array($tagName, $this->CDATAEncoding))? \"]]></$tagName>\" : \"</$tagName>\";\n\t\t\t$nodeText .= \"</$tagName>\";\n\t\t\treturn $nodeText . PHP_EOL;\n\t\t}\n\t\telseif ($this->version == JSON || $this->version == JSONP)\n\t\t{\n\t\t\t$tagName = (string)$tagName;\n\t\t\t$tagName = strtr($tagName, ':', '_');\n\t\t\t$node = null;\n\t\t\tif (!$tagContent && is_array($attributes) && count($attributes))\n\t\t\t{\n\t\t\t\t$node = array('@attributes' => $this->json_keys($attributes));\n\t\t\t} else {\n\t\t\t\tif (is_array($tagContent)) {\n\t\t\t\t\t$node = $this->json_keys($tagContent);\n\t\t\t\t} else {\n\t\t\t\t\t$node = $tagContent;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn $node;\n\t\t}\n\t\treturn ''; // should not get here\n\t}\n\t\n\tprivate function json_keys(array $array) {\n\t\t$new = array();\n\t\tforeach ($array as $key => $val) {\n\t\t\tif (is_string($key)) $key = strtr($key, ':', '_');\n\t\t\tif (is_array($val)) {\n\t\t\t\t$new[$key] = $this->json_keys($val);\n\t\t\t} else {\n\t\t\t\t$new[$key] = $val;\n\t\t\t}\n\t\t}\n\t\treturn $new;\n\t}\n\t\n\t/**\n\t* @desc     Print channels\n\t* @access   private\n\t* @return   void\n\t*/\n\tprivate function printChannels()\n\t{\n\t\t//Start channel tag\n\t\tif ($this->version == RSS2) {\n\t\t\techo '<channel>' . PHP_EOL;    \n\t\t\t// add hubs\n\t\t\tforeach ($this->hubs as $hub) {\n\t\t\t\t//echo $this->makeNode('link', '', array('rel'=>'hub', 'href'=>$hub, 'xmlns'=>'http://www.w3.org/2005/Atom'));\n\t\t\t\techo '<link rel=\"hub\"  href=\"'.htmlspecialchars($hub).'\" xmlns=\"http://www.w3.org/2005/Atom\" />' . PHP_EOL;\n\t\t\t}\n\t\t\t// add self\n\t\t\tif (isset($this->self)) {\n\t\t\t\t//echo $this->makeNode('link', '', array('rel'=>'self', 'href'=>$this->self, 'xmlns'=>'http://www.w3.org/2005/Atom'));\n\t\t\t\techo '<link rel=\"self\" href=\"'.htmlspecialchars($this->self).'\" xmlns=\"http://www.w3.org/2005/Atom\" />' . PHP_EOL;\n\t\t\t}\n\t\t\t//Print Items of channel\n\t\t\tforeach ($this->channels as $key => $value) \n\t\t\t{\n\t\t\t\techo $this->makeNode($key, $value);\n\t\t\t}\n\t\t} elseif ($this->version == JSON || $this->version == JSONP) {\n\t\t\t$this->json->rss['channel'] = (object)$this->json_keys($this->channels);\n\t\t}\n\t}\n\t\n\t/**\n\t* Prints formatted feed items\n\t* \n\t* @access   private\n\t* @return   void\n\t*/\n\tprivate function printItems()\n\t{    \n\t\tforeach ($this->items as $item) {\n\t\t\t$itemElements = $item->getElements();\n\t\t\t\n\t\t\techo $this->startItem();\n\t\t\t\n\t\t\tif ($this->version == JSON || $this->version == JSONP) {\n\t\t\t\t$json_item = array();\n\t\t\t}\n\t\t\t\n\t\t\tforeach ($itemElements as $thisElement) {\n\t\t\t\tforeach ($thisElement as $instance) {\t\t\t\n\t\t\t\t\tif ($this->version == RSS2) {\n\t\t\t\t\t\techo $this->makeNode($instance['name'], $instance['content'], $instance['attributes']);\n\t\t\t\t\t} elseif ($this->version == JSON || $this->version == JSONP) {\n\t\t\t\t\t\t$_json_node = $this->makeNode($instance['name'], $instance['content'], $instance['attributes']);\n\t\t\t\t\t\tif (count($thisElement) > 1) {\n\t\t\t\t\t\t\t$json_item[strtr($instance['name'], ':', '_')][] = $_json_node;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$json_item[strtr($instance['name'], ':', '_')] = $_json_node;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\techo $this->endItem();\n\t\t\tif ($this->version == JSON || $this->version == JSONP) {\n\t\t\t\tif (count($this->items) > 1) {\n\t\t\t\t\t$this->json->rss['channel']->item[] = $json_item;\n\t\t\t\t} else {\n\t\t\t\t\t$this->json->rss['channel']->item = $json_item;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\t/**\n\t* Make the starting tag of channels\n\t* \n\t* @access   private\n\t* @return   void\n\t*/\n\tprivate function startItem()\n\t{\n\t\tif ($this->version == RSS2)\n\t\t{\n\t\t\techo '<item>' . PHP_EOL; \n\t\t}    \n\t\t// nothing for JSON\n\t}\n\t\n\t/**\n\t* Closes feed item tag\n\t* \n\t* @access   private\n\t* @return   void\n\t*/\n\tprivate function endItem()\n\t{\n\t\tif ($this->version == RSS2)\n\t\t{\n\t\t\techo '</item>' . PHP_EOL; \n\t\t}    \n\t\t// nothing for JSON\n\t}\n\t\n\t// End # private functions ----------------------------------------------\n }"
  },
  {
    "path": "libraries/htmLawed/htmLawed2.php",
    "content": "<?php\n\n/*\nhtmLawed 1.2.b2, 9 June 2013\nCopyright Santosh Patnaik\nDual licensed with LGPL v3 and GPL v2+\nBased on PHP Labware internal utility:\nhttp://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/beta\n\nSee htmLawed_README.txt/htm\n*/\nclass htmLawed{\n// begin class\npublic static function hl($t, $C=1, $S=array()){\n$C = is_array($C) ? $C : array();\nif(!empty($C['valid_xhtml'])){\n $C['elements'] = empty($C['elements']) ? '*-acronym-big-center-dir-font-isindex-s-strike-tt' : $C['elements'];\n $C['make_tag_strict'] = isset($C['make_tag_strict']) ? $C['make_tag_strict'] : 2;\n $C['xml:lang'] = isset($C['xml:lang']) ? $C['xml:lang'] : 2;\n}\n// config eles\n$e = array('a'=>1, 'abbr'=>1, 'acronym'=>1, 'address'=>1, 'applet'=>1, 'area'=>1, 'article'=>1, 'aside'=>1, 'audio'=>1, 'b'=>1, 'bdi'=>1, 'bdo'=>1, 'big'=>1, 'blockquote'=>1, 'br'=>1, 'button'=>1, 'canvas'=>1, 'caption'=>1, 'center'=>1, 'cite'=>1, 'code'=>1, 'col'=>1, 'colgroup'=>1, 'command'=>1, 'data'=>1, 'datalist'=>1, 'dd'=>1, 'del'=>1, 'details'=>1, 'dfn'=>1, 'dir'=>1, 'div'=>1, 'dl'=>1, 'dt'=>1, 'em'=>1, 'embed'=>1, 'fieldset'=>1, 'figcaption'=>1, 'figure'=>1, 'font'=>1, 'footer'=>1, 'form'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'header'=>1, 'hgroup'=>1, 'hr'=>1, 'i'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'ins'=>1, 'isindex'=>1, 'kbd'=>1, 'keygen'=>1, 'label'=>1, 'legend'=>1, 'li'=>1, 'link'=>1, 'main'=>1, 'map'=>1, 'mark'=>1, 'menu'=>1, 'meta'=>1, 'meter'=>1, 'nav'=>1, 'noscript'=>1, 'object'=>1, 'ol'=>1, 'optgroup'=>1, 'option'=>1, 'output'=>1, 'p'=>1, 'param'=>1, 'pre'=>1, 'progress'=>1, 'q'=>1, 'rb'=>1, 'rbc'=>1, 'rp'=>1, 'rt'=>1, 'rtc'=>1, 'ruby'=>1, 's'=>1, 'samp'=>1, 'script'=>1, 'section'=>1, 'select'=>1, 'small'=>1, 'source'=>1, 'span'=>1, 'strike'=>1, 'strong'=>1, 'style'=>1, 'sub'=>1, 'summary'=>1, 'sup'=>1, 'table'=>1, 'tbody'=>1, 'td'=>1, 'textarea'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'time'=>1, 'tr'=>1, 'track'=>1, 'tt'=>1, 'u'=>1, 'ul'=>1, 'var'=>1, 'video'=>1, 'wbr'=>1); // 118 incl. deprecated & some Ruby\n\nif(!empty($C['safe'])){\n unset($e['applet'], $e['audio'], $e['canvas'], $e['embed'], $e['iframe'], $e['object'], $e['script'], $e['video']);\n}\n$x = !empty($C['elements']) ? str_replace(array(\"\\n\", \"\\r\", \"\\t\", ' '), '', $C['elements']) : '*';\nif($x == '-*'){$e = array();}\nelseif(strpos($x, '*') === false){$e = array_flip(explode(',', $x));}\nelse{\n if(isset($x[1])){\n  preg_match_all('`(?:^|-|\\+)[^\\-+]+?(?=-|\\+|$)`', $x, $m, PREG_SET_ORDER);\n  for($i=count($m); --$i>=0;){$m[$i] = $m[$i][0];}\n  foreach($m as $v){\n   if($v[0] == '+'){$e[substr($v, 1)] = 1;}\n   if($v[0] == '-' && isset($e[($v = substr($v, 1))]) && !in_array('+'. $v, $m)){unset($e[$v]);}\n  }\n }\n}\n$C['elements'] =& $e;\n// config attrs\n$x = !empty($C['deny_attribute']) ? str_replace(array(\"\\n\", \"\\r\", \"\\t\", ' '), '', $C['deny_attribute']) : '';\n$x = array_flip((isset($x[0]) && $x[0] == '*') ? explode('-', $x) : explode(',', $x. (!empty($C['safe']) ? ',on*' : '')));\nif(isset($x['on*'])){\n unset($x['on*']);\n $x += array('onabort'=>1, 'onblur'=>1, 'oncanplay'=>1, 'oncanplaythrough'=>1, 'onchange'=>1, 'onclick'=>1, 'oncontextmenu'=>1, 'oncuechange'=>1, 'ondblclick'=>1, 'ondrag'=>1, 'ondragend'=>1, 'ondragenter'=>1, 'ondragleave'=>1, 'ondragover'=>1, 'ondragstart'=>1, 'ondrop'=>1, 'ondurationchange'=>1, 'onemptied'=>1, 'onended'=>1, 'onerror'=>1, 'onfocus'=>1, 'oninput'=>1, 'oninvalid'=>1, 'onkeydown'=>1, 'onkeypress'=>1, 'onkeyup'=>1, 'onload'=>1, 'onloadeddata'=>1, 'onloadedmetadata'=>1, 'onloadstart'=>1, 'onmousedown'=>1, 'onmousemove'=>1, 'onmouseout'=>1, 'onmouseover'=>1, 'onmouseup'=>1, 'onmousewheel'=>1, 'onpause'=>1, 'onplay'=>1, 'onplaying'=>1, 'onprogress'=>1, 'onratechange'=>1, 'onreadystatechange'=>1, 'onreset'=>1, 'onscroll'=>1, 'onseeked'=>1, 'onseeking'=>1, 'onselect'=>1, 'onshow'=>1, 'onstalled'=>1, 'onsubmit'=>1, 'onsuspend'=>1, 'ontimeupdate'=>1, 'onvolumechange'=>1, 'onwaiting'=>1);\n}\n$C['deny_attribute'] = $x;\n// config URL\n$x = (isset($C['schemes'][2]) && strpos($C['schemes'], ':')) ? strtolower($C['schemes']) : 'href: aim, feed, file, ftp, gopher, http, https, irc, mailto, news, nntp, sftp, ssh, telnet, git; *:file, http, https';\n$C['schemes'] = array();\nforeach(explode(';', str_replace(array(' ', \"\\t\", \"\\r\", \"\\n\"), '', $x)) as $v){\n $x = $x2 = null; list($x, $x2) = explode(':', $v, 2);\n if($x2){$C['schemes'][$x] = array_flip(explode(',', $x2));}\n}\nif(!isset($C['schemes']['*'])){$C['schemes']['*'] = array('file'=>1, 'http'=>1, 'https'=>1,);}\nif(!empty($C['safe']) && empty($C['schemes']['style'])){$C['schemes']['style'] = array('!'=>1);}\n$C['abs_url'] = isset($C['abs_url']) ? $C['abs_url'] : 0;\nif(!isset($C['base_url']) or !preg_match('`^[a-zA-Z\\d.+\\-]+://[^/]+/(.+?/)?$`', $C['base_url'])){\n $C['base_url'] = $C['abs_url'] = 0;\n}\n// config rest\n$C['and_mark'] = empty($C['and_mark']) ? 0 : 1;\n$C['anti_link_spam'] = (isset($C['anti_link_spam']) && is_array($C['anti_link_spam']) && count($C['anti_link_spam']) == 2 && (empty($C['anti_link_spam'][0]) or htmLawed::hl_regex($C['anti_link_spam'][0])) && (empty($C['anti_link_spam'][1]) or htmLawed::hl_regex($C['anti_link_spam'][1]))) ? $C['anti_link_spam'] : 0;\n$C['anti_mail_spam'] = isset($C['anti_mail_spam']) ? $C['anti_mail_spam'] : 0;\n$C['balance'] = isset($C['balance']) ? (bool)$C['balance'] : 1;\n$C['cdata'] = isset($C['cdata']) ? $C['cdata'] : (empty($C['safe']) ? 3 : 0);\n$C['clean_ms_char'] = empty($C['clean_ms_char']) ? 0 : $C['clean_ms_char'];\n$C['comment'] = isset($C['comment']) ? $C['comment'] : (empty($C['safe']) ? 3 : 0);\n$C['css_expression'] = empty($C['css_expression']) ? 0 : 1;\n$C['direct_list_nest'] = empty($C['direct_list_nest']) ? 0 : 1;\n$C['hexdec_entity'] = isset($C['hexdec_entity']) ? $C['hexdec_entity'] : 1;\n$C['hook'] = (!empty($C['hook']) && function_exists($C['hook'])) ? $C['hook'] : 0;\n$C['hook_tag'] = (!empty($C['hook_tag']) && function_exists($C['hook_tag'])) ? $C['hook_tag'] : 0;\n$C['keep_bad'] = isset($C['keep_bad']) ? $C['keep_bad'] : 6;\n$C['lc_std_val'] = isset($C['lc_std_val']) ? (bool)$C['lc_std_val'] : 1;\n$C['make_tag_strict'] = isset($C['make_tag_strict']) ? $C['make_tag_strict'] : 1;\n$C['named_entity'] = isset($C['named_entity']) ? (bool)$C['named_entity'] : 1;\n$C['no_deprecated_attr'] = isset($C['no_deprecated_attr']) ? $C['no_deprecated_attr'] : 1;\n$C['parent'] = isset($C['parent'][0]) ? strtolower($C['parent']) : 'body';\n$C['show_setting'] = !empty($C['show_setting']) ? $C['show_setting'] : 0;\n$C['style_pass'] = empty($C['style_pass']) ? 0 : 1;\n$C['tidy'] = empty($C['tidy']) ? 0 : $C['tidy'];\n$C['unique_ids'] = isset($C['unique_ids']) && (!preg_match('`\\W`', $C['unique_ids'])) ? $C['unique_ids'] : 1;\n$C['xml:lang'] = isset($C['xml:lang']) ? $C['xml:lang'] : 0;\n\nif(isset($GLOBALS['C'])){$reC = $GLOBALS['C'];}\n$GLOBALS['C'] = $C;\n$S = is_array($S) ? $S : htmLawed::hl_spec($S);\nif(isset($GLOBALS['S'])){$reS = $GLOBALS['S'];}\n$GLOBALS['S'] = $S;\n\n$t = preg_replace('`[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]`', '', $t);\nif($C['clean_ms_char']){\n $x = array(\"\\x7f\"=>'', \"\\x80\"=>'&#8364;', \"\\x81\"=>'', \"\\x83\"=>'&#402;', \"\\x85\"=>'&#8230;', \"\\x86\"=>'&#8224;', \"\\x87\"=>'&#8225;', \"\\x88\"=>'&#710;', \"\\x89\"=>'&#8240;', \"\\x8a\"=>'&#352;', \"\\x8b\"=>'&#8249;', \"\\x8c\"=>'&#338;', \"\\x8d\"=>'', \"\\x8e\"=>'&#381;', \"\\x8f\"=>'', \"\\x90\"=>'', \"\\x95\"=>'&#8226;', \"\\x96\"=>'&#8211;', \"\\x97\"=>'&#8212;', \"\\x98\"=>'&#732;', \"\\x99\"=>'&#8482;', \"\\x9a\"=>'&#353;', \"\\x9b\"=>'&#8250;', \"\\x9c\"=>'&#339;', \"\\x9d\"=>'', \"\\x9e\"=>'&#382;', \"\\x9f\"=>'&#376;');\n $x = $x + ($C['clean_ms_char'] == 1 ? array(\"\\x82\"=>'&#8218;', \"\\x84\"=>'&#8222;', \"\\x91\"=>'&#8216;', \"\\x92\"=>'&#8217;', \"\\x93\"=>'&#8220;', \"\\x94\"=>'&#8221;') : array(\"\\x82\"=>'\\'', \"\\x84\"=>'\"', \"\\x91\"=>'\\'', \"\\x92\"=>'\\'', \"\\x93\"=>'\"', \"\\x94\"=>'\"'));\n $t = strtr($t, $x);\n}\nif($C['cdata'] or $C['comment']){$t = preg_replace_callback('`<!(?:(?:--.*?--)|(?:\\[CDATA\\[.*?\\]\\]))>`sm', 'htmLawed::hl_cmtcd', $t);}\n$t = preg_replace_callback('`&amp;([a-zA-Z][a-zA-Z0-9]{1,30}|#(?:[0-9]{1,8}|[Xx][0-9A-Fa-f]{1,7}));`', 'htmLawed::hl_ent', str_replace('&', '&amp;', $t));\nif($C['unique_ids'] && !isset($GLOBALS['hl_Ids'])){$GLOBALS['hl_Ids'] = array();}\nif($C['hook']){$t = $C['hook']($t, $C, $S);}\nif($C['show_setting'] && preg_match('`^[a-z][a-z0-9_]*$`i', $C['show_setting'])){\n $GLOBALS[$C['show_setting']] = array('config'=>$C, 'spec'=>$S, 'time'=>microtime());\n}\n// main\n$t = preg_replace_callback('`<(?:(?:\\s|$)|(?:[^>]*(?:>|$)))|>`m', 'htmLawed::hl_tag', $t);\n$t = $C['balance'] ? htmLawed::hl_bal($t, $C['keep_bad'], $C['parent']) : $t;\n$t = (($C['cdata'] or $C['comment']) && strpos($t, \"\\x01\") !== false) ? str_replace(array(\"\\x01\", \"\\x02\", \"\\x03\", \"\\x04\", \"\\x05\"), array('', '', '&', '<', '>'), $t) : $t;\n$t = $C['tidy'] ? htmLawed::hl_tidy($t, $C['tidy'], $C['parent']) : $t;\nunset($C, $e);\nif(isset($reC)){$GLOBALS['C'] = $reC;}\nif(isset($reS)){$GLOBALS['S'] = $reS;}\nreturn $t;\n// eof\n}\n\npublic static function hl_attrval($t, $p){\n// check attr val against $S\n$o = 1; $l = strlen($t);\nforeach($p as $k=>$v){\n switch($k){\n  case 'maxlen':if($l > $v){$o = 0;}\n  break; case 'minlen': if($l < $v){$o = 0;}\n  break; case 'maxval': if((float)($t) > $v){$o = 0;}\n  break; case 'minval': if((float)($t) < $v){$o = 0;}\n  break; case 'match': if(!preg_match($v, $t)){$o = 0;}\n  break; case 'nomatch': if(preg_match($v, $t)){$o = 0;}\n  break; case 'oneof':\n   $m = 0;\n   foreach(explode('|', $v) as $n){if($t == $n){$m = 1; break;}}\n   $o = $m;\n  break; case 'noneof':\n   $m = 1;\n   foreach(explode('|', $v) as $n){if($t == $n){$m = 0; break;}}\n   $o = $m;\n  break; default:\n  break;\n }\n if(!$o){break;}\n}\nreturn ($o ? $t : (isset($p['default']) ? $p['default'] : 0));\n// eof\n}\n\npublic static function hl_bal($t, $do=1, $in='div'){\n// balance tags\n// by content\n$cB = array('blockquote'=>1, 'form'=>1, 'map'=>1, 'noscript'=>1); // Block\n$cE = array('area'=>1, 'br'=>1, 'col'=>1, 'command'=>1, 'embed'=>1, 'hr'=>1, 'img'=>1, 'input'=>1, 'isindex'=>1, 'keygen'=>1, 'link'=>1, 'meta'=>1, 'param'=>1, 'source'=>1, 'track'=>1, 'wbr'=>1); // Empty\n$cF = array('a'=>1, 'article'=>1, 'aside'=>1, 'audio'=>1, 'button'=>1, 'canvas'=>1, 'del'=>1, 'details'=>1, 'div'=>1, 'dd'=>1, 'fieldset'=>1, 'figure'=>1, 'footer'=>1, 'header'=>1, 'iframe'=>1, 'ins'=>1, 'li'=>1, 'main'=>1, 'menu'=>1, 'nav'=>1, 'noscript'=>1, 'object'=>1, 'section'=>1, 'style'=>1, 'td'=>1, 'th'=>1, 'video'=>1); // Flow; later context-wise dynamic move of ins & del to $cI\n$cI = array('abbr'=>1, 'acronym'=>1, 'address'=>1, 'b'=>1, 'bdi'=>1, 'bdo'=>1, 'big'=>1, 'caption'=>1, 'cite'=>1, 'code'=>1, 'data'=>1, 'datalist'=>1, 'dfn'=>1, 'dt'=>1, 'em'=>1, 'figcaption'=>1, 'font'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'hgroup'=>1, 'i'=>1, 'kbd'=>1, 'label'=>1, 'legend'=>1, 'mark'=>1, 'meter'=>1, 'output'=>1, 'p'=>1, 'pre'=>1, 'progress'=>1, 'q'=>1, 'rb'=>1, 'rt'=>1, 's'=>1, 'samp'=>1, 'small'=>1, 'span'=>1, 'strike'=>1, 'strong'=>1, 'sub'=>1, 'summary'=>1, 'sup'=>1, 'time'=>1, 'tt'=>1, 'u'=>1, 'var'=>1); // Inline\n$cN = array('a'=>array('a'=>1, 'address'=>1, 'button'=>1, 'details'=>1, 'embed'=>1, 'keygen'=>1, 'label'=>1, 'select'=>1, 'textarea'=>1), 'address'=>array('address'=>1, 'article'=>1, 'aside'=>1, 'header'=>1, 'keygen'=>1, 'footer'=>1, 'nav'=>1, 'section'=>1), 'button'=>array('a'=>1, 'address'=>1, 'button'=>1, 'details'=>1, 'embed'=>1, 'fieldset'=>1, 'form'=>1, 'iframe'=>1, 'input'=>1, 'keygen'=>1, 'label'=>1, 'select'=>1, 'textarea'=>1), 'fieldset'=>array('fieldset'=>1), 'footer'=>array('header'=>1, 'footer'=>1), 'form'=>array('form'=>1), 'header'=>array('header'=>1, 'footer'=>1), 'label'=>array('label'=>1), 'main'=>array('main'=>1), 'meter'=>array('meter'=>1), 'noscript'=>array('script'=>1), 'pre'=>array('big'=>1, 'font'=>1, 'img'=>1, 'object'=>1, 'script'=>1, 'small'=>1, 'sub'=>1, 'sup'=>1), 'progress'=>array('progress'=>1), 'rb'=>array('ruby'=>1), 'rt'=>array('ruby'=>1), 'time'=>array('time'=>1), ); // Illegal\n$cN2 = array_keys($cN);\n$cR = array('blockquote'=>1, 'dir'=>1, 'dl'=>1, 'form'=>1, 'map'=>1, 'menu'=>1, 'noscript'=>1, 'ol'=>1, 'optgroup'=>1, 'rbc'=>1, 'rtc'=>1, 'ruby'=>1, 'select'=>1, 'table'=>1, 'tbody'=>1, 'tfoot'=>1, 'thead'=>1, 'tr'=>1, 'ul'=>1);\n$cS = array('colgroup'=>array('col'=>1), 'datalist'=>array('option'=>1), 'dir'=>array('li'=>1), 'dl'=>array('dd'=>1, 'dt'=>1), 'hgroup'=>array('h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1), 'menu'=>array('li'=>1), 'ol'=>array('li'=>1), 'optgroup'=>array('option'=>1), 'option'=>array('#pcdata'=>1), 'rbc'=>array('rb'=>1), 'rp'=>array('#pcdata'=>1), 'rtc'=>array('rt'=>1), 'ruby'=>array('rb'=>1, 'rbc'=>1, 'rp'=>1, 'rt'=>1, 'rtc'=>1), 'select'=>array('optgroup'=>1, 'option'=>1), 'script'=>array('#pcdata'=>1), 'table'=>array('caption'=>1, 'col'=>1, 'colgroup'=>1, 'tfoot'=>1, 'tbody'=>1, 'tr'=>1, 'thead'=>1), 'tbody'=>array('tr'=>1), 'tfoot'=>array('tr'=>1), 'textarea'=>array('#pcdata'=>1), 'thead'=>array('tr'=>1), 'tr'=>array('td'=>1, 'th'=>1), 'ul'=>array('li'=>1)); // Specific - immediate parent-child\nif($GLOBALS['C']['direct_list_nest']){$cS['ol'] = $cS['ul'] = $cS['menu'] += array('menu'=>1, 'ol'=>1, 'ul'=>1);}\n$cO = array('address'=>array('p'=>1), 'applet'=>array('param'=>1), 'audio'=>array('source'=>1, 'track'=>1), 'blockquote'=>array('script'=>1), 'details'=>array('summary'=>1), 'fieldset'=>array('legend'=>1, '#pcdata'=>1),  'figure'=>array('figcaption'=>1),'form'=>array('script'=>1), 'map'=>array('area'=>1), 'object'=>array('param'=>1, 'embed'=>1), 'video'=>array('source'=>1, 'track'=>1)); // Other\n$cT = array('colgroup'=>1, 'dd'=>1, 'dt'=>1, 'li'=>1, 'option'=>1, 'p'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1); // Omitable closing\n// block/inline type; ins & del both type; #pcdata: text\n$eB = array('a'=>1, 'address'=>1, 'article'=>1, 'aside'=>1, 'blockquote'=>1, 'center'=>1, 'del'=>1, 'details'=>1, 'dir'=>1, 'dl'=>1, 'div'=>1, 'fieldset'=>1, 'figure'=>1, 'footer'=>1, 'form'=>1, 'ins'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'header'=>1, 'hr'=>1, 'isindex'=>1, 'main'=>1, 'menu'=>1, 'nav'=>1, 'noscript'=>1, 'ol'=>1, 'p'=>1, 'pre'=>1, 'section'=>1, 'style'=>1, 'table'=>1, 'ul'=>1);\n$eI = array('#pcdata'=>1, 'abbr'=>1, 'acronym'=>1, 'applet'=>1, 'audio'=>1, 'b'=>1, 'bdi'=>1, 'bdo'=>1, 'big'=>1, 'br'=>1, 'button'=>1, 'canvas'=>1, 'cite'=>1, 'code'=>1, 'command'=>1, 'data'=>1, 'datalist'=>1, 'del'=>1, 'dfn'=>1, 'em'=>1, 'embed'=>1, 'figcaption'=>1, 'font'=>1, 'i'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'ins'=>1, 'kbd'=>1, 'label'=>1, 'link'=>1, 'map'=>1, 'mark'=>1, 'meta'=>1, 'meter'=>1, 'object'=>1, 'output'=>1, 'progress'=>1, 'q'=>1, 'ruby'=>1, 's'=>1, 'samp'=>1, 'select'=>1, 'script'=>1, 'small'=>1, 'span'=>1, 'strike'=>1, 'strong'=>1, 'sub'=>1, 'summary'=>1, 'sup'=>1, 'textarea'=>1, 'time'=>1, 'tt'=>1, 'u'=>1, 'var'=>1, 'video'=>1, 'wbr'=>1);\n$eN = array('a'=>1, 'address'=>1, 'article'=>1, 'aside'=>1, 'big'=>1, 'button'=>1, 'details'=>1, 'embed'=>1, 'fieldset'=>1, 'font'=>1, 'footer'=>1, 'form'=>1, 'header'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'keygen'=>1, 'label'=>1, 'meter'=>1, 'nav'=>1, 'object'=>1, 'progress'=>1, 'ruby'=>1, 'script'=>1, 'select'=>1, 'small'=>1, 'sub'=>1, 'sup'=>1, 'textarea'=>1, 'time'=>1); // Exclude from specific ele; $cN values\n$eO = array('area'=>1, 'caption'=>1, 'col'=>1, 'colgroup'=>1, 'command'=>1, 'dd'=>1, 'dt'=>1, 'hgroup'=>1, 'keygen'=>1, 'legend'=>1, 'li'=>1, 'optgroup'=>1, 'option'=>1, 'param'=>1, 'rb'=>1, 'rbc'=>1, 'rp'=>1, 'rt'=>1, 'rtc'=>1, 'script'=>1, 'source'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'thead'=>1, 'th'=>1, 'tr'=>1, 'track'=>1); // Missing in $eB & $eI\n$eF = $eB + $eI;\n\n// $in sets allowed child\n$in = ((isset($eF[$in]) && $in != '#pcdata') or isset($eO[$in])) ? $in : 'div';\nif(isset($cE[$in])){\n return (!$do ? '' : str_replace(array('<', '>'), array('&lt;', '&gt;'), $t));\n}\nif(isset($cS[$in])){$inOk = $cS[$in];}\nelseif(isset($cI[$in])){$inOk = $eI; $cI['del'] = 1; $cI['ins'] = 1;}\nelseif(isset($cF[$in])){$inOk = $eF; unset($cI['del'], $cI['ins']);}\nelseif(isset($cB[$in])){$inOk = $eB; unset($cI['del'], $cI['ins']);}\nif(isset($cO[$in])){$inOk = $inOk + $cO[$in];}\nif(isset($cN[$in])){$inOk = array_diff_assoc($inOk, $cN[$in]);}\n\n$t = explode('<', $t);\n$ok = $q = array(); // $q seq list of open non-empty ele\nob_start();\n\nfor($i=-1, $ci=count($t); ++$i<$ci;){\n // allowed $ok in parent $p\n if($ql = count($q)){\n  $p = array_pop($q);\n  $q[] = $p;\n  if(isset($cS[$p])){$ok = $cS[$p];}\n  elseif(isset($cI[$p])){$ok = $eI; $cI['del'] = 1; $cI['ins'] = 1;}\n  elseif(isset($cF[$p])){$ok = $eF; unset($cI['del'], $cI['ins']);}\n  elseif(isset($cB[$p])){$ok = $eB; unset($cI['del'], $cI['ins']);}\n  if(isset($cO[$p])){$ok = $ok + $cO[$p];}\n  if(isset($cN[$p])){$ok = array_diff_assoc($ok, $cN[$p]);}\n }else{$ok = $inOk; unset($cI['del'], $cI['ins']);}\n // bad tags, & ele content\n if(isset($e) && ($do == 1 or (isset($ok['#pcdata']) && ($do == 3 or $do == 5)))){\n  echo '&lt;', $s, $e, $a, '&gt;';\n }\n if(isset($x[0])){\n  if(strlen(trim($x)) && (($ql && isset($cB[$p])) or (isset($cB[$in]) && !$ql))){\n   echo '<div>', $x, '</div>';\n  }\n  elseif($do < 3 or isset($ok['#pcdata'])){echo $x;}\n  elseif(strpos($x, \"\\x02\\x04\")){\n   foreach(preg_split('`(\\x01\\x02[^\\x01\\x02]+\\x02\\x01)`', $x, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY) as $v){\n    echo (substr($v, 0, 2) == \"\\x01\\x02\" ? $v : ($do > 4 ? preg_replace('`\\S`', '', $v) : ''));\n   }\n  }elseif($do > 4){echo preg_replace('`\\S`', '', $x);}\n }\n // get markup\n if(!preg_match('`^(/?)([a-zA-Z1-6]+)([^>]*)>(.*)`sm', $t[$i], $r)){$x = $t[$i]; continue;}\n $s = null; $e = null; $a = null; $x = null; list($all, $s, $e, $a, $x) = $r;\n // close tag\n if($s){\n  if(isset($cE[$e]) or !in_array($e, $q)){continue;} // Empty/unopen\n  if($p == $e){array_pop($q); echo '</', $e, '>'; unset($e); continue;} // Last open\n  $add = ''; // Nesting - close open tags that need to be\n  for($j=-1, $cj=count($q); ++$j<$cj;){  \n   if(($d = array_pop($q)) == $e){break;}\n   else{$add .= \"</{$d}>\";}\n  }\n  echo $add, '</', $e, '>'; unset($e); continue;\n }\n // open tag\n // $cB ele needs $eB ele as child\n if(isset($cB[$e]) && strlen(trim($x))){\n  $t[$i] = \"{$e}{$a}>\";\n  array_splice($t, $i+1, 0, 'div>'. $x); unset($e, $x); ++$ci; --$i; continue;\n }\n if((($ql && isset($cB[$p])) or (isset($cB[$in]) && !$ql)) && !isset($eB[$e]) && !isset($ok[$e])){\n  array_splice($t, $i, 0, 'div>'); unset($e, $x); ++$ci; --$i; continue;\n }\n // if no open ele, $in = parent; mostly immediate parent-child relation should hold\n if(!$ql or !isset($eN[$e]) or !array_intersect($q, $cN2)){\n  if(!isset($ok[$e])){\n   if($ql && isset($cT[$p])){echo '</', array_pop($q), '>'; unset($e, $x); --$i;}\n   continue;\n  }\n  if(!isset($cE[$e])){$q[] = $e;}\n  echo '<', $e, $a, '>'; unset($e); continue;\n }\n // specific parent-child\n if(isset($cS[$p][$e])){\n  if(!isset($cE[$e])){$q[] = $e;}\n  echo '<', $e, $a, '>'; unset($e); continue;\n }\n // nesting\n $add = '';\n $q2 = array();\n for($k=-1, $kc=count($q); ++$k<$kc;){\n  $d = $q[$k];\n  $ok2 = array();\n  if(isset($cS[$d])){$q2[] = $d; continue;}\n  $ok2 = isset($cI[$d]) ? $eI : $eF;\n  if(isset($cO[$d])){$ok2 = $ok2 + $cO[$d];}\n  if(isset($cN[$d])){$ok2 = array_diff_assoc($ok2, $cN[$d]);}\n  if(!isset($ok2[$e])){\n   if(!$k && !isset($inOk[$e])){continue 2;}\n   $add = \"</{$d}>\";\n   for(;++$k<$kc;){$add = \"</{$q[$k]}>{$add}\";}\n   break;\n  }\n  else{$q2[] = $d;}\n }\n $q = $q2;\n if(!isset($cE[$e])){$q[] = $e;}\n echo $add, '<', $e, $a, '>'; unset($e); continue;\n}\n\n// end\nif($ql = count($q)){\n $p = array_pop($q);\n $q[] = $p;\n if(isset($cS[$p])){$ok = $cS[$p];}\n elseif(isset($cI[$p])){$ok = $eI; $cI['del'] = 1; $cI['ins'] = 1;}\n elseif(isset($cF[$p])){$ok = $eF; unset($cI['del'], $cI['ins']);}\n elseif(isset($cB[$p])){$ok = $eB; unset($cI['del'], $cI['ins']);}\n if(isset($cO[$p])){$ok = $ok + $cO[$p];}\n if(isset($cN[$p])){$ok = array_diff_assoc($ok, $cN[$p]);}\n}else{$ok = $inOk; unset($cI['del'], $cI['ins']);}\nif(isset($e) && ($do == 1 or (isset($ok['#pcdata']) && ($do == 3 or $do == 5)))){\n echo '&lt;', $s, $e, $a, '&gt;';\n}\nif(isset($x[0])){\n if(strlen(trim($x)) && (($ql && isset($cB[$p])) or (isset($cB[$in]) && !$ql))){\n  echo '<div>', $x, '</div>';\n }\n elseif($do < 3 or isset($ok['#pcdata'])){echo $x;}\n elseif(strpos($x, \"\\x02\\x04\")){\n  foreach(preg_split('`(\\x01\\x02[^\\x01\\x02]+\\x02\\x01)`', $x, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY) as $v){\n   echo (substr($v, 0, 2) == \"\\x01\\x02\" ? $v : ($do > 4 ? preg_replace('`\\S`', '', $v) : ''));\n  }\n }elseif($do > 4){echo preg_replace('`\\S`', '', $x);}\n}\nwhile(!empty($q) && ($e = array_pop($q))){echo '</', $e, '>';}\n$o = ob_get_contents();\nob_end_clean();\nreturn $o;\n// eof\n}\n\npublic static function hl_cmtcd($t){\n// comment/CDATA sec handler\n$t = $t[0];\nglobal $C;\nif(!($v = $C[$n = $t[3] == '-' ? 'comment' : 'cdata'])){return $t;}\nif($v == 1){return '';}\nif($n == 'comment'){\n if(substr(($t = preg_replace('`--+`', '-', substr($t, 4, -3))), -1) != ' '){$t .= ' ';}\n}\nelse{$t = substr($t, 1, -1);}\n$t = $v == 2 ? str_replace(array('&', '<', '>'), array('&amp;', '&lt;', '&gt;'), $t) : $t;\nreturn str_replace(array('&', '<', '>'), array(\"\\x03\", \"\\x04\", \"\\x05\"), ($n == 'comment' ? \"\\x01\\x02\\x04!--$t--\\x05\\x02\\x01\" : \"\\x01\\x01\\x04$t\\x05\\x01\\x01\"));\n// eof\n}\n\npublic static function hl_ent($t){\n// entitity handler\nglobal $C;\n$t = $t[1];\nstatic $U = array('quot'=>1,'amp'=>1,'lt'=>1,'gt'=>1);\nstatic $N = array('fnof'=>'402', 'Alpha'=>'913', 'Beta'=>'914', 'Gamma'=>'915', 'Delta'=>'916', 'Epsilon'=>'917', 'Zeta'=>'918', 'Eta'=>'919', 'Theta'=>'920', 'Iota'=>'921', 'Kappa'=>'922', 'Lambda'=>'923', 'Mu'=>'924', 'Nu'=>'925', 'Xi'=>'926', 'Omicron'=>'927', 'Pi'=>'928', 'Rho'=>'929', 'Sigma'=>'931', 'Tau'=>'932', 'Upsilon'=>'933', 'Phi'=>'934', 'Chi'=>'935', 'Psi'=>'936', 'Omega'=>'937', 'alpha'=>'945', 'beta'=>'946', 'gamma'=>'947', 'delta'=>'948', 'epsilon'=>'949', 'zeta'=>'950', 'eta'=>'951', 'theta'=>'952', 'iota'=>'953', 'kappa'=>'954', 'lambda'=>'955', 'mu'=>'956', 'nu'=>'957', 'xi'=>'958', 'omicron'=>'959', 'pi'=>'960', 'rho'=>'961', 'sigmaf'=>'962', 'sigma'=>'963', 'tau'=>'964', 'upsilon'=>'965', 'phi'=>'966', 'chi'=>'967', 'psi'=>'968', 'omega'=>'969', 'thetasym'=>'977', 'upsih'=>'978', 'piv'=>'982', 'bull'=>'8226', 'hellip'=>'8230', 'prime'=>'8242', 'Prime'=>'8243', 'oline'=>'8254', 'frasl'=>'8260', 'weierp'=>'8472', 'image'=>'8465', 'real'=>'8476', 'trade'=>'8482', 'alefsym'=>'8501', 'larr'=>'8592', 'uarr'=>'8593', 'rarr'=>'8594', 'darr'=>'8595', 'harr'=>'8596', 'crarr'=>'8629', 'lArr'=>'8656', 'uArr'=>'8657', 'rArr'=>'8658', 'dArr'=>'8659', 'hArr'=>'8660', 'forall'=>'8704', 'part'=>'8706', 'exist'=>'8707', 'empty'=>'8709', 'nabla'=>'8711', 'isin'=>'8712', 'notin'=>'8713', 'ni'=>'8715', 'prod'=>'8719', 'sum'=>'8721', 'minus'=>'8722', 'lowast'=>'8727', 'radic'=>'8730', 'prop'=>'8733', 'infin'=>'8734', 'ang'=>'8736', 'and'=>'8743', 'or'=>'8744', 'cap'=>'8745', 'cup'=>'8746', 'int'=>'8747', 'there4'=>'8756', 'sim'=>'8764', 'cong'=>'8773', 'asymp'=>'8776', 'ne'=>'8800', 'equiv'=>'8801', 'le'=>'8804', 'ge'=>'8805', 'sub'=>'8834', 'sup'=>'8835', 'nsub'=>'8836', 'sube'=>'8838', 'supe'=>'8839', 'oplus'=>'8853', 'otimes'=>'8855', 'perp'=>'8869', 'sdot'=>'8901', 'lceil'=>'8968', 'rceil'=>'8969', 'lfloor'=>'8970', 'rfloor'=>'8971', 'lang'=>'9001', 'rang'=>'9002', 'loz'=>'9674', 'spades'=>'9824', 'clubs'=>'9827', 'hearts'=>'9829', 'diams'=>'9830', 'apos'=>'39',  'OElig'=>'338', 'oelig'=>'339', 'Scaron'=>'352', 'scaron'=>'353', 'Yuml'=>'376', 'circ'=>'710', 'tilde'=>'732', 'ensp'=>'8194', 'emsp'=>'8195', 'thinsp'=>'8201', 'zwnj'=>'8204', 'zwj'=>'8205', 'lrm'=>'8206', 'rlm'=>'8207', 'ndash'=>'8211', 'mdash'=>'8212', 'lsquo'=>'8216', 'rsquo'=>'8217', 'sbquo'=>'8218', 'ldquo'=>'8220', 'rdquo'=>'8221', 'bdquo'=>'8222', 'dagger'=>'8224', 'Dagger'=>'8225', 'permil'=>'8240', 'lsaquo'=>'8249', 'rsaquo'=>'8250', 'euro'=>'8364', 'nbsp'=>'160', 'iexcl'=>'161', 'cent'=>'162', 'pound'=>'163', 'curren'=>'164', 'yen'=>'165', 'brvbar'=>'166', 'sect'=>'167', 'uml'=>'168', 'copy'=>'169', 'ordf'=>'170', 'laquo'=>'171', 'not'=>'172', 'shy'=>'173', 'reg'=>'174', 'macr'=>'175', 'deg'=>'176', 'plusmn'=>'177', 'sup2'=>'178', 'sup3'=>'179', 'acute'=>'180', 'micro'=>'181', 'para'=>'182', 'middot'=>'183', 'cedil'=>'184', 'sup1'=>'185', 'ordm'=>'186', 'raquo'=>'187', 'frac14'=>'188', 'frac12'=>'189', 'frac34'=>'190', 'iquest'=>'191', 'Agrave'=>'192', 'Aacute'=>'193', 'Acirc'=>'194', 'Atilde'=>'195', 'Auml'=>'196', 'Aring'=>'197', 'AElig'=>'198', 'Ccedil'=>'199', 'Egrave'=>'200', 'Eacute'=>'201', 'Ecirc'=>'202', 'Euml'=>'203', 'Igrave'=>'204', 'Iacute'=>'205', 'Icirc'=>'206', 'Iuml'=>'207', 'ETH'=>'208', 'Ntilde'=>'209', 'Ograve'=>'210', 'Oacute'=>'211', 'Ocirc'=>'212', 'Otilde'=>'213', 'Ouml'=>'214', 'times'=>'215', 'Oslash'=>'216', 'Ugrave'=>'217', 'Uacute'=>'218', 'Ucirc'=>'219', 'Uuml'=>'220', 'Yacute'=>'221', 'THORN'=>'222', 'szlig'=>'223', 'agrave'=>'224', 'aacute'=>'225', 'acirc'=>'226', 'atilde'=>'227', 'auml'=>'228', 'aring'=>'229', 'aelig'=>'230', 'ccedil'=>'231', 'egrave'=>'232', 'eacute'=>'233', 'ecirc'=>'234', 'euml'=>'235', 'igrave'=>'236', 'iacute'=>'237', 'icirc'=>'238', 'iuml'=>'239', 'eth'=>'240', 'ntilde'=>'241', 'ograve'=>'242', 'oacute'=>'243', 'ocirc'=>'244', 'otilde'=>'245', 'ouml'=>'246', 'divide'=>'247', 'oslash'=>'248', 'ugrave'=>'249', 'uacute'=>'250', 'ucirc'=>'251', 'uuml'=>'252', 'yacute'=>'253', 'thorn'=>'254', 'yuml'=>'255');\nif($t[0] != '#'){\n return ($C['and_mark'] ? \"\\x06\" : '&'). (isset($U[$t]) ? $t : (isset($N[$t]) ? (!$C['named_entity'] ? '#'. ($C['hexdec_entity'] > 1 ? 'x'. dechex($N[$t]) : $N[$t]) : $t) : 'amp;'. $t)). ';';\n}\nif(($n = ctype_digit($t = substr($t, 1)) ? intval($t) : hexdec(substr($t, 1))) < 9 or ($n > 13 && $n < 32) or $n == 11 or $n == 12 or ($n > 126 && $n < 160 && $n != 133) or ($n > 55295 && ($n < 57344 or ($n > 64975 && $n < 64992) or $n == 65534 or $n == 65535 or $n > 1114111))){\n return ($C['and_mark'] ? \"\\x06\" : '&'). \"amp;#{$t};\";\n}\nreturn ($C['and_mark'] ? \"\\x06\" : '&'). '#'. (((ctype_digit($t) && $C['hexdec_entity'] < 2) or !$C['hexdec_entity']) ? $n : 'x'. dechex($n)). ';';\n// eof\n}\n\npublic static function hl_prot($p, $c=null){\n// check URL scheme\nglobal $C;\n$b = $a = '';\nif($c == null){$c = 'style'; $b = $p[1]; $a = $p[3]; $p = trim($p[2]);}\n$c = isset($C['schemes'][$c]) ? $C['schemes'][$c] : $C['schemes']['*'];\nstatic $d = 'denied:';\nif(isset($c['!']) && substr($p, 0, 7) != $d){$p = \"$d$p\";}\nif(isset($c['*']) or !strcspn($p, '#?;') or (substr($p, 0, 7) == $d)){return \"{$b}{$p}{$a}\";} // All ok, frag, query, param\nif(preg_match('`^([a-z\\d\\-+.&#; ]+?)(:|&#(58|x3a);|%3a|\\\\\\\\0{0,4}3a).`i', $p, $m) && !isset($c[strtolower($m[1])])){ // Denied prot\n return \"{$b}{$d}{$p}{$a}\";\n}\nif($C['abs_url']){\n if($C['abs_url'] == -1 && strpos($p, $C['base_url']) === 0){ // Make url rel\n  $p = substr($p, strlen($C['base_url']));\n }elseif(empty($m[1])){ // Make URL abs\n  if(substr($p, 0, 2) == '//'){$p = substr($C['base_url'], 0, strpos($C['base_url'], ':')+1). $p;}\n  elseif($p[0] == '/'){$p = preg_replace('`(^.+?://[^/]+)(.*)`', '$1', $C['base_url']). $p;}\n  elseif(strcspn($p, './')){$p = $C['base_url']. $p;}\n  else{\n   preg_match('`^([a-zA-Z\\d\\-+.]+://[^/]+)(.*)`', $C['base_url'], $m);\n   $p = preg_replace('`(?<=/)\\./`', '', $m[2]. $p);\n   while(preg_match('`(?<=/)([^/]{3,}|[^/.]+?|\\.[^/.]|[^/.]\\.)/\\.\\./`', $p)){\n    $p = preg_replace('`(?<=/)([^/]{3,}|[^/.]+?|\\.[^/.]|[^/.]\\.)/\\.\\./`', '', $p);\n   }\n   $p = $m[1]. $p;\n  }\n }\n}\nreturn \"{$b}{$p}{$a}\";\n// eof\n}\n\npublic static function hl_regex($p){\n// ?regex\nif(empty($p)){return 0;}\nif($t = ini_get('track_errors')){$o = isset($php_errormsg) ? $php_errormsg : null;}\nelse{ini_set('track_errors', 1);}\nunset($php_errormsg);\nif(($d = ini_get('display_errors'))){ini_set('display_errors', 0);}\npreg_match($p, '');\nif($d){ini_set('display_errors', 1);}\n$r = isset($php_errormsg) ? 0 : 1;\nif($t){$php_errormsg = isset($o) ? $o : null;}\nelse{ini_set('track_errors', 0);}\nreturn $r;\n// eof\n}\n\npublic static function hl_spec($t){\n// final $spec\n$s = array();\n$t = str_replace(array(\"\\t\", \"\\r\", \"\\n\", ' '), '', preg_replace('/\"(?>(`.|[^\"])*)\"/sme', 'substr(str_replace(array(\";\", \"|\", \"~\", \" \", \",\", \"/\", \"(\", \")\", \\'`\"\\'), array(\"\\x01\", \"\\x02\", \"\\x03\", \"\\x04\", \"\\x05\", \"\\x06\", \"\\x07\", \"\\x08\", \"\\\"\"), \"$0\"), 1, -1)', trim($t))); \nfor($i = count(($t = explode(';', $t))); --$i>=0;){\n $w = $t[$i];\n if(empty($w) or ($e = strpos($w, '=')) === false or !strlen(($a =  substr($w, $e+1)))){continue;}\n $y = $n = array();\n foreach(explode(',', $a) as $v){\n  if(!preg_match('`^([a-z:\\-\\*]+)(?:\\((.*?)\\))?`i', $v, $m)){continue;}\n  if(($x = strtolower($m[1])) == '-*'){$n['*'] = 1; continue;}\n  if($x[0] == '-'){$n[substr($x, 1)] = 1; continue;}\n  if(!isset($m[2])){$y[$x] = 1; continue;}\n  foreach(explode('/', $m[2]) as $m){\n   if(empty($m) or ($p = strpos($m, '=')) == 0 or $p < 5){$y[$x] = 1; continue;}\n   $y[$x][strtolower(substr($m, 0, $p))] = str_replace(array(\"\\x01\", \"\\x02\", \"\\x03\", \"\\x04\", \"\\x05\", \"\\x06\", \"\\x07\", \"\\x08\"), array(\";\", \"|\", \"~\", \" \", \",\", \"/\", \"(\", \")\"), substr($m, $p+1));\n  }\n  if(isset($y[$x]['match']) && !htmLawed::hl_regex($y[$x]['match'])){unset($y[$x]['match']);}\n  if(isset($y[$x]['nomatch']) && !htmLawed::hl_regex($y[$x]['nomatch'])){unset($y[$x]['nomatch']);}\n }\n if(!count($y) && !count($n)){continue;}\n foreach(explode(',', substr($w, 0, $e)) as $v){\n  if(!strlen(($v = strtolower($v)))){continue;}\n  if(count($y)){$s[$v] = $y;}\n  if(count($n)){$s[$v]['n'] = $n;}\n }\n}\nreturn $s;\n// eof\n}\n\npublic static function hl_tag($t){\n// tag/attribute handler\nglobal $C;\n$t = $t[0];\n// invalid < >\nif($t == '< '){return '&lt; ';}\nif($t == '>'){return '&gt;';}\nif(!preg_match('`^<(/?)([a-zA-Z][a-zA-Z1-6]*)([^>]*?)\\s?>$`m', $t, $m)){\n return str_replace(array('<', '>'), array('&lt;', '&gt;'), $t);\n}elseif(!isset($C['elements'][($e = strtolower($m[2]))])){\n return (($C['keep_bad']%2) ? str_replace(array('<', '>'), array('&lt;', '&gt;'), $t) : '');\n}\n// attr string\n$a = str_replace(array(\"\\n\", \"\\r\", \"\\t\"), ' ', trim($m[3]));\n// tag transform\nstatic $eD = array('acronym'=>1, 'applet'=>1, 'big'=>1, 'center'=>1, 'dir'=>1, 'font'=>1, 'isindex'=>1, 's'=>1, 'strike'=>1, 'tt'=>1); // Deprecated\nif($C['make_tag_strict'] && isset($eD[$e])){\n $trt = htmLawed::hl_tag2($e, $a, $C['make_tag_strict']);\n if(!$e){return (($C['keep_bad']%2) ? str_replace(array('<', '>'), array('&lt;', '&gt;'), $t) : '');}\n}\n// close tag\nstatic $eE = array('area'=>1, 'br'=>1, 'col'=>1, 'command'=>1, 'embed'=>1, 'hr'=>1, 'img'=>1, 'input'=>1, 'isindex'=>1, 'keygen'=>1, 'link'=>1, 'meta'=>1, 'param'=>1, 'source'=>1, 'track'=>1, 'wbr'=>1); // Empty ele\nif(!empty($m[1])){\n return (!isset($eE[$e]) ? (empty($C['hook_tag']) ? \"</$e>\" : $C['hook_tag']($e)) : (($C['keep_bad'])%2 ? str_replace(array('<', '>'), array('&lt;', '&gt;'), $t) : ''));\n}\n\n// open tag & attr\nstatic $aN = array('abbr'=>array('td'=>1, 'th'=>1), 'accept-charset'=>array('form'=>1), 'accept'=>array('form'=>1, 'input'=>1), 'action'=>array('form'=>1), 'align'=>array('caption'=>1, 'embed'=>1, 'applet'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'object'=>1, 'legend'=>1, 'table'=>1, 'hr'=>1, 'div'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'p'=>1, 'col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'alt'=>array('applet'=>1, 'area'=>1, 'img'=>1, 'input'=>1), 'archive'=>array('applet'=>1, 'object'=>1), 'async'=>array('script'=>1), 'autocomplete'=>array('input'=>1), 'autofocus'=>array('button'=>1, 'input'=>1, 'keygen'=>1, 'select'=>1, 'textarea'=>1), 'autoplay'=>array('audio'=>1, 'video'=>1), 'axis'=>array('td'=>1, 'th'=>1), 'bgcolor'=>array('embed'=>1, 'table'=>1, 'tr'=>1, 'td'=>1, 'th'=>1), 'border'=>array('table'=>1, 'img'=>1, 'object'=>1), 'bordercolor'=>array('table'=>1, 'td'=>1, 'tr'=>1), 'cellpadding'=>array('table'=>1), 'cellspacing'=>array('table'=>1), 'challenge'=>array('keygen'=>1), 'char'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'charoff'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'charset'=>array('a'=>1, 'script'=>1), 'checked'=>array('command'=>1, 'input'=>1), 'cite'=>array('blockquote'=>1, 'q'=>1, 'del'=>1, 'ins'=>1), 'classid'=>array('object'=>1), 'clear'=>array('br'=>1), 'code'=>array('applet'=>1), 'codebase'=>array('object'=>1, 'applet'=>1), 'codetype'=>array('object'=>1), 'color'=>array('font'=>1), 'cols'=>array('textarea'=>1), 'colspan'=>array('td'=>1, 'th'=>1), 'compact'=>array('dir'=>1, 'dl'=>1, 'menu'=>1, 'ol'=>1, 'ul'=>1), 'content'=>array('meta'=>1), 'controls'=>array('audio'=>1, 'video'=>1), 'coords'=>array('area'=>1, 'a'=>1), 'crossorigin'=>array('img'=>1), 'data'=>array('object'=>1), 'datetime'=>array('del'=>1, 'ins'=>1, 'time'=>1), 'declare'=>array('object'=>1), 'default'=>array('track'=>1), 'defer'=>array('script'=>1), 'dirname'=>array('input'=>1, 'textarea'=>1), 'disabled'=>array('button'=>1, 'command'=>1, 'fieldset'=>1, 'input'=>1, 'keygen'=>1, 'optgroup'=>1, 'option'=>1, 'select'=>1, 'textarea'=>1), 'download'=>array('a'=>1), 'enctype'=>array('form'=>1), 'face'=>array('font'=>1), 'flashvars'=>array('embed'=>1), 'for'=>array('label'=>1, 'output'=>1), 'form'=>array('button'=>1, 'fieldset'=>1, 'input'=>1, 'keygen'=>1, 'label'=>1, 'object'=>1, 'output'=>1, 'select'=>1, 'textarea'=>1), 'formaction'=>array('button'=>1, 'input'=>1), 'formenctype'=>array('button'=>1, 'input'=>1), 'formmethod'=>array('button'=>1, 'input'=>1), 'formnovalidate'=>array('button'=>1, 'input'=>1), 'formtarget'=>array('button'=>1, 'input'=>1), 'frame'=>array('table'=>1), 'frameborder'=>array('iframe'=>1), 'headers'=>array('td'=>1, 'th'=>1), 'height'=>array('canvas'=>1, 'embed'=>1, 'iframe'=>1, 'input'=>1, 'td'=>1, 'th'=>1, 'img'=>1, 'object'=>1, 'applet'=>1, 'video'=>1), 'high'=>array('meter'=>1), 'href'=>array('a'=>1, 'area'=>1, 'link'=>1), 'hreflang'=>array('a'=>1, 'area'=>1, 'link'=>1), 'hspace'=>array('applet'=>1, 'embed'=>1, 'img'=>1, 'object'=>1), 'icon'=>array('command'=>1), 'ismap'=>array('img'=>1, 'input'=>1), 'keyparams'=>array('keygen'=>1), 'keytype'=>array('keygen'=>1), 'kind'=>array('track'=>1), 'label'=>array('command'=>1, 'menu'=>1, 'option'=>1, 'optgroup'=>1, 'track'=>1), 'language'=>array('script'=>1), 'list'=>array('input'=>1), 'longdesc'=>array('img'=>1, 'iframe'=>1), 'loop'=>array('audio'=>1, 'video'=>1), 'low'=>array('meter'=>1), 'marginheight'=>array('iframe'=>1), 'marginwidth'=>array('iframe'=>1), 'max'=>array('input'=>1, 'meter'=>1, 'progress'=>1), 'maxlength'=>array('input'=>1, 'textarea'=>1), 'media'=>array('a'=>1, 'area'=>1, 'link'=>1, 'source'=>1, 'style'=>1), 'mediagroup'=>array('audio'=>1, 'video'=>1), 'method'=>array('form'=>1), 'min'=>array('input'=>1, 'meter'=>1), 'model'=>array('embed'=>1), 'multiple'=>array('input'=>1, 'select'=>1), 'muted'=>array('audio'=>1, 'video'=>1), 'name'=>array('button'=>1, 'embed'=>1, 'fieldset'=>1, 'keygen'=>1, 'output'=>1, 'textarea'=>1, 'applet'=>1, 'select'=>1, 'form'=>1, 'iframe'=>1, 'img'=>1, 'a'=>1, 'input'=>1, 'object'=>1, 'map'=>1, 'param'=>1), 'nohref'=>array('area'=>1), 'noshade'=>array('hr'=>1), 'novalidate'=>array('form'=>1), 'nowrap'=>array('td'=>1, 'th'=>1), 'object'=>array('applet'=>1), 'open'=>array('details'=>1), 'optimum'=>array('meter'=>1), 'pattern'=>array('input'=>1), 'ping'=>array('a'=>1), 'placeholder'=>array('input'=>1, 'textarea'=>1), 'pluginspage'=>array('embed'=>1), 'pluginurl'=>array('embed'=>1), 'poster'=>array('video'=>1), 'pqg'=>array('keygen'=>1), 'preload'=>array('audio'=>1, 'video'=>1), 'prompt'=>array('isindex'=>1), 'radiogroup'=>array('command'=>1), 'readonly'=>array('textarea'=>1, 'input'=>1), 'rel'=>array('a'=>1, 'area'=>1, 'link'=>1), 'required'=>array('input'=>1, 'select'=>1, 'textarea'=>1), 'rev'=>array('a'=>1), 'reversed'=>array('ol'=>1), 'rows'=>array('textarea'=>1), 'rowspan'=>array('td'=>1, 'th'=>1), 'rules'=>array('table'=>1), 'sandbox'=>array('iframe'=>1), 'scope'=>array('td'=>1, 'th'=>1), 'scoped'=>array('style'=>1), 'scrolling'=>array('iframe'=>1), 'seamless'=>array('iframe'=>1), 'selected'=>array('option'=>1), 'shape'=>array('area'=>1, 'a'=>1), 'size'=>array('hr'=>1, 'font'=>1, 'input'=>1, 'select'=>1), 'sizes'=>array('link'=>1), 'span'=>array('col'=>1, 'colgroup'=>1), 'src'=>array('audio'=>1, 'embed'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'source'=>1, 'script'=>1, 'track'=>1, 'video'=>1), 'srcdoc'=>array('iframe'=>1), 'srclang'=>array('track'=>1), 'standby'=>array('object'=>1), 'start'=>array('ol'=>1), 'step'=>array('input'=>1), 'summary'=>array('table'=>1), 'target'=>array('a'=>1, 'area'=>1, 'form'=>1), 'type'=>array('a'=>1, 'area'=>1, 'command'=>1, 'embed'=>1, 'link'=>1, 'menu'=>1, 'object'=>1, 'param'=>1, 'script'=>1, 'source'=>1, 'style'=>1, 'input'=>1, 'li'=>1, 'ol'=>1, 'ul'=>1, 'button'=>1), 'typemustmatch'=>array('object'=>1), 'usemap'=>array('img'=>1, 'input'=>1, 'object'=>1), 'valign'=>array('col'=>1, 'colgroup'=>1, 'tbody'=>1, 'td'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1), 'value'=>array('data'=>1, 'input'=>1, 'meter'=>1, 'option'=>1, 'param'=>1, 'progress'=>1, 'button'=>1, 'li'=>1), 'valuetype'=>array('param'=>1), 'vspace'=>array('applet'=>1, 'embed'=>1, 'img'=>1, 'object'=>1), 'width'=>array('canvas'=>1, 'embed'=>1, 'hr'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'object'=>1, 'table'=>1, 'td'=>1, 'th'=>1, 'applet'=>1, 'col'=>1, 'colgroup'=>1, 'pre'=>1, 'video'=>1), 'wmode'=>array('embed'=>1), 'wrap'=>array('textarea'=>1)); // Ele-specific\nstatic $aNE = array('checkbox'=>1, 'checked'=>1, 'command'=>1, 'compact'=>1, 'declare'=>1, 'defer'=>1, 'default'=>1, 'disabled'=>1, 'ismap'=>1, 'itemscope'=>1, 'multiple'=>1, 'nohref'=>1, 'noresize'=>1, 'noshade'=>1, 'nowrap'=>1, 'open'=>1, 'radio'=>1, 'readonly'=>1, 'required'=>1, 'reversed'=>1, 'selected'=>1); // Empty\nstatic $aNP = array('action'=>1, 'cite'=>1, 'classid'=>1, 'codebase'=>1, 'data'=>1, 'href'=>1, 'itemtype'=>1, 'longdesc'=>1, 'model'=>1, 'pluginspage'=>1, 'pluginurl'=>1, 'usemap'=>1); // Need scheme check; excludes style, on* & src\nstatic $aNU = array('accesskey'=>1, 'aria-activedescendant'=>1, 'aria-atomic'=>1, 'aria-autocomplete'=>1, 'aria-busy'=>1, 'aria-checked'=>1, 'aria-controls'=>1, 'aria-describedby'=>1, 'aria-disabled'=>1, 'aria-dropeffect'=>1, 'aria-expanded'=>1, 'aria-flowto'=>1, 'aria-grabbed'=>1, 'aria-haspopup'=>1, 'aria-hidden'=>1, 'aria-invalid'=>1, 'aria-label'=>1, 'aria-labelledby'=>1, 'aria-level'=>1, 'aria-live'=>1, 'aria-multiline'=>1, 'aria-multiselectable'=>1, 'aria-orientation'=>1, 'aria-owns'=>1, 'aria-posinset'=>1, 'aria-pressed'=>1, 'aria-readonly'=>1, 'aria-relevant'=>1, 'aria-required'=>1, 'aria-selected'=>1, 'aria-setsize'=>1, 'aria-sort'=>1, 'aria-valuemax'=>1, 'aria-valuemin'=>1, 'aria-valuenow'=>1, 'aria-valuetext'=>1, 'class'=>1, 'contenteditable'=>1, 'contextmenu'=>1, 'dir'=>1, 'draggable'=>1, 'dropzone'=>1, 'hidden'=>1, 'id'=>1, 'inert'=>1, 'itemid'=>1, 'itemprop'=>1, 'itemref'=>1, 'itemscope'=>1, 'itemtype'=>1, 'lang'=>1, 'spellcheck'=>1, 'style'=>1, 'tabindex'=>1, 'title'=>1, 'translate'=>1, 'onabort'=>1, 'onblur'=>1, 'oncanplay'=>1, 'oncanplaythrough'=>1, 'onchange'=>1, 'onclick'=>1, 'oncontextmenu'=>1, 'oncuechange'=>1, 'ondblclick'=>1, 'ondrag'=>1, 'ondragend'=>1, 'ondragenter'=>1, 'ondragleave'=>1, 'ondragover'=>1, 'ondragstart'=>1, 'ondrop'=>1, 'ondurationchange'=>1, 'onemptied'=>1, 'onended'=>1, 'onerror'=>1, 'onfocus'=>1, 'oninput'=>1, 'oninvalid'=>1, 'onkeydown'=>1, 'onkeypress'=>1, 'onkeyup'=>1, 'onload'=>1, 'onloadeddata'=>1, 'onloadedmetadata'=>1, 'onloadstart'=>1, 'onmousedown'=>1, 'onmousemove'=>1, 'onmouseout'=>1, 'onmouseover'=>1, 'onmouseup'=>1, 'onmousewheel'=>1, 'onpause'=>1, 'onplay'=>1, 'onplaying'=>1, 'onprogress'=>1, 'onratechange'=>1, 'onreadystatechange'=>1, 'onreset'=>1, 'onscroll'=>1, 'onseeked'=>1, 'onseeking'=>1, 'onselect'=>1, 'onshow'=>1, 'onstalled'=>1, 'onsubmit'=>1, 'onsuspend'=>1, 'ontimeupdate'=>1, 'onvolumechange'=>1, 'onwaiting'=>1, 'role'=>1, 'translate'=>1, 'xmlns'=>1, 'xml:base'=>1, 'xml:lang'=>1, 'xml:space'=>1); // Univ\n\nif($C['lc_std_val']){\n // predef attr vals for $eAL & $aNE ele\n static $aNL = array('all'=>1, 'auto'=>1, 'baseline'=>1, 'bottom'=>1, 'button'=>1, 'captions'=>1, 'center'=>1, 'chapters'=>1, 'char'=>1, 'checkbox'=>1, 'circle'=>1, 'col'=>1, 'colgroup'=>1, 'color'=>1, 'cols'=>1, 'data'=>1, 'date'=>1, 'datetime'=>1, 'datetime-local'=>1, 'default'=>1, 'descriptions'=>1, 'email'=>1, 'file'=>1, 'get'=>1, 'groups'=>1, 'hidden'=>1, 'image'=>1, 'justify'=>1, 'left'=>1, 'ltr'=>1, 'metadata'=>1, 'middle'=>1, 'month'=>1, 'none'=>1, 'number'=>1, 'object'=>1, 'password'=>1, 'poly'=>1, 'post'=>1, 'preserve'=>1, 'radio'=>1, 'range'=>1, 'rect'=>1, 'ref'=>1, 'reset'=>1, 'right'=>1, 'row'=>1, 'rowgroup'=>1, 'rows'=>1, 'rtl'=>1, 'search'=>1, 'submit'=>1, 'subtitles'=>1, 'tel'=>1, 'text'=>1, 'top'=>1, 'url'=>1, 'week'=>1);\n static $eAL = array('a'=>1, 'area'=>1, 'bdo'=>1, 'button'=>1, 'col'=>1, 'fieldset'=>1, 'form'=>1, 'img'=>1, 'input'=>1, 'object'=>1, 'ol'=>1, 'optgroup'=>1, 'option'=>1, 'param'=>1, 'script'=>1, 'select'=>1, 'table'=>1, 'td'=>1, 'textarea'=>1, 'tfoot'=>1, 'th'=>1, 'thead'=>1, 'tr'=>1, 'track'=>1, 'xml:space'=>1);\n $lcase = isset($eAL[$e]) ? 1 : 0;\n}\n\n$depTr = 0;\nif($C['no_deprecated_attr']){\n // dep attr:applicable ele\n static $aND = array('align'=>array('caption'=>1, 'div'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'hr'=>1, 'img'=>1, 'input'=>1, 'legend'=>1, 'object'=>1, 'p'=>1, 'table'=>1), 'bgcolor'=>array('table'=>1, 'td'=>1, 'th'=>1, 'tr'=>1), 'border'=>array('object'=>1), 'bordercolor'=>array('table'=>1, 'td'=>1, 'tr'=>1), 'clear'=>array('br'=>1), 'compact'=>array('dl'=>1, 'ol'=>1, 'ul'=>1), 'height'=>array('td'=>1, 'th'=>1), 'hspace'=>array('img'=>1, 'object'=>1), 'language'=>array('script'=>1), 'name'=>array('a'=>1, 'form'=>1, 'iframe'=>1, 'img'=>1, 'map'=>1), 'noshade'=>array('hr'=>1), 'nowrap'=>array('td'=>1, 'th'=>1), 'size'=>array('hr'=>1), 'vspace'=>array('img'=>1, 'object'=>1), 'width'=>array('hr'=>1, 'pre'=>1, 'td'=>1, 'th'=>1));\n static $eAD = array('a'=>1, 'br'=>1, 'caption'=>1, 'div'=>1, 'dl'=>1, 'form'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'hr'=>1, 'iframe'=>1, 'img'=>1, 'input'=>1, 'legend'=>1, 'map'=>1, 'object'=>1, 'ol'=>1, 'p'=>1, 'pre'=>1, 'script'=>1, 'table'=>1, 'td'=>1, 'th'=>1, 'tr'=>1, 'ul'=>1);\n $depTr = isset($eAD[$e]) ? 1 : 0;\n}\n\n// attr name-vals\nif(strpos($a, \"\\x01\") !== false){$a = preg_replace('`\\x01[^\\x01]*\\x01`', '', $a);} // No comment/CDATA sec\n$mode = 0; $a = trim($a, ' /'); $aA = array();\nwhile(strlen($a)){\n $w = 0;\n switch($mode){\n  case 0: // Name\n   if(preg_match('`^[a-zA-Z][^\\s=]+`', $a, $m)){\n    $nm = strtolower($m[0]);\n    $w = $mode = 1; $a = ltrim(substr_replace($a, '', 0, strlen($m[0])));\n   }\n  break; case 1:\n   if($a[0] == '='){ // =\n    $w = 1; $mode = 2; $a = ltrim($a, '= ');\n   }else{ // No val\n    $w = 1; $mode = 0; $a = ltrim($a);\n    $aA[$nm] = '';\n   }\n  break; case 2: // Val\n   if(preg_match('`^((?:\"[^\"]*\")|(?:\\'[^\\']*\\')|(?:\\s*[^\\s\"\\']+))(.*)`', $a, $m)){\n    $a = ltrim($m[2]); $m = $m[1]; $w = 1; $mode = 0;\n    $aA[$nm] = trim(($m[0] == '\"' or $m[0] == '\\'') ? substr($m, 1, -1) : $m);\n   }\n  break;\n }\n if($w == 0){ // Parse errs, deal with space, \" & '\n  $a = preg_replace('`^(?:\"[^\"]*(\"|$)|\\'[^\\']*(\\'|$)|\\S)*\\s*`', '', $a);\n  $mode = 0;\n }\n}\nif($mode == 1){$aA[$nm] = '';}\n\n// clean attrs\nglobal $S;\n$rl = isset($S[$e]) ? $S[$e] : array();\n$a = array(); $nfr = 0;\nforeach($aA as $k=>$v){\n if(((isset($C['deny_attribute']['*']) ? isset($C['deny_attribute'][$k]) : !isset($C['deny_attribute'][$k])) && (isset($aN[$k][$e]) or isset($aNU[$k]) or preg_match('`data-((?!xml)[^:]+$)`', $k)) && !isset($rl['n'][$k]) && !isset($rl['n']['*'])) or isset($rl[$k])){\n  if(isset($aNE[$k])){$v = $k;}\n  elseif(!empty($lcase) && (($e != 'button' or $e != 'input') or $k == 'type')){ // Rather loose but ?not cause issues\n   $v = (isset($aNL[($v2 = strtolower($v))])) ? $v2 : $v;\n  }\n  if($k == 'style' && !$C['style_pass']){\n   if(false !== strpos($v, '&#')){\n    static $sC = array('&#x20;'=>' ', '&#32;'=>' ', '&#x45;'=>'e', '&#69;'=>'e', '&#x65;'=>'e', '&#101;'=>'e', '&#x58;'=>'x', '&#88;'=>'x', '&#x78;'=>'x', '&#120;'=>'x', '&#x50;'=>'p', '&#80;'=>'p', '&#x70;'=>'p', '&#112;'=>'p', '&#x53;'=>'s', '&#83;'=>'s', '&#x73;'=>'s', '&#115;'=>'s', '&#x49;'=>'i', '&#73;'=>'i', '&#x69;'=>'i', '&#105;'=>'i', '&#x4f;'=>'o', '&#79;'=>'o', '&#x6f;'=>'o', '&#111;'=>'o', '&#x4e;'=>'n', '&#78;'=>'n', '&#x6e;'=>'n', '&#110;'=>'n', '&#x55;'=>'u', '&#85;'=>'u', '&#x75;'=>'u', '&#117;'=>'u', '&#x52;'=>'r', '&#82;'=>'r', '&#x72;'=>'r', '&#114;'=>'r', '&#x4c;'=>'l', '&#76;'=>'l', '&#x6c;'=>'l', '&#108;'=>'l', '&#x28;'=>'(', '&#40;'=>'(', '&#x29;'=>')', '&#41;'=>')', '&#x20;'=>':', '&#32;'=>':', '&#x22;'=>'\"', '&#34;'=>'\"', '&#x27;'=>\"'\", '&#39;'=>\"'\", '&#x2f;'=>'/', '&#47;'=>'/', '&#x2a;'=>'*', '&#42;'=>'*', '&#x5c;'=>'\\\\', '&#92;'=>'\\\\');\n    $v = strtr($v, $sC);\n   }\n   $v = preg_replace_callback('`(url(?:\\()(?: )*(?:\\'|\"|&(?:quot|apos);)?)(.+?)((?:\\'|\"|&(?:quot|apos);)?(?: )*(?:\\)))`iS', 'htmLawed::hl_prot', $v);\n   $v = !$C['css_expression'] ? preg_replace('`expression`i', ' ', preg_replace('`\\\\\\\\\\S|(/|(%2f))(\\*|(%2a))`i', ' ', $v)) : $v;\n  }elseif(isset($aNP[$k]) or strpos($k, 'src') !== false or $k[0] == 'o'){\n   $v = str_replace(\"\\xad\", ' ', (strpos($v, '&') !== false ? str_replace(array('&#xad;', '&#173;', '&shy;'), ' ', $v) : $v));\n   $v = htmLawed::hl_prot($v, $k);\n   if($k == 'href'){ // X-spam\n    if($C['anti_mail_spam'] && strpos($v, 'mailto:') === 0){\n     $v = str_replace('@', htmlspecialchars($C['anti_mail_spam'], ENT_COMPAT, 'UTF-8'), $v);\n    }elseif($C['anti_link_spam']){\n     $r1 = $C['anti_link_spam'][1];\n     if(!empty($r1) && preg_match($r1, $v)){continue;}\n     $r0 = $C['anti_link_spam'][0];\n     if(!empty($r0) && preg_match($r0, $v)){\n      if(isset($a['rel'])){\n       if(!preg_match('`\\bnofollow\\b`i', $a['rel'])){$a['rel'] .= ' nofollow';}\n      }elseif(isset($aA['rel'])){\n       if(!preg_match('`\\bnofollow\\b`i', $aA['rel'])){$nfr = 1;}\n      }else{$a['rel'] = 'nofollow';}\n     }\n    }\n   }\n  }\n  if(isset($rl[$k]) && is_array($rl[$k]) && ($v = htmLawed::hl_attrval($v, $rl[$k])) === 0){continue;}\n  $a[$k] = str_replace('\"', '&quot;', $v);\n }\n}\nif($nfr){$a['rel'] = isset($a['rel']) ? $a['rel']. ' nofollow' : 'nofollow';}\n\n// rqd attr\nstatic $eAR = array('area'=>array('alt'=>'area'), 'bdo'=>array('dir'=>'ltr'), 'command'=>array('label'=>''), 'form'=>array('action'=>''), 'img'=>array('src'=>'', 'alt'=>'image'), 'map'=>array('name'=>''), 'optgroup'=>array('label'=>''), 'param'=>array('name'=>''), 'style'=>array('scoped'=>''), 'textarea'=>array('rows'=>'10', 'cols'=>'50'));\nif(isset($eAR[$e])){\n foreach($eAR[$e] as $k=>$v){\n  if(!isset($a[$k])){$a[$k] = isset($v[0]) ? $v : $k;}\n }\n}\n\n// depr attrs\nif($depTr){\n $c = array();\n foreach($a as $k=>$v){\n  if($k == 'style' or !isset($aND[$k][$e])){continue;}\n  if($k == 'align'){\n   unset($a['align']);\n   if($e == 'img' && ($v == 'left' or $v == 'right')){$c[] = 'float: '. $v;}\n   elseif(($e == 'div' or $e == 'table') && $v == 'center'){$c[] = 'margin: auto';}\n   else{$c[] = 'text-align: '. $v;}\n  }elseif($k == 'bgcolor'){\n   unset($a['bgcolor']);\n   $c[] = 'background-color: '. $v;\n  }elseif($k == 'border'){\n   unset($a['border']); $c[] = \"border: {$v}px\";\n  }elseif($k == 'bordercolor'){\n   unset($a['bordercolor']); $c[] = 'border-color: '. $v;\n  }elseif($k == 'clear'){\n   unset($a['clear']); $c[] = 'clear: '. ($v != 'all' ? $v : 'both');\n  }elseif($k == 'compact'){\n   unset($a['compact']); $c[] = 'font-size: 85%';\n  }elseif($k == 'height' or $k == 'width'){\n   unset($a[$k]); $c[] = $k. ': '. ($v[0] != '*' ? $v. (ctype_digit($v) ? 'px' : '') : 'auto');\n  }elseif($k == 'hspace'){\n   unset($a['hspace']); $c[] = \"margin-left: {$v}px; margin-right: {$v}px\";\n  }elseif($k == 'language' && !isset($a['type'])){\n   unset($a['language']);\n   $a['type'] = 'text/'. strtolower($v);\n  }elseif($k == 'name'){\n   if($C['no_deprecated_attr'] == 2 or ($e != 'a' && $e != 'map')){unset($a['name']);}\n   if(!isset($a['id']) && !preg_match('`\\W`', $v)){$a['id'] = $v;}\n  }elseif($k == 'noshade'){\n   unset($a['noshade']); $c[] = 'border-style: none; border: 0; background-color: gray; color: gray';\n  }elseif($k == 'nowrap'){\n   unset($a['nowrap']); $c[] = 'white-space: nowrap';\n  }elseif($k == 'size'){\n   unset($a['size']); $c[] = 'size: '. $v. 'px';\n  }elseif($k == 'vspace'){\n   unset($a['vspace']); $c[] = \"margin-top: {$v}px; margin-bottom: {$v}px\";\n  }\n }\n if(count($c)){\n  $c = implode('; ', $c);\n  $a['style'] = isset($a['style']) ? rtrim($a['style'], ' ;'). '; '. $c. ';': $c. ';';\n }\n}\n// unique ID\nif($C['unique_ids'] && isset($a['id'])){\n if(preg_match('`\\s`', ($id = $a['id'])) or (isset($GLOBALS['hl_Ids'][$id]) && $C['unique_ids'] == 1)){unset($a['id']);\n }else{\n  while(isset($GLOBALS['hl_Ids'][$id])){$id = $C['unique_ids']. $id;}\n  $GLOBALS['hl_Ids'][($a['id'] = $id)] = 1;\n }\n}\n// xml:lang\nif($C['xml:lang'] && isset($a['lang'])){\n $a['xml:lang'] = isset($a['xml:lang']) ? $a['xml:lang'] : $a['lang'];\n if($C['xml:lang'] == 2){unset($a['lang']);}\n}\n// for transformed tag\nif(!empty($trt)){\n $a['style'] = isset($a['style']) ? rtrim($a['style'], ' ;'). '; '. $trt : $trt;\n}\n// return with empty ele /\nif(empty($C['hook_tag'])){\n $aA = '';\n foreach($a as $k=>$v){$aA .= \" {$k}=\\\"{$v}\\\"\";}\n return \"<{$e}{$aA}\". (isset($eE[$e]) ? ' /' : ''). '>';\n}\nelse{return $C['hook_tag']($e, $a);}\n// eof\n}\n\npublic static function hl_tag2(&$e, &$a, $t=1){\n// transform tag\nif($e == 'big'){$e = 'span'; return 'font-size: larger;';}\nif($e == 's' or $e == 'strike'){$e = 'span'; return 'text-decoration: line-through;';}\nif($e == 'tt'){$e = 'code'; return '';}\nif($e == 'center'){$e = 'div'; return 'text-align: center;';}\nstatic $fs = array('0'=>'xx-small', '1'=>'xx-small', '2'=>'small', '3'=>'medium', '4'=>'large', '5'=>'x-large', '6'=>'xx-large', '7'=>'300%', '-1'=>'smaller', '-2'=>'60%', '+1'=>'larger', '+2'=>'150%', '+3'=>'200%', '+4'=>'300%');\nif($e == 'font'){\n $a2 = '';\n if(preg_match('`face\\s*=\\s*(\\'|\")([^=]+?)\\\\1`i', $a, $m) or preg_match('`face\\s*=(\\s*)(\\S+)`i', $a, $m)){\n  $a2 .= ' font-family: '. str_replace('\"', '\\'', trim($m[2])). ';';\n }\n if(preg_match('`color\\s*=\\s*(\\'|\")?(.+?)(\\\\1|\\s|$)`i', $a, $m)){\n  $a2 .= ' color: '. trim($m[2]). ';';\n }\n if(preg_match('`size\\s*=\\s*(\\'|\")?(.+?)(\\\\1|\\s|$)`i', $a, $m) && isset($fs[($m = trim($m[2]))])){\n  $a2 .= ' font-size: '. $fs[$m]. ';';\n }\n $e = 'span'; return ltrim($a2);\n}\nif($e == 'acronym'){$e = 'abbr'; return '';}\nif($e == 'dir'){$e = 'ul'; return '';}\nif($t == 2){$e = 0; return 0;}\nreturn '';\n// eof\n}\n\npublic static function hl_tidy($t, $w, $p){\n// Tidy/compact HTM\nif(strpos(' pre,script,textarea', \"$p,\")){return $t;}\n$t = str_replace(' </', '</', preg_replace(array('`(<\\w[^>]*(?<!/)>)\\s+`', '`\\s+`', '`(<\\w[^>]*(?<!/)>) `'), array(' $1', ' ', '$1'), preg_replace_callback(array('`(<(!\\[CDATA\\[))(.+?)(\\]\\]>)`sm', '`(<(!--))(.+?)(-->)`sm', '`(<(pre|script|textarea)[^>]*?>)(.+?)(</\\2>)`sm'), create_function('$m', 'return $m[1]. str_replace(array(\"<\", \">\", \"\\n\", \"\\r\", \"\\t\", \" \"), array(\"\\x01\", \"\\x02\", \"\\x03\", \"\\x04\", \"\\x05\", \"\\x07\"), $m[3]). $m[4];'), $t)));\nif(($w = strtolower($w)) == -1){\n return str_replace(array(\"\\x01\", \"\\x02\", \"\\x03\", \"\\x04\", \"\\x05\", \"\\x07\"), array('<', '>', \"\\n\", \"\\r\", \"\\t\", ' '), $t);\n}\n$s = strpos(\" $w\", 't') ? \"\\t\" : ' ';\n$s = preg_match('`\\d`', $w, $m) ? str_repeat($s, $m[0]) : str_repeat($s, ($s == \"\\t\" ? 1 : 2));\n$N = preg_match('`[ts]([1-9])`', $w, $m) ? $m[1] : 0;\n$a = array('br'=>1);\n$b = array('button'=>1, 'command'=>1, 'input'=>1, 'option'=>1, 'param'=>1, 'track'=>1);\n$c = array('audio'=>1, 'canvas'=>1, 'caption'=>1, 'dd'=>1, 'dt'=>1, 'figcaption'=>1, 'h1'=>1, 'h2'=>1, 'h3'=>1, 'h4'=>1, 'h5'=>1, 'h6'=>1, 'isindex'=>1, 'label'=>1, 'legend'=>1, 'li'=>1, 'object'=>1, 'p'=>1, 'pre'=>1, 'style'=>1, 'summary'=>1, 'td'=>1, 'textarea'=>1, 'th'=>1, 'video'=>1);\n$d = array('address'=>1, 'article'=>1, 'aside'=>1, 'blockquote'=>1, 'center'=>1, 'colgroup'=>1, 'datalist'=>1, 'details'=>1, 'dir'=>1, 'div'=>1, 'dl'=>1, 'fieldset'=>1, 'figure'=>1, 'footer'=>1, 'form'=>1, 'header'=>1, 'hgroup'=>1, 'hr'=>1, 'iframe'=>1, 'main'=>1, 'map'=>1, 'menu'=>1, 'nav'=>1, 'noscript'=>1, 'ol'=>1, 'optgroup'=>1, 'rbc'=>1, 'rtc'=>1, 'ruby'=>1, 'script'=>1, 'section'=>1, 'select'=>1, 'table'=>1, 'tbody'=>1, 'tfoot'=>1, 'thead'=>1, 'tr'=>1, 'ul'=>1);\n$T = explode('<', $t);\n$X = 1;\nwhile($X){\n $n = $N;\n $t = $T;\n ob_start();\n if(isset($d[$p])){echo str_repeat($s, ++$n);}\n echo ltrim(array_shift($t));\n for($i=-1, $j=count($t); ++$i<$j;){\n  $r = ''; list($e, $r) = explode('>', $t[$i]);\n  $x = $e[0] == '/' ? 0 : (substr($e, -1) == '/' ? 1 : ($e[0] != '!' ? 2 : -1));\n  $y = !$x ? ltrim($e, '/') : ($x > 0 ? substr($e, 0, strcspn($e, ' ')) : 0);\n  $e = \"<$e>\"; \n  if(isset($d[$y])){\n   if(!$x){\n    if($n){echo \"\\n\", str_repeat($s, --$n), \"$e\\n\", str_repeat($s, $n);}\n    else{++$N; ob_end_clean(); continue 2;}\n   }\n   else{echo \"\\n\", str_repeat($s, $n), \"$e\\n\", str_repeat($s, ($x != 1 ? ++$n : $n));}\n   echo ltrim($r); continue;\n  }\n  $f = \"\\n\". str_repeat($s, $n);\n  if(isset($c[$y])){\n   if(!$x){echo $e, $f, ltrim($r);}\n   else{echo $f, $e, $r;}\n  }elseif(isset($b[$y])){echo $f, $e, $r;\n  }elseif(isset($a[$y])){echo $e, $f, ltrim($r);\n  }elseif(!$y){echo $f, $e, $f, ltrim($r);\n  }else{echo $e, $r;}\n }\n $X = 0;\n}\n$t = preg_replace('`[\\n]\\s*?[\\n]+`', \"\\n\", ob_get_contents());\nob_end_clean();\nif(($l = strpos(\" $w\", 'r') ? (strpos(\" $w\", 'n') ? \"\\r\\n\" : \"\\r\") : 0)){\n $t = str_replace(\"\\n\", $l, $t);\n}\nreturn str_replace(array(\"\\x01\", \"\\x02\", \"\\x03\", \"\\x04\", \"\\x05\", \"\\x07\"), array('<', '>', \"\\n\", \"\\r\", \"\\t\", ' '), $t);\n// eof\n}\n\npublic static function hl_version(){\n// rel\nreturn '1.2.beta.2';\n// eof\n}\n\npublic static function kses($t, $h, $p=array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'gopher', 'mailto')){\n// kses compat\nforeach($h as $k=>$v){\n $h[$k]['n']['*'] = 1;\n}\n$C['cdata'] = $C['comment'] = $C['make_tag_strict'] = $C['no_deprecated_attr'] = $C['unique_ids'] = 0;\n$C['keep_bad'] = 1;\n$C['elements'] = count($h) ? strtolower(implode(',', array_keys($h))) : '-*';\n$C['hook'] = 'htmLawed::kses_hook';\n$C['schemes'] = '*:'. implode(',', $p);\nreturn htmLawed::hl($t, $C, $h);\n// eof\n}\n\npublic static function kses_hook($t, &$C, &$S){\n// kses compat\nreturn $t;\n// eof\n}\n// end class\n}\n"
  },
  {
    "path": "libraries/html5/Data.php",
    "content": "<?php\n\n// warning: this file is encoded in UTF-8!\n\nclass HTML5_Data\n{\n\n    // at some point this should be moved to a .ser file. Another\n    // possible optimization is to give UTF-8 bytes, not Unicode\n    // codepoints\n    // XXX: Not quite sure why it's named this; this is\n    // actually the numeric entity dereference table.\n    protected static $realCodepointTable = array(\n        0x00 => 0xFFFD, // REPLACEMENT CHARACTER\n        0x0D => 0x000A, // LINE FEED (LF)\n        0x80 => 0x20AC, // EURO SIGN ('€')\n        0x81 => 0x0081, // <control>\n        0x82 => 0x201A, // SINGLE LOW-9 QUOTATION MARK ('‚')\n        0x83 => 0x0192, // LATIN SMALL LETTER F WITH HOOK ('ƒ')\n        0x84 => 0x201E, // DOUBLE LOW-9 QUOTATION MARK ('„')\n        0x85 => 0x2026, // HORIZONTAL ELLIPSIS ('…')\n        0x86 => 0x2020, // DAGGER ('†')\n        0x87 => 0x2021, // DOUBLE DAGGER ('‡')\n        0x88 => 0x02C6, // MODIFIER LETTER CIRCUMFLEX ACCENT ('ˆ')\n        0x89 => 0x2030, // PER MILLE SIGN ('‰')\n        0x8A => 0x0160, // LATIN CAPITAL LETTER S WITH CARON ('Š')\n        0x8B => 0x2039, // SINGLE LEFT-POINTING ANGLE QUOTATION MARK ('‹')\n        0x8C => 0x0152, // LATIN CAPITAL LIGATURE OE ('Œ')\n        0x8D => 0x008D, // <control>\n        0x8E => 0x017D, // LATIN CAPITAL LETTER Z WITH CARON ('Ž')\n        0x8F => 0x008F, // <control>\n        0x90 => 0x0090, // <control>\n        0x91 => 0x2018, // LEFT SINGLE QUOTATION MARK ('‘')\n        0x92 => 0x2019, // RIGHT SINGLE QUOTATION MARK ('’')\n        0x93 => 0x201C, // LEFT DOUBLE QUOTATION MARK ('“')\n        0x94 => 0x201D, // RIGHT DOUBLE QUOTATION MARK ('”')\n        0x95 => 0x2022, // BULLET ('•')\n        0x96 => 0x2013, // EN DASH ('–')\n        0x97 => 0x2014, // EM DASH ('—')\n        0x98 => 0x02DC, // SMALL TILDE ('˜')\n        0x99 => 0x2122, // TRADE MARK SIGN ('™')\n        0x9A => 0x0161, // LATIN SMALL LETTER S WITH CARON ('š')\n        0x9B => 0x203A, // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK ('›')\n        0x9C => 0x0153, // LATIN SMALL LIGATURE OE ('œ')\n        0x9D => 0x009D, // <control>\n        0x9E => 0x017E, // LATIN SMALL LETTER Z WITH CARON ('ž')\n        0x9F => 0x0178, // LATIN CAPITAL LETTER Y WITH DIAERESIS ('Ÿ')\n    );\n\n    protected static $namedCharacterReferences;\n\n    protected static $namedCharacterReferenceMaxLength;\n\n    /**\n     * Returns the \"real\" Unicode codepoint of a malformed character\n     * reference.\n     */\n    public static function getRealCodepoint($ref) {\n        if (!isset(self::$realCodepointTable[$ref])) return false;\n        else return self::$realCodepointTable[$ref];\n    }\n\n    public static function getNamedCharacterReferences() {\n        if (!self::$namedCharacterReferences) {\n            self::$namedCharacterReferences = unserialize(\n                file_get_contents(dirname(__FILE__) . '/named-character-references.ser'));\n        }\n        return self::$namedCharacterReferences;\n    }\n\n    /**\n     * Converts a Unicode codepoint to sequence of UTF-8 bytes.\n     * @note Shamelessly stolen from HTML Purifier, which is also\n     *       shamelessly stolen from Feyd (which is in public domain).\n     */\n    public static function utf8chr($code) {\n        /* We don't care: we live dangerously\n         * if($code > 0x10FFFF or $code < 0x0 or\n          ($code >= 0xD800 and $code <= 0xDFFF) ) {\n            // bits are set outside the \"valid\" range as defined\n            // by UNICODE 4.1.0\n            return \"\\xEF\\xBF\\xBD\";\n          }*/\n\n        $x = $y = $z = $w = 0;\n        if ($code < 0x80) {\n            // regular ASCII character\n            $x = $code;\n        } else {\n            // set up bits for UTF-8\n            $x = ($code & 0x3F) | 0x80;\n            if ($code < 0x800) {\n               $y = (($code & 0x7FF) >> 6) | 0xC0;\n            } else {\n                $y = (($code & 0xFC0) >> 6) | 0x80;\n                if($code < 0x10000) {\n                    $z = (($code >> 12) & 0x0F) | 0xE0;\n                } else {\n                    $z = (($code >> 12) & 0x3F) | 0x80;\n                    $w = (($code >> 18) & 0x07) | 0xF0;\n                }\n            }\n        }\n        // set up the actual character\n        $ret = '';\n        if($w) $ret .= chr($w);\n        if($z) $ret .= chr($z);\n        if($y) $ret .= chr($y);\n        $ret .= chr($x);\n\n        return $ret;\n    }\n\n}\n"
  },
  {
    "path": "libraries/html5/InputStream.php",
    "content": "<?php\n\n/*\n\nCopyright 2009 Geoffrey Sneddon <http://gsnedders.com/>\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n*/\n\n// Some conventions:\n// /* */ indicates verbatim text from the HTML 5 specification\n// // indicates regular comments\n\nclass HTML5_InputStream {\n    /**\n     * The string data we're parsing.\n     */\n    private $data;\n\n    /**\n     * The current integer byte position we are in $data\n     */\n    private $char;\n\n    /**\n     * Length of $data; when $char === $data, we are at the end-of-file.\n     */\n    private $EOF;\n\n    /**\n     * Parse errors.\n     */\n    public $errors = array();\n\n    /**\n     * @param $data Data to parse\n     */\n    public function __construct($data) {\n\n        /* Given an encoding, the bytes in the input stream must be\n        converted to Unicode characters for the tokeniser, as\n        described by the rules for that encoding, except that the\n        leading U+FEFF BYTE ORDER MARK character, if any, must not\n        be stripped by the encoding layer (it is stripped by the rule below).\n\n        Bytes or sequences of bytes in the original byte stream that\n        could not be converted to Unicode characters must be converted\n        to U+FFFD REPLACEMENT CHARACTER code points. */\n\n        // XXX currently assuming input data is UTF-8; once we\n        // build encoding detection this will no longer be the case\n        //\n        // We previously had an mbstring implementation here, but that\n        // implementation is heavily non-conforming, so it's been\n        // omitted.\n        if (extension_loaded('iconv')) {\n            // non-conforming\n            $data = @iconv('UTF-8', 'UTF-8//IGNORE', $data);\n        } else {\n            // we can make a conforming native implementation\n            throw new Exception('Not implemented, please install mbstring or iconv');\n        }\n\n        /* One leading U+FEFF BYTE ORDER MARK character must be\n        ignored if any are present. */\n        if (substr($data, 0, 3) === \"\\xEF\\xBB\\xBF\") {\n            $data = substr($data, 3);\n        }\n\n        /* All U+0000 NULL characters in the input must be replaced\n        by U+FFFD REPLACEMENT CHARACTERs. Any occurrences of such\n        characters is a parse error. */\n        for ($i = 0, $count = substr_count($data, \"\\0\"); $i < $count; $i++) {\n            $this->errors[] = array(\n                'type' => HTML5_Tokenizer::PARSEERROR,\n                'data' => 'null-character'\n            );\n        }\n        /* U+000D CARRIAGE RETURN (CR) characters and U+000A LINE FEED\n        (LF) characters are treated specially. Any CR characters\n        that are followed by LF characters must be removed, and any\n        CR characters not followed by LF characters must be converted\n        to LF characters. Thus, newlines in HTML DOMs are represented\n        by LF characters, and there are never any CR characters in the\n        input to the tokenization stage. */\n        $data = str_replace(\n            array(\n                \"\\0\",\n                \"\\r\\n\",\n                \"\\r\"\n            ),\n            array(\n                \"\\xEF\\xBF\\xBD\",\n                \"\\n\",\n                \"\\n\"\n            ),\n            $data\n        );\n\n        /* Any occurrences of any characters in the ranges U+0001 to\n        U+0008, U+000B,  U+000E to U+001F,  U+007F  to U+009F,\n        U+D800 to U+DFFF , U+FDD0 to U+FDEF, and\n        characters U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, U+2FFFE, U+2FFFF,\n        U+3FFFE, U+3FFFF, U+4FFFE, U+4FFFF, U+5FFFE, U+5FFFF, U+6FFFE,\n        U+6FFFF, U+7FFFE, U+7FFFF, U+8FFFE, U+8FFFF, U+9FFFE, U+9FFFF,\n        U+AFFFE, U+AFFFF, U+BFFFE, U+BFFFF, U+CFFFE, U+CFFFF, U+DFFFE,\n        U+DFFFF, U+EFFFE, U+EFFFF, U+FFFFE, U+FFFFF, U+10FFFE, and\n        U+10FFFF are parse errors. (These are all control characters\n        or permanently undefined Unicode characters.) */\n        // Check PCRE is loaded.\n        if (extension_loaded('pcre')) {\n            $count = preg_match_all(\n                '/(?:\n                    [\\x01-\\x08\\x0B\\x0E-\\x1F\\x7F] # U+0001 to U+0008, U+000B,  U+000E to U+001F and U+007F\n                |\n                    \\xC2[\\x80-\\x9F] # U+0080 to U+009F\n                |\n                    \\xED(?:\\xA0[\\x80-\\xFF]|[\\xA1-\\xBE][\\x00-\\xFF]|\\xBF[\\x00-\\xBF]) # U+D800 to U+DFFFF\n                |\n                    \\xEF\\xB7[\\x90-\\xAF] # U+FDD0 to U+FDEF\n                |\n                    \\xEF\\xBF[\\xBE\\xBF] # U+FFFE and U+FFFF\n                |\n                    [\\xF0-\\xF4][\\x8F-\\xBF]\\xBF[\\xBE\\xBF] # U+nFFFE and U+nFFFF (1 <= n <= 10_{16})\n                )/x',\n                $data,\n                $matches\n            );\n            for ($i = 0; $i < $count; $i++) {\n                $this->errors[] = array(\n                    'type' => HTML5_Tokenizer::PARSEERROR,\n                    'data' => 'invalid-codepoint'\n                );\n            }\n        } else {\n            // XXX: Need non-PCRE impl, probably using substr_count\n        }\n\n        $this->data = $data;\n        $this->char = 0;\n        $this->EOF  = strlen($data);\n    }\n\n    /**\n     * Returns the current line that the tokenizer is at.\n     */\n    public function getCurrentLine() {\n        // Check the string isn't empty\n        if($this->EOF) {\n            // Add one to $this->char because we want the number for the next\n            // byte to be processed.\n            return substr_count($this->data, \"\\n\", 0, min($this->char, $this->EOF)) + 1;\n        } else {\n            // If the string is empty, we are on the first line (sorta).\n            return 1;\n        }\n    }\n\n    /**\n     * Returns the current column of the current line that the tokenizer is at.\n     */\n    public function getColumnOffset() {\n        // strrpos is weird, and the offset needs to be negative for what we\n        // want (i.e., the last \\n before $this->char). This needs to not have\n        // one (to make it point to the next character, the one we want the\n        // position of) added to it because strrpos's behaviour includes the\n        // final offset byte.\n        $lastLine = strrpos($this->data, \"\\n\", $this->char - 1 - strlen($this->data));\n\n        // However, for here we want the length up until the next byte to be\n        // processed, so add one to the current byte ($this->char).\n        if($lastLine !== false) {\n            $findLengthOf = substr($this->data, $lastLine + 1, $this->char - 1 - $lastLine);\n        } else {\n            $findLengthOf = substr($this->data, 0, $this->char);\n        }\n\n        // Get the length for the string we need.\n        if(extension_loaded('iconv')) {\n            return iconv_strlen($findLengthOf, 'utf-8');\n        } elseif(extension_loaded('mbstring')) {\n            return mb_strlen($findLengthOf, 'utf-8');\n        } elseif(extension_loaded('xml')) {\n            return strlen(utf8_decode($findLengthOf));\n        } else {\n            $count = count_chars($findLengthOf);\n            // 0x80 = 0x7F - 0 + 1 (one added to get inclusive range)\n            // 0x33 = 0xF4 - 0x2C + 1 (one added to get inclusive range)\n            return array_sum(array_slice($count, 0, 0x80)) +\n                   array_sum(array_slice($count, 0xC2, 0x33));\n        }\n    }\n\n    /**\n     * Retrieve the currently consume character.\n     * @note This performs bounds checking\n     */\n    public function char() {\n        return ($this->char++ < $this->EOF)\n            ? $this->data[$this->char - 1]\n            : false;\n    }\n\n    /**\n     * Get all characters until EOF.\n     * @note This performs bounds checking\n     */\n    public function remainingChars() {\n        if($this->char < $this->EOF) {\n            $data = substr($this->data, $this->char);\n            $this->char = $this->EOF;\n            return $data;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * Matches as far as possible until we reach a certain set of bytes\n     * and returns the matched substring.\n     * @param $bytes Bytes to match.\n     */\n    public function charsUntil($bytes, $max = null) {\n        if ($this->char < $this->EOF) {\n            if ($max === 0 || $max) {\n                $len = strcspn($this->data, $bytes, $this->char, $max);\n            } else {\n                $len = strcspn($this->data, $bytes, $this->char);\n            }\n            $string = (string) substr($this->data, $this->char, $len);\n            $this->char += $len;\n            return $string;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * Matches as far as possible with a certain set of bytes\n     * and returns the matched substring.\n     * @param $bytes Bytes to match.\n     */\n    public function charsWhile($bytes, $max = null) {\n        if ($this->char < $this->EOF) {\n            if ($max === 0 || $max) {\n                $len = strspn($this->data, $bytes, $this->char, $max);\n            } else {\n                $len = strspn($this->data, $bytes, $this->char);\n            }\n            $string = (string) substr($this->data, $this->char, $len);\n            $this->char += $len;\n            return $string;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * Unconsume one character.\n     */\n    public function unget() {\n        if ($this->char <= $this->EOF) {\n            $this->char--;\n        }\n    }\n}\n"
  },
  {
    "path": "libraries/html5/Parser.php",
    "content": "<?php\n\nrequire_once dirname(__FILE__) . '/Data.php';\nrequire_once dirname(__FILE__) . '/InputStream.php';\nrequire_once dirname(__FILE__) . '/TreeBuilder.php';\nrequire_once dirname(__FILE__) . '/Tokenizer.php';\n\n/**\n * Outwards facing interface for HTML5.\n */\nclass HTML5_Parser\n{\n    /**\n     * Parses a full HTML document.\n     * @param $text HTML text to parse\n     * @param $builder Custom builder implementation\n     * @return Parsed HTML as DOMDocument\n     */\n    static public function parse($text, $builder = null) {\n        $tokenizer = new HTML5_Tokenizer($text, $builder);\n        $tokenizer->parse();\n        return $tokenizer->save();\n    }\n    /**\n     * Parses an HTML fragment.\n     * @param $text HTML text to parse\n     * @param $context String name of context element to pretend parsing is in.\n     * @param $builder Custom builder implementation\n     * @return Parsed HTML as DOMDocument\n     */\n    static public function parseFragment($text, $context = null, $builder = null) {\n        $tokenizer = new HTML5_Tokenizer($text, $builder);\n        $tokenizer->parseFragment($context);\n        return $tokenizer->save();\n    }\n}\n"
  },
  {
    "path": "libraries/html5/Tokenizer.php",
    "content": "<?php\n\n/*\n\nCopyright 2007 Jeroen van der Meer <http://jero.net/>\nCopyright 2008 Edward Z. Yang <http://htmlpurifier.org/>\nCopyright 2009 Geoffrey Sneddon <http://gsnedders.com/>\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n*/\n\n// Some conventions:\n// /* */ indicates verbatim text from the HTML 5 specification\n// // indicates regular comments\n\n// all flags are in hyphenated form\n\nclass HTML5_Tokenizer {\n    /**\n     * Points to an InputStream object.\n     */\n    protected $stream;\n\n    /**\n     * Tree builder that the tokenizer emits token to.\n     */\n    private $tree;\n\n    /**\n     * Current content model we are parsing as.\n     */\n    protected $content_model;\n\n    /**\n     * Current token that is being built, but not yet emitted. Also\n     * is the last token emitted, if applicable.\n     */\n    protected $token;\n\n    // These are constants describing the content model\n    const PCDATA    = 0;\n    const RCDATA    = 1;\n    const CDATA     = 2;\n    const PLAINTEXT = 3;\n\n    // These are constants describing tokens\n    // XXX should probably be moved somewhere else, probably the\n    // HTML5 class.\n    const DOCTYPE        = 0;\n    const STARTTAG       = 1;\n    const ENDTAG         = 2;\n    const COMMENT        = 3;\n    const CHARACTER      = 4;\n    const SPACECHARACTER = 5;\n    const EOF            = 6;\n    const PARSEERROR     = 7;\n\n    // These are constants representing bunches of characters.\n    const ALPHA       = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n    const UPPER_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\n    const LOWER_ALPHA = 'abcdefghijklmnopqrstuvwxyz';\n    const DIGIT       = '0123456789';\n    const HEX         = '0123456789ABCDEFabcdef';\n    const WHITESPACE  = \"\\t\\n\\x0c \";\n\n    /**\n     * @param $data Data to parse\n     */\n    public function __construct($data, $builder = null) {\n        $this->stream = new HTML5_InputStream($data);\n        if (!$builder) $this->tree = new HTML5_TreeBuilder;\n        else $this->tree = $builder;\n        $this->content_model = self::PCDATA;\n    }\n\n    public function parseFragment($context = null) {\n        $this->tree->setupContext($context);\n        if ($this->tree->content_model) {\n            $this->content_model = $this->tree->content_model;\n            $this->tree->content_model = null;\n        }\n        $this->parse();\n    }\n\n    // XXX maybe convert this into an iterator? regardless, this function\n    // and the save function should go into a Parser facade of some sort\n    /**\n     * Performs the actual parsing of the document.\n     */\n    public function parse() {\n        // Current state\n        $state = 'data';\n        // This is used to avoid having to have look-behind in the data state.\n        $lastFourChars = '';\n        /**\n         * Escape flag as specified by the HTML5 specification: \"used to\n         * control the behavior of the tokeniser. It is either true or\n         * false, and initially must be set to the false state.\"\n         */\n        $escape = false;\n        //echo \"\\n\\n\";\n        while($state !== null) {\n            \n            /*echo $state . ' ';\n            switch ($this->content_model) {\n                case self::PCDATA: echo 'PCDATA'; break;\n                case self::RCDATA: echo 'RCDATA'; break;\n                case self::CDATA: echo 'CDATA'; break;\n                case self::PLAINTEXT: echo 'PLAINTEXT'; break;\n            }\n            if ($escape) echo \" escape\";\n            echo \"\\n\";*/\n            \n            switch($state) {\n                case 'data':\n\n                    /* Consume the next input character */\n                    $char = $this->stream->char();\n                    $lastFourChars .= $char;\n                    if (strlen($lastFourChars) > 4) $lastFourChars = substr($lastFourChars, -4);\n\n                    // see below for meaning\n                    $hyp_cond = \n                        !$escape &&\n                        (\n                            $this->content_model === self::RCDATA ||\n                            $this->content_model === self::CDATA\n                        );\n                    $amp_cond =\n                        !$escape &&\n                        (\n                            $this->content_model === self::PCDATA ||\n                            $this->content_model === self::RCDATA\n                        );\n                    $lt_cond =\n                        $this->content_model === self::PCDATA ||\n                        (\n                            (\n                                $this->content_model === self::RCDATA ||\n                                $this->content_model === self::CDATA\n                             ) &&\n                             !$escape\n                        );\n                    $gt_cond = \n                        $escape &&\n                        (\n                            $this->content_model === self::RCDATA ||\n                            $this->content_model === self::CDATA\n                        );\n\n                    if($char === '&' && $amp_cond) {\n                        /* U+0026 AMPERSAND (&)\n                        When the content model flag is set to one of the PCDATA or RCDATA\n                        states and the escape flag is false: switch to the\n                        character reference data state. Otherwise: treat it as per\n                        the \"anything else\" entry below. */\n                        $state = 'character reference data';\n\n                    } elseif(\n                        $char === '-' &&\n                        $hyp_cond &&\n                        $lastFourChars === '<!--'\n                    ) {\n                        /*\n                        U+002D HYPHEN-MINUS (-)\n                        If the content model flag is set to either the RCDATA state or\n                        the CDATA state, and the escape flag is false, and there are at\n                        least three characters before this one in the input stream, and the\n                        last four characters in the input stream, including this one, are\n                        U+003C LESS-THAN SIGN, U+0021 EXCLAMATION MARK, U+002D HYPHEN-MINUS,\n                        and U+002D HYPHEN-MINUS (\"<!--\"), then set the escape flag to true. */\n                        $escape = true;\n\n                        /* In any case, emit the input character as a character token. Stay\n                        in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::CHARACTER,\n                            'data' => '-'\n                        ));\n                        // We do the \"any case\" part as part of \"anything else\".\n\n                    /* U+003C LESS-THAN SIGN (<) */\n                    } elseif($char === '<' && $lt_cond) {\n                        /* When the content model flag is set to the PCDATA state: switch\n                        to the tag open state.\n\n                        When the content model flag is set to either the RCDATA state or\n                        the CDATA state and the escape flag is false: switch to the tag\n                        open state.\n\n                        Otherwise: treat it as per the \"anything else\" entry below. */\n                        $state = 'tag open';\n\n                    /* U+003E GREATER-THAN SIGN (>) */\n                    } elseif(\n                        $char === '>' &&\n                        $gt_cond &&\n                        substr($lastFourChars, 1) === '-->'\n                    ) {\n                        /* If the content model flag is set to either the RCDATA state or\n                        the CDATA state, and the escape flag is true, and the last three\n                        characters in the input stream including this one are U+002D\n                        HYPHEN-MINUS, U+002D HYPHEN-MINUS, U+003E GREATER-THAN SIGN (\"-->\"),\n                        set the escape flag to false. */\n                        $escape = false;\n\n                        /* In any case, emit the input character as a character token.\n                        Stay in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::CHARACTER,\n                            'data' => '>'\n                        ));\n                        // We do the \"any case\" part as part of \"anything else\".\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Emit an end-of-file token. */\n                        $state = null;\n                        $this->tree->emitToken(array(\n                            'type' => self::EOF\n                        ));\n                    \n                    } elseif($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        // Directly after emitting a token you switch back to the \"data\n                        // state\". At that point spaceCharacters are important so they are\n                        // emitted separately.\n                        $chars = $this->stream->charsWhile(self::WHITESPACE);\n                        $this->emitToken(array(\n                            'type' => self::SPACECHARACTER,\n                            'data' => $char . $chars\n                        ));\n                        $lastFourChars .= $chars;\n                        if (strlen($lastFourChars) > 4) $lastFourChars = substr($lastFourChars, -4);\n\n                    } else {\n                        /* Anything else\n                        THIS IS AN OPTIMIZATION: Get as many character that\n                        otherwise would also be treated as a character token and emit it\n                        as a single character token. Stay in the data state. */\n                        \n                        $mask = '';\n                        if ($hyp_cond) $mask .= '-';\n                        if ($amp_cond) $mask .= '&';\n                        if ($lt_cond)  $mask .= '<';\n                        if ($gt_cond)  $mask .= '>';\n\n                        if ($mask === '') {\n                            $chars = $this->stream->remainingChars();\n                        } else {\n                            $chars = $this->stream->charsUntil($mask);\n                        }\n\n                        $this->emitToken(array(\n                            'type' => self::CHARACTER,\n                            'data' => $char . $chars\n                        ));\n\n                        $lastFourChars .= $chars;\n                        if (strlen($lastFourChars) > 4) $lastFourChars = substr($lastFourChars, -4);\n\n                        $state = 'data';\n                    }\n                break;\n\n                case 'character reference data':\n                    /* (This cannot happen if the content model flag\n                    is set to the CDATA state.) */\n\n                    /* Attempt to consume a character reference, with no\n                    additional allowed character. */\n                    $entity = $this->consumeCharacterReference();\n\n                    /* If nothing is returned, emit a U+0026 AMPERSAND\n                    character token. Otherwise, emit the character token that\n                    was returned. */\n                    // This is all done when consuming the character reference.\n                    $this->emitToken(array(\n                        'type' => self::CHARACTER,\n                        'data' => $entity\n                    ));\n\n                    /* Finally, switch to the data state. */\n                    $state = 'data';\n                break;\n\n                case 'tag open':\n                    $char = $this->stream->char();\n\n                    switch($this->content_model) {\n                        case self::RCDATA:\n                        case self::CDATA:\n                            /* Consume the next input character. If it is a\n                            U+002F SOLIDUS (/) character, switch to the close\n                            tag open state. Otherwise, emit a U+003C LESS-THAN\n                            SIGN character token and reconsume the current input\n                            character in the data state. */\n                            // We consumed above.\n\n                            if($char === '/') {\n                                $state = 'close tag open';\n\n                            } else {\n                                $this->emitToken(array(\n                                    'type' => self::CHARACTER,\n                                    'data' => '<'\n                                ));\n\n                                $this->stream->unget();\n\n                                $state = 'data';\n                            }\n                        break;\n\n                        case self::PCDATA:\n                            /* If the content model flag is set to the PCDATA state\n                            Consume the next input character: */\n                            // We consumed above.\n\n                            if($char === '!') {\n                                /* U+0021 EXCLAMATION MARK (!)\n                                Switch to the markup declaration open state. */\n                                $state = 'markup declaration open';\n\n                            } elseif($char === '/') {\n                                /* U+002F SOLIDUS (/)\n                                Switch to the close tag open state. */\n                                $state = 'close tag open';\n\n                            } elseif('A' <= $char && $char <= 'Z') {\n                                /* U+0041 LATIN LETTER A through to U+005A LATIN LETTER Z\n                                Create a new start tag token, set its tag name to the lowercase\n                                version of the input character (add 0x0020 to the character's code\n                                point), then switch to the tag name state. (Don't emit the token\n                                yet; further details will be filled in before it is emitted.) */\n                                $this->token = array(\n                                    'name'  => strtolower($char),\n                                    'type'  => self::STARTTAG,\n                                    'attr'  => array()\n                                );\n\n                                $state = 'tag name';\n\n                            } elseif('a' <= $char && $char <= 'z') {\n                                /* U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z\n                                Create a new start tag token, set its tag name to the input\n                                character, then switch to the tag name state. (Don't emit\n                                the token yet; further details will be filled in before it\n                                is emitted.) */\n                                $this->token = array(\n                                    'name'  => $char,\n                                    'type'  => self::STARTTAG,\n                                    'attr'  => array()\n                                );\n\n                                $state = 'tag name';\n\n                            } elseif($char === '>') {\n                                /* U+003E GREATER-THAN SIGN (>)\n                                Parse error. Emit a U+003C LESS-THAN SIGN character token and a\n                                U+003E GREATER-THAN SIGN character token. Switch to the data state. */\n                                $this->emitToken(array(\n                                    'type' => self::PARSEERROR,\n                                    'data' => 'expected-tag-name-but-got-right-bracket'\n                                ));\n                                $this->emitToken(array(\n                                    'type' => self::CHARACTER,\n                                    'data' => '<>'\n                                ));\n\n                                $state = 'data';\n\n                            } elseif($char === '?') {\n                                /* U+003F QUESTION MARK (?)\n                                Parse error. Switch to the bogus comment state. */\n                                $this->emitToken(array(\n                                    'type' => self::PARSEERROR,\n                                    'data' => 'expected-tag-name-but-got-question-mark'\n                                ));\n                                $this->token = array(\n                                    'data' => '?',\n                                    'type' => self::COMMENT\n                                );\n                                $state = 'bogus comment';\n\n                            } else {\n                                /* Anything else\n                                Parse error. Emit a U+003C LESS-THAN SIGN character token and\n                                reconsume the current input character in the data state. */\n                                $this->emitToken(array(\n                                    'type' => self::PARSEERROR,\n                                    'data' => 'expected-tag-name'\n                                ));\n                                $this->emitToken(array(\n                                    'type' => self::CHARACTER,\n                                    'data' => '<'\n                                ));\n\n                                $state = 'data';\n                                $this->stream->unget();\n                            }\n                        break;\n                    }\n                break;\n\n                case 'close tag open':\n                    if (\n                        $this->content_model === self::RCDATA ||\n                        $this->content_model === self::CDATA\n                    ) {\n                        /* If the content model flag is set to the RCDATA or CDATA\n                        states... */\n                        $name = strtolower($this->stream->charsWhile(self::ALPHA));\n                        $following = $this->stream->char();\n                        $this->stream->unget();\n                        if (\n                            !$this->token ||\n                            $this->token['name'] !== $name ||\n                            $this->token['name'] === $name && !in_array($following, array(\"\\x09\", \"\\x0A\", \"\\x0C\", \"\\x20\", \"\\x3E\", \"\\x2F\", false))\n                        ) {\n                            /* if no start tag token has ever been emitted by this instance\n                            of the tokenizer (fragment case), or, if the next few\n                            characters do not match the tag name of the last start tag\n                            token emitted (compared in an ASCII case-insensitive manner),\n                            or if they do but they are not immediately followed by one of\n                            the following characters:\n\n                                * U+0009 CHARACTER TABULATION\n                                * U+000A LINE FEED (LF)\n                                * U+000C FORM FEED (FF)\n                                * U+0020 SPACE\n                                * U+003E GREATER-THAN SIGN (>)\n                                * U+002F SOLIDUS (/)\n                                * EOF\n\n                            ...then emit a U+003C LESS-THAN SIGN character token, a\n                            U+002F SOLIDUS character token, and switch to the data\n                            state to process the next input character. */\n                            // XXX: Probably ought to replace in_array with $following === x ||...\n\n                            // We also need to emit $name now we've consumed that, as we\n                            // know it'll just be emitted as a character token.\n                            $this->emitToken(array(\n                                'type' => self::CHARACTER,\n                                'data' => '</' . $name\n                            ));\n\n                            $state = 'data';\n                        } else {\n                            // This matches what would happen if we actually did the\n                            // otherwise below (but we can't because we've consumed too\n                            // much).\n\n                            // Start the end tag token with the name we already have.\n                            $this->token = array(\n                                'name'  => $name,\n                                'type'  => self::ENDTAG\n                            );\n\n                            // Change to tag name state.\n                            $state = 'tag name';\n                        }\n                    } elseif ($this->content_model === self::PCDATA) {\n                        /* Otherwise, if the content model flag is set to the PCDATA\n                        state [...]: */\n                        $char = $this->stream->char();\n\n                        if ('A' <= $char && $char <= 'Z') {\n                            /* U+0041 LATIN LETTER A through to U+005A LATIN LETTER Z\n                            Create a new end tag token, set its tag name to the lowercase version\n                            of the input character (add 0x0020 to the character's code point), then\n                            switch to the tag name state. (Don't emit the token yet; further details\n                            will be filled in before it is emitted.) */\n                            $this->token = array(\n                                'name'  => strtolower($char),\n                                'type'  => self::ENDTAG\n                            );\n\n                            $state = 'tag name';\n\n                        } elseif ('a' <= $char && $char <= 'z') {\n                            /* U+0061 LATIN SMALL LETTER A through to U+007A LATIN SMALL LETTER Z\n                            Create a new end tag token, set its tag name to the\n                            input character, then switch to the tag name state.\n                            (Don't emit the token yet; further details will be\n                            filled in before it is emitted.) */\n                            $this->token = array(\n                                'name'  => $char,\n                                'type'  => self::ENDTAG\n                            );\n\n                            $state = 'tag name';\n\n                        } elseif($char === '>') {\n                            /* U+003E GREATER-THAN SIGN (>)\n                            Parse error. Switch to the data state. */\n                            $this->emitToken(array(\n                                'type' => self::PARSEERROR,\n                                'data' => 'expected-closing-tag-but-got-right-bracket'\n                            ));\n                            $state = 'data';\n\n                        } elseif($char === false) {\n                            /* EOF\n                            Parse error. Emit a U+003C LESS-THAN SIGN character token and a U+002F\n                            SOLIDUS character token. Reconsume the EOF character in the data state. */\n                            $this->emitToken(array(\n                                'type' => self::PARSEERROR,\n                                'data' => 'expected-closing-tag-but-got-eof'\n                            ));\n                            $this->emitToken(array(\n                                'type' => self::CHARACTER,\n                                'data' => '</'\n                            ));\n\n                            $this->stream->unget();\n                            $state = 'data';\n\n                        } else {\n                            /* Parse error. Switch to the bogus comment state. */\n                            $this->emitToken(array(\n                                'type' => self::PARSEERROR,\n                                'data' => 'expected-closing-tag-but-got-char'\n                            ));\n                            $this->token = array(\n                                'data' => $char,\n                                'type' => self::COMMENT\n                            );\n                            $state = 'bogus comment';\n                        }\n                    }\n                break;\n\n                case 'tag name':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                        U+000A LINE FEED (LF)\n                        U+000C FORM FEED (FF)\n                        U+0020 SPACE\n                        Switch to the before attribute name state. */\n                        $state = 'before attribute name';\n\n                    } elseif($char === '/') {\n                        /* U+002F SOLIDUS (/)\n                        Switch to the self-closing start tag state. */\n                        $state = 'self-closing start tag';\n\n                    } elseif($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Emit the current tag token. Switch to the data state. */\n                        $this->emitToken($this->token);\n                        $state = 'data';\n\n                    } elseif('A' <= $char && $char <= 'Z') {\n                        /* U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z\n                        Append the lowercase version of the current input\n                        character (add 0x0020 to the character's code point) to\n                        the current tag token's tag name. Stay in the tag name state. */\n                        $chars = $this->stream->charsWhile(self::UPPER_ALPHA);\n\n                        $this->token['name'] .= strtolower($char . $chars);\n                        $state = 'tag name';\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Parse error. Reconsume the EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-tag-name'\n                        ));\n\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* Anything else\n                        Append the current input character to the current tag token's tag name.\n                        Stay in the tag name state. */\n                        $chars = $this->stream->charsUntil(\"\\t\\n\\x0C />\" . self::UPPER_ALPHA);\n\n                        $this->token['name'] .= $char . $chars;\n                        $state = 'tag name';\n                    }\n                break;\n\n                case 'before attribute name':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    // this conditional is optimized, check bottom\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                        U+000A LINE FEED (LF)\n                        U+000C FORM FEED (FF)\n                        U+0020 SPACE\n                        Stay in the before attribute name state. */\n                        $state = 'before attribute name';\n\n                    } elseif($char === '/') {\n                        /* U+002F SOLIDUS (/)\n                        Switch to the self-closing start tag state. */\n                        $state = 'self-closing start tag';\n\n                    } elseif($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Emit the current tag token. Switch to the data state. */\n                        $this->emitToken($this->token);\n                        $state = 'data';\n\n                    } elseif('A' <= $char && $char <= 'Z') {\n                        /* U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z\n                        Start a new attribute in the current tag token. Set that\n                        attribute's name to the lowercase version of the current\n                        input character (add 0x0020 to the character's code\n                        point), and its value to the empty string. Switch to the\n                        attribute name state.*/\n                        $this->token['attr'][] = array(\n                            'name'  => strtolower($char),\n                            'value' => ''\n                        );\n\n                        $state = 'attribute name';\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Parse error. Reconsume the EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'expected-attribute-name-but-got-eof'\n                        ));\n\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* U+0022 QUOTATION MARK (\")\n                           U+0027 APOSTROPHE (')\n                           U+003C LESS-THAN SIGN (<)\n                           U+003D EQUALS SIGN (=)\n                        Parse error. Treat it as per the \"anything else\" entry\n                        below. */\n                        if($char === '\"' || $char === \"'\" || $char === '<' || $char === '=') {\n                            $this->emitToken(array(\n                                'type' => self::PARSEERROR,\n                                'data' => 'invalid-character-in-attribute-name'\n                            ));\n                        }\n\n                        /* Anything else\n                        Start a new attribute in the current tag token. Set that attribute's\n                        name to the current input character, and its value to the empty string.\n                        Switch to the attribute name state. */\n                        $this->token['attr'][] = array(\n                            'name'  => $char,\n                            'value' => ''\n                        );\n\n                        $state = 'attribute name';\n                    }\n                break;\n\n                case 'attribute name':\n                    // Consume the next input character:\n                    $char = $this->stream->char();\n\n                    // this conditional is optimized, check bottom\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                        U+000A LINE FEED (LF)\n                        U+000C FORM FEED (FF)\n                        U+0020 SPACE\n                        Switch to the after attribute name state. */\n                        $state = 'after attribute name';\n\n                    } elseif($char === '/') {\n                        /* U+002F SOLIDUS (/)\n                        Switch to the self-closing start tag state. */\n                        $state = 'self-closing start tag';\n\n                    } elseif($char === '=') {\n                        /* U+003D EQUALS SIGN (=)\n                        Switch to the before attribute value state. */\n                        $state = 'before attribute value';\n\n                    } elseif($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Emit the current tag token. Switch to the data state. */\n                        $this->emitToken($this->token);\n                        $state = 'data';\n\n                    } elseif('A' <= $char && $char <= 'Z') {\n                        /* U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z\n                        Append the lowercase version of the current input\n                        character (add 0x0020 to the character's code point) to\n                        the current attribute's name. Stay in the attribute name\n                        state. */\n                        $chars = $this->stream->charsWhile(self::UPPER_ALPHA);\n\n                        $last = count($this->token['attr']) - 1;\n                        $this->token['attr'][$last]['name'] .= strtolower($char . $chars);\n\n                        $state = 'attribute name';\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Parse error. Reconsume the EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-attribute-name'\n                        ));\n\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* U+0022 QUOTATION MARK (\")\n                           U+0027 APOSTROPHE (')\n                           U+003C LESS-THAN SIGN (<)\n                        Parse error. Treat it as per the \"anything else\"\n                        entry below. */\n                        if($char === '\"' || $char === \"'\" || $char === '<') {\n                            $this->emitToken(array(\n                                'type' => self::PARSEERROR,\n                                'data' => 'invalid-character-in-attribute-name'\n                            ));\n                        }\n\n                        /* Anything else\n                        Append the current input character to the current attribute's name.\n                        Stay in the attribute name state. */\n                        $chars = $this->stream->charsUntil(\"\\t\\n\\x0C /=>\\\"'\" . self::UPPER_ALPHA);\n\n                        $last = count($this->token['attr']) - 1;\n                        $this->token['attr'][$last]['name'] .= $char . $chars;\n\n                        $state = 'attribute name';\n                    }\n\n                    /* When the user agent leaves the attribute name state\n                    (and before emitting the tag token, if appropriate), the\n                    complete attribute's name must be compared to the other\n                    attributes on the same token; if there is already an\n                    attribute on the token with the exact same name, then this\n                    is a parse error and the new attribute must be dropped, along\n                    with the value that gets associated with it (if any). */\n                    // this might be implemented in the emitToken method\n                break;\n\n                case 'after attribute name':\n                    // Consume the next input character:\n                    $char = $this->stream->char();\n\n                    // this is an optimized conditional, check the bottom\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                        U+000A LINE FEED (LF)\n                        U+000C FORM FEED (FF)\n                        U+0020 SPACE\n                        Stay in the after attribute name state. */\n                        $state = 'after attribute name';\n\n                    } elseif($char === '/') {\n                        /* U+002F SOLIDUS (/)\n                        Switch to the self-closing start tag state. */\n                        $state = 'self-closing start tag';\n\n                    } elseif($char === '=') {\n                        /* U+003D EQUALS SIGN (=)\n                        Switch to the before attribute value state. */\n                        $state = 'before attribute value';\n\n                    } elseif($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Emit the current tag token. Switch to the data state. */\n                        $this->emitToken($this->token);\n                        $state = 'data';\n\n                    } elseif('A' <= $char && $char <= 'Z') {\n                        /* U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z\n                        Start a new attribute in the current tag token. Set that\n                        attribute's name to the lowercase version of the current\n                        input character (add 0x0020 to the character's code\n                        point), and its value to the empty string. Switch to the\n                        attribute name state. */\n                        $this->token['attr'][] = array(\n                            'name'  => strtolower($char),\n                            'value' => ''\n                        );\n\n                        $state = 'attribute name';\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Parse error. Reconsume the EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'expected-end-of-tag-but-got-eof'\n                        ));\n\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* U+0022 QUOTATION MARK (\")\n                           U+0027 APOSTROPHE (')\n                           U+003C LESS-THAN SIGN(<)\n                        Parse error. Treat it as per the \"anything else\"\n                        entry below. */\n                        if($char === '\"' || $char === \"'\" || $char === \"<\") {\n                            $this->emitToken(array(\n                                'type' => self::PARSEERROR,\n                                'data' => 'invalid-character-after-attribute-name'\n                            ));\n                        }\n\n                        /* Anything else\n                        Start a new attribute in the current tag token. Set that attribute's\n                        name to the current input character, and its value to the empty string.\n                        Switch to the attribute name state. */\n                        $this->token['attr'][] = array(\n                            'name'  => $char,\n                            'value' => ''\n                        );\n\n                        $state = 'attribute name';\n                    }\n                break;\n\n                case 'before attribute value':\n                    // Consume the next input character:\n                    $char = $this->stream->char();\n\n                    // this is an optimized conditional\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                        U+000A LINE FEED (LF)\n                        U+000C FORM FEED (FF)\n                        U+0020 SPACE\n                        Stay in the before attribute value state. */\n                        $state = 'before attribute value';\n\n                    } elseif($char === '\"') {\n                        /* U+0022 QUOTATION MARK (\")\n                        Switch to the attribute value (double-quoted) state. */\n                        $state = 'attribute value (double-quoted)';\n\n                    } elseif($char === '&') {\n                        /* U+0026 AMPERSAND (&)\n                        Switch to the attribute value (unquoted) state and reconsume\n                        this input character. */\n                        $this->stream->unget();\n                        $state = 'attribute value (unquoted)';\n\n                    } elseif($char === '\\'') {\n                        /* U+0027 APOSTROPHE (')\n                        Switch to the attribute value (single-quoted) state. */\n                        $state = 'attribute value (single-quoted)';\n\n                    } elseif($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Parse error. Emit the current tag token. Switch to the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'expected-attribute-value-but-got-right-bracket'\n                        ));\n                        $this->emitToken($this->token);\n                        $state = 'data';\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Parse error. Reconsume the EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'expected-attribute-value-but-got-eof'\n                        ));\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* U+003D EQUALS SIGN (=)\n                         * U+003C LESS-THAN SIGN (<)\n                        Parse error. Treat it as per the \"anything else\" entry below. */\n                        if($char === '=' || $char === '<') {\n                            $this->emitToken(array(\n                                'type' => self::PARSEERROR,\n                                'data' => 'equals-in-unquoted-attribute-value'\n                            ));\n                        }\n\n                        /* Anything else\n                        Append the current input character to the current attribute's value.\n                        Switch to the attribute value (unquoted) state. */\n                        $last = count($this->token['attr']) - 1;\n                        $this->token['attr'][$last]['value'] .= $char;\n\n                        $state = 'attribute value (unquoted)';\n                    }\n                break;\n\n                case 'attribute value (double-quoted)':\n                    // Consume the next input character:\n                    $char = $this->stream->char();\n\n                    if($char === '\"') {\n                        /* U+0022 QUOTATION MARK (\")\n                        Switch to the after attribute value (quoted) state. */\n                        $state = 'after attribute value (quoted)';\n\n                    } elseif($char === '&') {\n                        /* U+0026 AMPERSAND (&)\n                        Switch to the character reference in attribute value\n                        state, with the additional allowed character\n                        being U+0022 QUOTATION MARK (\"). */\n                        $this->characterReferenceInAttributeValue('\"');\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Parse error. Reconsume the EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-attribute-value-double-quote'\n                        ));\n\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* Anything else\n                        Append the current input character to the current attribute's value.\n                        Stay in the attribute value (double-quoted) state. */\n                        $chars = $this->stream->charsUntil('\"&');\n\n                        $last = count($this->token['attr']) - 1;\n                        $this->token['attr'][$last]['value'] .= $char . $chars;\n\n                        $state = 'attribute value (double-quoted)';\n                    }\n                break;\n\n                case 'attribute value (single-quoted)':\n                    // Consume the next input character:\n                    $char = $this->stream->char();\n\n                    if($char === \"'\") {\n                        /* U+0022 QUOTATION MARK (')\n                        Switch to the after attribute value state. */\n                        $state = 'after attribute value (quoted)';\n\n                    } elseif($char === '&') {\n                        /* U+0026 AMPERSAND (&)\n                        Switch to the entity in attribute value state. */\n                        $this->characterReferenceInAttributeValue(\"'\");\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Parse error. Reconsume the EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-attribute-value-single-quote'\n                        ));\n\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* Anything else\n                        Append the current input character to the current attribute's value.\n                        Stay in the attribute value (single-quoted) state. */\n                        $chars = $this->stream->charsUntil(\"'&\");\n\n                        $last = count($this->token['attr']) - 1;\n                        $this->token['attr'][$last]['value'] .= $char . $chars;\n\n                        $state = 'attribute value (single-quoted)';\n                    }\n                break;\n\n                case 'attribute value (unquoted)':\n                    // Consume the next input character:\n                    $char = $this->stream->char();\n\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                        U+000A LINE FEED (LF)\n                        U+000C FORM FEED (FF)\n                        U+0020 SPACE\n                        Switch to the before attribute name state. */\n                        $state = 'before attribute name';\n\n                    } elseif($char === '&') {\n                        /* U+0026 AMPERSAND (&)\n                        Switch to the entity in attribute value state, with the \n                        additional allowed character  being U+003E \n                        GREATER-THAN SIGN (>). */\n                        $this->characterReferenceInAttributeValue('>');\n\n                    } elseif($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Emit the current tag token. Switch to the data state. */\n                        $this->emitToken($this->token);\n                        $state = 'data';\n\n                    } elseif ($char === false) {\n                        /* EOF\n                        Parse error. Reconsume the EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-attribute-value-no-quotes'\n                        ));\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* U+0022 QUOTATION MARK (\")\n                           U+0027 APOSTROPHE (')\n                           U+003C LESS-THAN SIGN (<)\n                           U+003D EQUALS SIGN (=)\n                        Parse error. Treat it as per the \"anything else\"\n                        entry below. */\n                        if($char === '\"' || $char === \"'\" || $char === '=' || $char == '<') {\n                            $this->emitToken(array(\n                                'type' => self::PARSEERROR,\n                                'data' => 'unexpected-character-in-unquoted-attribute-value'\n                            ));\n                        }\n\n                        /* Anything else\n                        Append the current input character to the current attribute's value.\n                        Stay in the attribute value (unquoted) state. */\n                        $chars = $this->stream->charsUntil(\"\\t\\n\\x0c &>\\\"'=\");\n\n                        $last = count($this->token['attr']) - 1;\n                        $this->token['attr'][$last]['value'] .= $char . $chars;\n\n                        $state = 'attribute value (unquoted)';\n                    }\n                break;\n\n                case 'after attribute value (quoted)':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                           U+000A LINE FEED (LF)\n                           U+000C FORM FEED (FF)\n                           U+0020 SPACE\n                        Switch to the before attribute name state. */\n                        $state = 'before attribute name';\n\n                    } elseif ($char === '/') {\n                        /* U+002F SOLIDUS (/)\n                        Switch to the self-closing start tag state. */\n                        $state = 'self-closing start tag';\n\n                    } elseif ($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Emit the current tag token. Switch to the data state. */\n                        $this->emitToken($this->token);\n                        $state = 'data';\n\n                    } elseif ($char === false) {\n                        /* EOF\n                        Parse error. Reconsume the EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-EOF-after-attribute-value'\n                        ));\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* Anything else\n                        Parse error. Reconsume the character in the before attribute\n                        name state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-character-after-attribute-value'\n                        ));\n                        $this->stream->unget();\n                        $state = 'before attribute name';\n                    }\n                break;\n\n                case 'self-closing start tag':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if ($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Set the self-closing flag of the current tag token.\n                        Emit the current tag token. Switch to the data state. */\n                        // not sure if this is the name we want\n                        $this->token['self-closing'] = true;\n                        $this->emitToken($this->token);\n                        $state = 'data';\n\n                    } elseif ($char === false) {\n                        /* EOF\n                        Parse error. Reconsume the EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-eof-after-self-closing'\n                        ));\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* Anything else\n                        Parse error. Reconsume the character in the before attribute name state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-character-after-self-closing'\n                        ));\n                        $this->stream->unget();\n                        $state = 'before attribute name';\n                    }\n                break;\n\n                case 'bogus comment':\n                    /* (This can only happen if the content model flag is set to the PCDATA state.) */\n                    /* Consume every character up to the first U+003E GREATER-THAN SIGN\n                    character (>) or the end of the file (EOF), whichever comes first. Emit\n                    a comment token whose data is the concatenation of all the characters\n                    starting from and including the character that caused the state machine\n                    to switch into the bogus comment state, up to and including the last\n                    consumed character before the U+003E character, if any, or up to the\n                    end of the file otherwise. (If the comment was started by the end of\n                    the file (EOF), the token is empty.) */\n                    $this->token['data'] .= (string) $this->stream->charsUntil('>');\n                    $this->stream->char();\n\n                    $this->emitToken($this->token);\n\n                    /* Switch to the data state. */\n                    $state = 'data';\n                break;\n\n                case 'markup declaration open':\n                    // Consume for below\n                    $hyphens = $this->stream->charsWhile('-', 2);\n                    if ($hyphens === '-') {\n                        $this->stream->unget();\n                    }\n                    if ($hyphens !== '--') {\n                        $alpha = $this->stream->charsWhile(self::ALPHA, 7);\n                    }\n\n                    /* If the next two characters are both U+002D HYPHEN-MINUS (-)\n                    characters, consume those two characters, create a comment token whose\n                    data is the empty string, and switch to the comment state. */\n                    if($hyphens === '--') {\n                        $state = 'comment start';\n                        $this->token = array(\n                            'data' => '',\n                            'type' => self::COMMENT\n                        );\n\n                    /* Otherwise if the next seven characters are a case-insensitive match\n                    for the word \"DOCTYPE\", then consume those characters and switch to the\n                    DOCTYPE state. */\n                    } elseif(strtoupper($alpha) === 'DOCTYPE') {\n                        $state = 'DOCTYPE';\n\n                    // XXX not implemented\n                    /* Otherwise, if the insertion mode is \"in foreign content\"\n                    and the current node is not an element in the HTML namespace\n                    and the next seven characters are an ASCII case-sensitive\n                    match for the string \"[CDATA[\" (the five uppercase letters\n                    \"CDATA\" with a U+005B LEFT SQUARE BRACKET character before\n                    and after), then consume those characters and switch to the\n                    CDATA section state (which is unrelated to the content model\n                    flag's CDATA state). */\n\n                    /* Otherwise, is is a parse error. Switch to the bogus comment state.\n                    The next character that is consumed, if any, is the first character\n                    that will be in the comment. */\n                    } else {\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'expected-dashes-or-doctype'\n                        ));\n                        $this->token = array(\n                            'data' => (string) $alpha,\n                            'type' => self::COMMENT\n                        );\n                        $state = 'bogus comment';\n                    }\n                break;\n\n                case 'comment start':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if ($char === '-') {\n                        /* U+002D HYPHEN-MINUS (-)\n                        Switch to the comment start dash state. */\n                        $state = 'comment start dash';\n                    } elseif ($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Parse error. Emit the comment token. Switch to the\n                        data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'incorrect-comment'\n                        ));\n                        $this->emitToken($this->token);\n                        $state = 'data';\n                    } elseif ($char === false) {\n                        /* EOF\n                        Parse error. Emit the comment token. Reconsume the\n                        EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-comment'\n                        ));\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n                    } else {\n                        /* Anything else\n                        Append the input character to the comment token's\n                        data. Switch to the comment state. */\n                        $this->token['data'] .= $char;\n                        $state = 'comment';\n                    }\n                break;\n\n                case 'comment start dash':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n                    if ($char === '-') {\n                        /* U+002D HYPHEN-MINUS (-)\n                        Switch to the comment end state */\n                        $state = 'comment end';\n                    } elseif ($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Parse error. Emit the comment token. Switch to the\n                        data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'incorrect-comment'\n                        ));\n                        $this->emitToken($this->token);\n                        $state = 'data';\n                    } elseif ($char === false) {\n                        /* Parse error. Emit the comment token. Reconsume the\n                        EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-comment'\n                        ));\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n                    } else {\n                        $this->token['data'] .= '-' . $char;\n                        $state = 'comment';\n                    }\n                break;\n\n                case 'comment':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if($char === '-') {\n                        /* U+002D HYPHEN-MINUS (-)\n                        Switch to the comment end dash state */\n                        $state = 'comment end dash';\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Parse error. Emit the comment token. Reconsume the EOF character\n                        in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-comment'\n                        ));\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* Anything else\n                        Append the input character to the comment token's data. Stay in\n                        the comment state. */\n                        $chars = $this->stream->charsUntil('-');\n\n                        $this->token['data'] .= $char . $chars;\n                    }\n                break;\n\n                case 'comment end dash':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if($char === '-') {\n                        /* U+002D HYPHEN-MINUS (-)\n                        Switch to the comment end state  */\n                        $state = 'comment end';\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Parse error. Emit the comment token. Reconsume the EOF character\n                        in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-comment-end-dash'\n                        ));\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* Anything else\n                        Append a U+002D HYPHEN-MINUS (-) character and the input\n                        character to the comment token's data. Switch to the comment state. */\n                        $this->token['data'] .= '-'.$char;\n                        $state = 'comment';\n                    }\n                break;\n\n                case 'comment end':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Emit the comment token. Switch to the data state. */\n                        $this->emitToken($this->token);\n                        $state = 'data';\n\n                    } elseif($char === '-') {\n                        /* U+002D HYPHEN-MINUS (-)\n                        Parse error. Append a U+002D HYPHEN-MINUS (-) character\n                        to the comment token's data. Stay in the comment end\n                        state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-dash-after-double-dash-in-comment'\n                        ));\n                        $this->token['data'] .= '-';\n\n                    } elseif($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0a\" || $char === ' ') {\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-space-after-double-dash-in-comment'\n                        ));\n                        $this->token['data'] .= '--' . $char;\n                        $state = 'comment end space';\n\n                    } elseif($char === '!') {\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-bang-after-double-dash-in-comment'\n                        ));\n                        $state = 'comment end bang';\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Parse error. Emit the comment token. Reconsume the\n                        EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-comment-double-dash'\n                        ));\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* Anything else\n                        Parse error. Append two U+002D HYPHEN-MINUS (-)\n                        characters and the input character to the comment token's\n                        data. Switch to the comment state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-char-in-comment'\n                        ));\n                        $this->token['data'] .= '--'.$char;\n                        $state = 'comment';\n                    }\n                break;\n\n                case 'comment end bang':\n                    $char = $this->stream->char();\n                    if ($char === '>') {\n                        $this->emitToken($this->token);\n                        $state = 'data';\n                    } elseif ($char === \"-\") {\n                        $this->token['data'] .= '--!';\n                        $state = 'comment end dash';\n                    } elseif ($char === false) {\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-comment-end-bang'\n                        ));\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n                    } else {\n                        $this->token['data'] .= '--!' . $char;\n                        $state = 'comment';\n                    }\n                break;\n\n                case 'comment end space':\n                    $char = $this->stream->char();\n                    if ($char === '>') {\n                        $this->emitToken($this->token);\n                        $state = 'data';\n                    } elseif ($char === '-') {\n                        $state = 'comment end dash';\n                    } elseif ($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        $this->token['data'] .= $char;\n                    } elseif ($char === false) {\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-eof-in-comment-end-space',\n                        ));\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n                    } else {\n                        $this->token['data'] .= $char;\n                        $state = 'comment';\n                    }\n                break;\n\n                case 'DOCTYPE':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                           U+000A LINE FEED (LF)\n                           U+000C FORM FEED (FF)\n                           U+0020 SPACE\n                        Switch to the before DOCTYPE name state. */\n                        $state = 'before DOCTYPE name';\n                    \n                    } elseif($char === false) {\n                        /* EOF\n                        Parse error. Create a new DOCTYPE token. Set its\n                        force-quirks flag to on. Emit the token. Reconsume the\n                        EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'need-space-after-doctype-but-got-eof'\n                        ));\n                        $this->emitToken(array(\n                            'name' => '',\n                            'type' => self::DOCTYPE,\n                            'force-quirks' => true,\n                            'error' => true\n                        ));\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* Anything else\n                        Parse error. Reconsume the current character in the\n                        before DOCTYPE name state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'need-space-after-doctype'\n                        ));\n                        $this->stream->unget();\n                        $state = 'before DOCTYPE name';\n                    }\n                break;\n\n                case 'before DOCTYPE name':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                           U+000A LINE FEED (LF)\n                           U+000C FORM FEED (FF)\n                           U+0020 SPACE\n                        Stay in the before DOCTYPE name state. */\n\n                    } elseif($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Parse error. Create a new DOCTYPE token. Set its\n                        force-quirks flag to on. Emit the token. Switch to the\n                        data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'expected-doctype-name-but-got-right-bracket'\n                        ));\n                        $this->emitToken(array(\n                            'name' => '',\n                            'type' => self::DOCTYPE,\n                            'force-quirks' => true,\n                            'error' => true\n                        ));\n\n                        $state = 'data';\n\n                    } elseif('A' <= $char && $char <= 'Z') {\n                        /* U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z\n                        Create a new DOCTYPE token. Set the token's name to the\n                        lowercase version of the input character (add 0x0020 to\n                        the character's code point). Switch to the DOCTYPE name\n                        state. */\n                        $this->token = array(\n                            'name' => strtolower($char),\n                            'type' => self::DOCTYPE,\n                            'error' => true\n                        );\n\n                        $state = 'DOCTYPE name';\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Parse error. Create a new DOCTYPE token. Set its\n                        force-quirks flag to on. Emit the token. Reconsume the\n                        EOF character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'expected-doctype-name-but-got-eof'\n                        ));\n                        $this->emitToken(array(\n                            'name' => '',\n                            'type' => self::DOCTYPE,\n                            'force-quirks' => true,\n                            'error' => true\n                        ));\n\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* Anything else\n                        Create a new DOCTYPE token. Set the token's name to the\n                        current input character. Switch to the DOCTYPE name state. */\n                        $this->token = array(\n                            'name' => $char,\n                            'type' => self::DOCTYPE,\n                            'error' => true\n                        );\n\n                        $state = 'DOCTYPE name';\n                    }\n                break;\n\n                case 'DOCTYPE name':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                           U+000A LINE FEED (LF)\n                           U+000C FORM FEED (FF)\n                           U+0020 SPACE\n                        Switch to the after DOCTYPE name state. */\n                        $state = 'after DOCTYPE name';\n\n                    } elseif($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Emit the current DOCTYPE token. Switch to the data state. */\n                        $this->emitToken($this->token);\n                        $state = 'data';\n\n                    } elseif('A' <= $char && $char <= 'Z') {\n                        /* U+0041 LATIN CAPITAL LETTER A through to U+005A LATIN CAPITAL LETTER Z\n                        Append the lowercase version of the input character\n                        (add 0x0020 to the character's code point) to the current\n                        DOCTYPE token's name. Stay in the DOCTYPE name state. */\n                        $this->token['name'] .= strtolower($char);\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Emit that DOCTYPE token. Reconsume the EOF\n                        character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-doctype-name'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* Anything else\n                        Append the current input character to the current\n                        DOCTYPE token's name. Stay in the DOCTYPE name state. */\n                        $this->token['name'] .= $char;\n                    }\n\n                    // XXX this is probably some sort of quirks mode designation,\n                    // check tree-builder to be sure. In general 'error' needs\n                    // to be specc'ified, this probably means removing it at the end\n                    $this->token['error'] = ($this->token['name'] === 'HTML')\n                        ? false\n                        : true;\n                break;\n\n                case 'after DOCTYPE name':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                           U+000A LINE FEED (LF)\n                           U+000C FORM FEED (FF)\n                           U+0020 SPACE\n                        Stay in the after DOCTYPE name state. */\n\n                    } elseif($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Emit the current DOCTYPE token. Switch to the data state. */\n                        $this->emitToken($this->token);\n                        $state = 'data';\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Emit that DOCTYPE token. Reconsume the EOF\n                        character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* Anything else */\n\n                        $nextSix = strtoupper($char . $this->stream->charsWhile(self::ALPHA, 5));\n                        if ($nextSix === 'PUBLIC') {\n                            /* If the next six characters are an ASCII\n                            case-insensitive match for the word \"PUBLIC\", then\n                            consume those characters and switch to the before\n                            DOCTYPE public identifier state. */\n                            $state = 'before DOCTYPE public identifier';\n\n                        } elseif ($nextSix === 'SYSTEM') {\n                            /* Otherwise, if the next six characters are an ASCII\n                            case-insensitive match for the word \"SYSTEM\", then\n                            consume those characters and switch to the before\n                            DOCTYPE system identifier state. */\n                            $state = 'before DOCTYPE system identifier';\n\n                        } else {\n                            /* Otherwise, this is the parse error. Set the DOCTYPE\n                            token's force-quirks flag to on. Switch to the bogus\n                            DOCTYPE state. */\n                            $this->emitToken(array(\n                                'type' => self::PARSEERROR,\n                                'data' => 'expected-space-or-right-bracket-in-doctype'\n                            ));\n                            $this->token['force-quirks'] = true;\n                            $this->token['error'] = true;\n                            $state = 'bogus DOCTYPE';\n                        }\n                    }\n                break;\n\n                case 'before DOCTYPE public identifier':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                           U+000A LINE FEED (LF)\n                           U+000C FORM FEED (FF)\n                           U+0020 SPACE\n                        Stay in the before DOCTYPE public identifier state. */\n                    } elseif ($char === '\"') {\n                        /* U+0022 QUOTATION MARK (\")\n                        Set the DOCTYPE token's public identifier to the empty\n                        string (not missing), then switch to the DOCTYPE public\n                        identifier (double-quoted) state. */\n                        $this->token['public'] = '';\n                        $state = 'DOCTYPE public identifier (double-quoted)';\n                    } elseif ($char === \"'\") {\n                        /* U+0027 APOSTROPHE (')\n                        Set the DOCTYPE token's public identifier to the empty\n                        string (not missing), then switch to the DOCTYPE public\n                        identifier (single-quoted) state. */\n                        $this->token['public'] = '';\n                        $state = 'DOCTYPE public identifier (single-quoted)';\n                    } elseif ($char === '>') {\n                        /* Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Emit that DOCTYPE token. Switch to the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-end-of-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $state = 'data';\n                    } elseif ($char === false) {\n                        /* Parse error. Set the DOCTYPE token's force-quirks\n                        flag to on. Emit that DOCTYPE token. Reconsume the EOF\n                        character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n                    } else {\n                        /* Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Switch to the bogus DOCTYPE state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-char-in-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $state = 'bogus DOCTYPE';\n                    }\n                break;\n\n                case 'DOCTYPE public identifier (double-quoted)':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if ($char === '\"') {\n                        /* U+0022 QUOTATION MARK (\")\n                        Switch to the after DOCTYPE public identifier state. */\n                        $state = 'after DOCTYPE public identifier';\n                    } elseif ($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Emit that DOCTYPE token. Switch to the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-end-of-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $state = 'data';\n                    } elseif ($char === false) {\n                        /* EOF\n                        Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Emit that DOCTYPE token. Reconsume the EOF\n                        character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n                    } else {\n                        /* Anything else\n                        Append the current input character to the current\n                        DOCTYPE token's public identifier. Stay in the DOCTYPE\n                        public identifier (double-quoted) state. */\n                        $this->token['public'] .= $char;\n                    }\n                break;\n\n                case 'DOCTYPE public identifier (single-quoted)':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if ($char === \"'\") {\n                        /* U+0027 APOSTROPHE (')\n                        Switch to the after DOCTYPE public identifier state. */\n                        $state = 'after DOCTYPE public identifier';\n                    } elseif ($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Emit that DOCTYPE token. Switch to the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-end-of-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $state = 'data';\n                    } elseif ($char === false) {\n                        /* EOF\n                        Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Emit that DOCTYPE token. Reconsume the EOF\n                        character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n                    } else {\n                        /* Anything else\n                        Append the current input character to the current\n                        DOCTYPE token's public identifier. Stay in the DOCTYPE\n                        public identifier (double-quoted) state. */\n                        $this->token['public'] .= $char;\n                    }\n                break;\n\n                case 'after DOCTYPE public identifier':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                           U+000A LINE FEED (LF)\n                           U+000C FORM FEED (FF)\n                           U+0020 SPACE\n                        Stay in the after DOCTYPE public identifier state. */\n                    } elseif ($char === '\"') {\n                        /* U+0022 QUOTATION MARK (\")\n                        Set the DOCTYPE token's system identifier to the\n                        empty string (not missing), then switch to the DOCTYPE\n                        system identifier (double-quoted) state. */\n                        $this->token['system'] = '';\n                        $state = 'DOCTYPE system identifier (double-quoted)';\n                    } elseif ($char === \"'\") {\n                        /* U+0027 APOSTROPHE (')\n                        Set the DOCTYPE token's system identifier to the\n                        empty string (not missing), then switch to the DOCTYPE\n                        system identifier (single-quoted) state. */\n                        $this->token['system'] = '';\n                        $state = 'DOCTYPE system identifier (single-quoted)';\n                    } elseif ($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Emit the current DOCTYPE token. Switch to the data state. */\n                        $this->emitToken($this->token);\n                        $state = 'data';\n                    } elseif ($char === false) {\n                        /* Parse error. Set the DOCTYPE token's force-quirks\n                        flag to on. Emit that DOCTYPE token. Reconsume the EOF\n                        character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n                    } else {\n                        /* Anything else\n                        Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Switch to the bogus DOCTYPE state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-char-in-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $state = 'bogus DOCTYPE';\n                    }\n                break;\n\n                case 'before DOCTYPE system identifier':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                           U+000A LINE FEED (LF)\n                           U+000C FORM FEED (FF)\n                           U+0020 SPACE\n                        Stay in the before DOCTYPE system identifier state. */\n                    } elseif ($char === '\"') {\n                        /* U+0022 QUOTATION MARK (\")\n                        Set the DOCTYPE token's system identifier to the empty\n                        string (not missing), then switch to the DOCTYPE system\n                        identifier (double-quoted) state. */\n                        $this->token['system'] = '';\n                        $state = 'DOCTYPE system identifier (double-quoted)';\n                    } elseif ($char === \"'\") {\n                        /* U+0027 APOSTROPHE (')\n                        Set the DOCTYPE token's system identifier to the empty\n                        string (not missing), then switch to the DOCTYPE system\n                        identifier (single-quoted) state. */\n                        $this->token['system'] = '';\n                        $state = 'DOCTYPE system identifier (single-quoted)';\n                    } elseif ($char === '>') {\n                        /* Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Emit that DOCTYPE token. Switch to the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-char-in-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $state = 'data';\n                    } elseif ($char === false) {\n                        /* Parse error. Set the DOCTYPE token's force-quirks\n                        flag to on. Emit that DOCTYPE token. Reconsume the EOF\n                        character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n                    } else {\n                        /* Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Switch to the bogus DOCTYPE state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-char-in-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $state = 'bogus DOCTYPE';\n                    }\n                break;\n\n                case 'DOCTYPE system identifier (double-quoted)':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if ($char === '\"') {\n                        /* U+0022 QUOTATION MARK (\")\n                        Switch to the after DOCTYPE system identifier state. */\n                        $state = 'after DOCTYPE system identifier';\n                    } elseif ($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Emit that DOCTYPE token. Switch to the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-end-of-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $state = 'data';\n                    } elseif ($char === false) {\n                        /* EOF\n                        Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Emit that DOCTYPE token. Reconsume the EOF\n                        character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n                    } else {\n                        /* Anything else\n                        Append the current input character to the current\n                        DOCTYPE token's system identifier. Stay in the DOCTYPE\n                        system identifier (double-quoted) state. */\n                        $this->token['system'] .= $char;\n                    }\n                break;\n\n                case 'DOCTYPE system identifier (single-quoted)':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if ($char === \"'\") {\n                        /* U+0027 APOSTROPHE (')\n                        Switch to the after DOCTYPE system identifier state. */\n                        $state = 'after DOCTYPE system identifier';\n                    } elseif ($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Emit that DOCTYPE token. Switch to the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-end-of-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $state = 'data';\n                    } elseif ($char === false) {\n                        /* EOF\n                        Parse error. Set the DOCTYPE token's force-quirks flag\n                        to on. Emit that DOCTYPE token. Reconsume the EOF\n                        character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n                    } else {\n                        /* Anything else\n                        Append the current input character to the current\n                        DOCTYPE token's system identifier. Stay in the DOCTYPE\n                        system identifier (double-quoted) state. */\n                        $this->token['system'] .= $char;\n                    }\n                break;\n\n                case 'after DOCTYPE system identifier':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if($char === \"\\t\" || $char === \"\\n\" || $char === \"\\x0c\" || $char === ' ') {\n                        /* U+0009 CHARACTER TABULATION\n                           U+000A LINE FEED (LF)\n                           U+000C FORM FEED (FF)\n                           U+0020 SPACE\n                        Stay in the after DOCTYPE system identifier state. */\n                    } elseif ($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Emit the current DOCTYPE token. Switch to the data state. */\n                        $this->emitToken($this->token);\n                        $state = 'data';\n                    } elseif ($char === false) {\n                        /* Parse error. Set the DOCTYPE token's force-quirks\n                        flag to on. Emit that DOCTYPE token. Reconsume the EOF\n                        character in the data state. */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'eof-in-doctype'\n                        ));\n                        $this->token['force-quirks'] = true;\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n                    } else {\n                        /* Anything else\n                        Parse error. Switch to the bogus DOCTYPE state.\n                        (This does not set the DOCTYPE token's force-quirks\n                        flag to on.) */\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'unexpected-char-in-doctype'\n                        ));\n                        $state = 'bogus DOCTYPE';\n                    }\n                break;\n\n                case 'bogus DOCTYPE':\n                    /* Consume the next input character: */\n                    $char = $this->stream->char();\n\n                    if ($char === '>') {\n                        /* U+003E GREATER-THAN SIGN (>)\n                        Emit the DOCTYPE token. Switch to the data state. */\n                        $this->emitToken($this->token);\n                        $state = 'data';\n\n                    } elseif($char === false) {\n                        /* EOF\n                        Emit the DOCTYPE token. Reconsume the EOF character in\n                        the data state. */\n                        $this->emitToken($this->token);\n                        $this->stream->unget();\n                        $state = 'data';\n\n                    } else {\n                        /* Anything else\n                        Stay in the bogus DOCTYPE state. */\n                    }\n                break;\n\n                // case 'cdataSection':\n\n            }\n        }\n    }\n\n    /**\n     * Returns a serialized representation of the tree.\n     */\n    public function save() {\n        return $this->tree->save();\n    }\n\n    /**\n     * Returns the input stream.\n     */\n    public function stream() {\n        return $this->stream;\n    }\n\n    private function consumeCharacterReference($allowed = false, $inattr = false) {\n        // This goes quite far against spec, and is far closer to the Python\n        // impl., mainly because we don't do the large unconsuming the spec\n        // requires.\n\n        // All consumed characters.\n        $chars = $this->stream->char();\n\n        /* This section defines how to consume a character\n        reference. This definition is used when parsing character\n        references in text and in attributes.\n\n        The behavior depends on the identity of the next character\n        (the one immediately after the U+0026 AMPERSAND character): */\n\n        if (\n            $chars[0] === \"\\x09\" ||\n            $chars[0] === \"\\x0A\" ||\n            $chars[0] === \"\\x0C\" ||\n            $chars[0] === \"\\x20\" ||\n            $chars[0] === '<' ||\n            $chars[0] === '&' ||\n            $chars === false ||\n            $chars[0] === $allowed\n        ) {\n            /* U+0009 CHARACTER TABULATION\n               U+000A LINE FEED (LF)\n               U+000C FORM FEED (FF)\n               U+0020 SPACE\n               U+003C LESS-THAN SIGN\n               U+0026 AMPERSAND\n               EOF\n               The additional allowed character, if there is one\n            Not a character reference. No characters are consumed,\n            and nothing is returned. (This is not an error, either.) */\n            // We already consumed, so unconsume.\n            $this->stream->unget();\n            return '&';\n        } elseif ($chars[0] === '#') {\n            /* Consume the U+0023 NUMBER SIGN. */\n            // Um, yeah, we already did that.\n            /* The behavior further depends on the character after\n            the U+0023 NUMBER SIGN: */\n            $chars .= $this->stream->char();\n            if (isset($chars[1]) && ($chars[1] === 'x' || $chars[1] === 'X')) {\n                /* U+0078 LATIN SMALL LETTER X\n                   U+0058 LATIN CAPITAL LETTER X */\n                /* Consume the X. */\n                // Um, yeah, we already did that.\n                /* Follow the steps below, but using the range of\n                characters U+0030 DIGIT ZERO through to U+0039 DIGIT\n                NINE, U+0061 LATIN SMALL LETTER A through to U+0066\n                LATIN SMALL LETTER F, and U+0041 LATIN CAPITAL LETTER\n                A, through to U+0046 LATIN CAPITAL LETTER F (in other\n                words, 0123456789, ABCDEF, abcdef). */\n                $char_class = self::HEX;\n                /* When it comes to interpreting the\n                number, interpret it as a hexadecimal number. */\n                $hex = true;\n            } else {\n                /* Anything else */\n                // Unconsume because we shouldn't have consumed this.\n                $chars = $chars[0];\n                $this->stream->unget();\n                /* Follow the steps below, but using the range of\n                characters U+0030 DIGIT ZERO through to U+0039 DIGIT\n                NINE (i.e. just 0123456789). */\n                $char_class = self::DIGIT;\n                /* When it comes to interpreting the number,\n                interpret it as a decimal number. */\n                $hex = false;\n            }\n\n            /* Consume as many characters as match the range of characters given above. */\n            $consumed = $this->stream->charsWhile($char_class);\n            if ($consumed === '' || $consumed === false) {\n                /* If no characters match the range, then don't consume\n                any characters (and unconsume the U+0023 NUMBER SIGN\n                character and, if appropriate, the X character). This\n                is a parse error; nothing is returned. */\n                $this->emitToken(array(\n                    'type' => self::PARSEERROR,\n                    'data' => 'expected-numeric-entity'\n                ));\n                return '&' . $chars;\n            } else {\n                /* Otherwise, if the next character is a U+003B SEMICOLON,\n                consume that too. If it isn't, there is a parse error. */\n                if ($this->stream->char() !== ';') {\n                    $this->stream->unget();\n                    $this->emitToken(array(\n                        'type' => self::PARSEERROR,\n                        'data' => 'numeric-entity-without-semicolon'\n                    ));\n                }\n\n                /* If one or more characters match the range, then take\n                them all and interpret the string of characters as a number\n                (either hexadecimal or decimal as appropriate). */\n                $codepoint = $hex ? hexdec($consumed) : (int) $consumed;\n\n                /* If that number is one of the numbers in the first column\n                of the following table, then this is a parse error. Find the\n                row with that number in the first column, and return a\n                character token for the Unicode character given in the\n                second column of that row. */\n                $new_codepoint = HTML5_Data::getRealCodepoint($codepoint);\n                if ($new_codepoint) {\n                    $this->emitToken(array(\n                        'type' => self::PARSEERROR,\n                        'data' => 'illegal-windows-1252-entity'\n                    ));\n                    return HTML5_Data::utf8chr($new_codepoint);\n                } else {\n                    /* Otherwise, if the number is greater than 0x10FFFF, then \n                     * this is a parse error. Return a U+FFFD REPLACEMENT \n                     * CHARACTER. */\n                    if ($codepoint > 0x10FFFF) {\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'overlong-character-entity' // XXX probably not correct\n                        ));\n                        return \"\\xEF\\xBF\\xBD\";\n                    }\n                    /* Otherwise, return a character token for the Unicode \n                     * character whose code point is that number.  If the \n                     * number is in the range 0x0001 to 0x0008,    0x000E to \n                     * 0x001F,  0x007F  to 0x009F, 0xD800 to 0xDFFF, 0xFDD0 to \n                     * 0xFDEF, or is one of 0x000B, 0xFFFE, 0xFFFF, 0x1FFFE, \n                     * 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, 0x3FFFF, 0x4FFFE, \n                     * 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE, \n                     * 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, \n                     * 0xAFFFF, 0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, \n                     * 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE, \n                     * or 0x10FFFF, then this is a parse error. */\n                    // && has higher precedence than ||\n                    if (\n                        $codepoint >= 0x0000 && $codepoint <= 0x0008 ||\n                        $codepoint === 0x000B ||\n                        $codepoint >= 0x000E && $codepoint <= 0x001F ||\n                        $codepoint >= 0x007F && $codepoint <= 0x009F ||\n                        $codepoint >= 0xD800 && $codepoint <= 0xDFFF ||\n                        $codepoint >= 0xFDD0 && $codepoint <= 0xFDEF ||\n                        ($codepoint & 0xFFFE) === 0xFFFE ||\n                        $codepoint == 0x10FFFF || $codepoint == 0x10FFFE\n                    ) {\n                        $this->emitToken(array(\n                            'type' => self::PARSEERROR,\n                            'data' => 'illegal-codepoint-for-numeric-entity'\n                        ));\n                    }\n                    return HTML5_Data::utf8chr($codepoint);\n                }\n            }\n\n        } else {\n            /* Anything else */\n\n            /* Consume the maximum number of characters possible,\n            with the consumed characters matching one of the\n            identifiers in the first column of the named character\n            references table (in a case-sensitive manner). */\n            // What we actually do here is consume as much as we can while it\n            // matches the start of one of the identifiers in the first column.\n\n            $refs = HTML5_Data::getNamedCharacterReferences();\n            \n            // Get the longest string which is the start of an identifier\n            // ($chars) as well as the longest identifier which matches ($id)\n            // and its codepoint ($codepoint).\n            $codepoint = false;\n            $char = $chars;\n            while ($char !== false && isset($refs[$char])) {\n                $refs = $refs[$char];\n                if (isset($refs['codepoint'])) {\n                    $id = $chars;\n                    $codepoint = $refs['codepoint'];\n                }\n                $chars .= $char = $this->stream->char();\n            }\n            \n            // Unconsume the one character we just took which caused the while\n            // statement to fail. This could be anything and could cause state\n            // changes (as if it matches the while loop it must be\n            // alphanumeric so we can just concat it to whatever we get later).\n            $this->stream->unget();\n            if ($char !== false) {\n                $chars = substr($chars, 0, -1);\n            }\n\n            /* If no match can be made, then this is a parse error.\n            No characters are consumed, and nothing is returned. */\n            if (!$codepoint) {\n                $this->emitToken(array(\n                    'type' => self::PARSEERROR,\n                    'data' => 'expected-named-entity'\n                ));\n                return '&' . $chars;\n            }\n\n            /* If the last character matched is not a U+003B SEMICOLON\n            (;), there is a parse error. */\n            $semicolon = true;\n            if (substr($id, -1) !== ';') {\n                $this->emitToken(array(\n                    'type' => self::PARSEERROR,\n                    'data' => 'named-entity-without-semicolon'\n                ));\n                $semicolon = false;\n            }\n\n            /* If the character reference is being consumed as part of\n            an attribute, and the last character matched is not a\n            U+003B SEMICOLON (;), and the next character is in the\n            range U+0030 DIGIT ZERO to U+0039 DIGIT NINE, U+0041\n            LATIN CAPITAL LETTER A to U+005A LATIN CAPITAL LETTER Z,\n            or U+0061 LATIN SMALL LETTER A to U+007A LATIN SMALL LETTER Z,\n            then, for historical reasons, all the characters that were\n            matched after the U+0026 AMPERSAND (&) must be unconsumed,\n            and nothing is returned. */\n            if ($inattr && !$semicolon) {\n                // The next character is either the next character in $chars or in the stream.\n                if (strlen($chars) > strlen($id)) {\n                    $next = substr($chars, strlen($id), 1);\n                } else {\n                    $next = $this->stream->char();\n                    $this->stream->unget();\n                }\n                if (\n                    '0' <= $next && $next <= '9' ||\n                    'A' <= $next && $next <= 'Z' ||\n                    'a' <= $next && $next <= 'z'\n                ) {\n                    return '&' . $chars;\n                }\n            }\n\n            /* Otherwise, return a character token for the character\n            corresponding to the character reference name (as given\n            by the second column of the named character references table). */\n            return HTML5_Data::utf8chr($codepoint) . substr($chars, strlen($id));\n        }\n    }\n\n    private function characterReferenceInAttributeValue($allowed = false) {\n        /* Attempt to consume a character reference. */\n        $entity = $this->consumeCharacterReference($allowed, true);\n\n        /* If nothing is returned, append a U+0026 AMPERSAND\n        character to the current attribute's value.\n\n        Otherwise, append the returned character token to the\n        current attribute's value. */\n        $char = (!$entity)\n            ? '&'\n            : $entity;\n\n        $last = count($this->token['attr']) - 1;\n        $this->token['attr'][$last]['value'] .= $char;\n\n        /* Finally, switch back to the attribute value state that you\n        were in when were switched into this state. */\n    }\n\n    /**\n     * Emits a token, passing it on to the tree builder.\n     */\n    protected function emitToken($token, $checkStream = true, $dry = false) {\n        if ($checkStream) {\n            // Emit errors from input stream.\n            while ($this->stream->errors) {\n                $this->emitToken(array_shift($this->stream->errors), false);\n            }\n        }\n        if($token['type'] === self::ENDTAG && !empty($token['attr'])) {\n            for ($i = 0; $i < count($token['attr']); $i++) {\n                $this->emitToken(array(\n                    'type' => self::PARSEERROR,\n                    'data' => 'attributes-in-end-tag'\n                ));\n            }\n        }\n        if($token['type'] === self::ENDTAG && !empty($token['self-closing'])) {\n            $this->emitToken(array(\n                'type' => self::PARSEERROR,\n                'data' => 'self-closing-flag-on-end-tag',\n            ));\n        }\n        if($token['type'] === self::STARTTAG) {\n            // This could be changed to actually pass the tree-builder a hash\n            $hash = array();\n            foreach ($token['attr'] as $keypair) {\n                if (isset($hash[$keypair['name']])) {\n                    $this->emitToken(array(\n                        'type' => self::PARSEERROR,\n                        'data' => 'duplicate-attribute',\n                    ));\n                } else {\n                    $hash[$keypair['name']] = $keypair['value'];\n                }\n            }\n        }\n\n        if(!$dry) {\n            // the current structure of attributes is not a terribly good one\n            $this->tree->emitToken($token);\n        }\n\n        if(!$dry && is_int($this->tree->content_model)) {\n            $this->content_model = $this->tree->content_model;\n            $this->tree->content_model = null;\n\n        } elseif($token['type'] === self::ENDTAG) {\n            $this->content_model = self::PCDATA;\n        }\n    }\n}\n\n"
  },
  {
    "path": "libraries/html5/TreeBuilder.php",
    "content": "<?php\n\n/*\n\nCopyright 2007 Jeroen van der Meer <http://jero.net/>\nCopyright 2009 Edward Z. Yang <edwardzyang@thewritingpot.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n*/\n\n// Tags for FIX ME!!!: (in order of priority)\n//      XXX - should be fixed NAO!\n//      XERROR - with regards to parse errors\n//      XSCRIPT - with regards to scripting mode\n//      XENCODING - with regards to encoding (for reparsing tests)\n//      XDOM - DOM specific code (tagName is explicitly not marked).\n//          this is not (yet) in helper functions.\n\nclass HTML5_TreeBuilder {\n    public $stack = array();\n    public $content_model;\n\n    private $mode;\n    private $original_mode;\n    private $secondary_mode;\n    private $dom;\n    // Whether or not normal insertion of nodes should actually foster\n    // parent (used in one case in spec)\n    private $foster_parent = false;\n    private $a_formatting  = array();\n\n    private $head_pointer = null;\n    private $form_pointer = null;\n\n    private $flag_frameset_ok = true;\n    private $flag_force_quirks = false;\n    private $ignored = false;\n    private $quirks_mode = null;\n    // this gets to 2 when we want to ignore the next lf character, and\n    // is decrement at the beginning of each processed token (this way,\n    // code can check for (bool)$ignore_lf_token, but it phases out\n    // appropriately)\n    private $ignore_lf_token = 0;\n    private $fragment = false;\n    private $root;\n\n    private $scoping = array('applet','button','caption','html','marquee','object','table','td','th', 'svg:foreignObject');\n    private $formatting = array('a','b','big','code','em','font','i','nobr','s','small','strike','strong','tt','u');\n    // dl and ds are speculative\n    private $special = array('address','area','article','aside','base','basefont','bgsound',\n    'blockquote','body','br','center','col','colgroup','command','dc','dd','details','dir','div','dl','ds',\n    'dt','embed','fieldset','figure','footer','form','frame','frameset','h1','h2','h3','h4','h5',\n    'h6','head','header','hgroup','hr','iframe','img','input','isindex','li','link',\n    'listing','menu','meta','nav','noembed','noframes','noscript','ol',\n    'p','param','plaintext','pre','script','select','spacer','style',\n    'tbody','textarea','tfoot','thead','title','tr','ul','wbr');\n\n    private $pendingTableCharacters;\n    private $pendingTableCharactersDirty;\n\n    // Tree construction modes\n    const INITIAL           = 0;\n    const BEFORE_HTML       = 1;\n    const BEFORE_HEAD       = 2;\n    const IN_HEAD           = 3;\n    const IN_HEAD_NOSCRIPT  = 4;\n    const AFTER_HEAD        = 5;\n    const IN_BODY           = 6;\n    const IN_CDATA_RCDATA   = 7;\n    const IN_TABLE          = 8;\n    const IN_TABLE_TEXT     = 9;\n    const IN_CAPTION        = 10;\n    const IN_COLUMN_GROUP   = 11;\n    const IN_TABLE_BODY     = 12;\n    const IN_ROW            = 13;\n    const IN_CELL           = 14;\n    const IN_SELECT         = 15;\n    const IN_SELECT_IN_TABLE= 16;\n    const IN_FOREIGN_CONTENT= 17;\n    const AFTER_BODY        = 18;\n    const IN_FRAMESET       = 19;\n    const AFTER_FRAMESET    = 20;\n    const AFTER_AFTER_BODY  = 21;\n    const AFTER_AFTER_FRAMESET = 22;\n\n    /**\n     * Converts a magic number to a readable name. Use for debugging.\n     */\n    private function strConst($number) {\n        static $lookup;\n        if (!$lookup) {\n            $lookup = array();\n            $r = new ReflectionClass('HTML5_TreeBuilder');\n            $consts = $r->getConstants();\n            foreach ($consts as $const => $num) {\n                if (!is_int($num)) continue;\n                $lookup[$num] = $const;\n            }\n        }\n        return $lookup[$number];\n    }\n\n    // The different types of elements.\n    const SPECIAL    = 100;\n    const SCOPING    = 101;\n    const FORMATTING = 102;\n    const PHRASING   = 103;\n\n    // Quirks modes in $quirks_mode\n    const NO_QUIRKS             = 200;\n    const QUIRKS_MODE           = 201;\n    const LIMITED_QUIRKS_MODE   = 202;\n\n    // Marker to be placed in $a_formatting\n    const MARKER     = 300;\n\n    // Namespaces for foreign content\n    const NS_HTML   = null; // to prevent DOM from requiring NS on everything\n    const NS_XHTML  = 'http://www.w3.org/1999/xhtml';\n    const NS_MATHML = 'http://www.w3.org/1998/Math/MathML';\n    const NS_SVG    = 'http://www.w3.org/2000/svg';\n    const NS_XLINK  = 'http://www.w3.org/1999/xlink';\n    const NS_XML    = 'http://www.w3.org/XML/1998/namespace';\n    const NS_XMLNS  = 'http://www.w3.org/2000/xmlns/';\n\n    // Different types of scopes to test for elements\n    const SCOPE = 0;\n    const SCOPE_LISTITEM = 1;\n    const SCOPE_TABLE = 2;\n\n    public function __construct() {\n        $this->mode = self::INITIAL;\n        $this->dom = new DOMDocument;\n\n        $this->dom->encoding = 'UTF-8';\n        $this->dom->preserveWhiteSpace = true;\n        $this->dom->substituteEntities = true;\n        $this->dom->strictErrorChecking = false;\n    }\n\n    // Process tag tokens\n    public function emitToken($token, $mode = null) {\n        // XXX: ignore parse errors... why are we emitting them, again?\n        if ($token['type'] === HTML5_Tokenizer::PARSEERROR) return;\n        if ($mode === null) $mode = $this->mode;\n\n        /*\n        $backtrace = debug_backtrace();\n        if ($backtrace[1]['class'] !== 'HTML5_TreeBuilder') echo \"--\\n\";\n        echo $this->strConst($mode);\n        if ($this->original_mode) echo \" (originally \".$this->strConst($this->original_mode).\")\";\n        echo \"\\n  \";\n        token_dump($token);\n        $this->printStack();\n        $this->printActiveFormattingElements();\n        if ($this->foster_parent) echo \"  -> this is a foster parent mode\\n\";\n        if ($this->flag_frameset_ok) echo \"  -> frameset ok\\n\";\n        */\n\n        if ($this->ignore_lf_token) $this->ignore_lf_token--;\n        $this->ignored = false;\n        // indenting is a little wonky, this can be changed later on\n        switch ($mode) {\n\n    case self::INITIAL:\n\n        /* A character token that is one of U+0009 CHARACTER TABULATION,\n         * U+000A LINE FEED (LF), U+000C FORM FEED (FF),  or U+0020 SPACE */\n        if ($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {\n            /* Ignore the token. */\n            $this->ignored = true;\n        } elseif ($token['type'] === HTML5_Tokenizer::DOCTYPE) {\n            if (\n                $token['name'] !== 'html' || !empty($token['public']) ||\n                !empty($token['system']) || $token !== 'about:legacy-compat'\n            ) {\n                /* If the DOCTYPE token's name is not a case-sensitive match\n                 * for the string \"html\", or if the token's public identifier\n                 * is not missing, or if the token's system identifier is\n                 * neither missing nor a case-sensitive match for the string\n                 * \"about:legacy-compat\", then there is a parse error (this\n                 * is the DOCTYPE parse error). */\n                // DOCTYPE parse error\n            }\n            /* Append a DocumentType node to the Document node, with the name\n             * attribute set to the name given in the DOCTYPE token, or the\n             * empty string if the name was missing; the publicId attribute\n             * set to the public identifier given in the DOCTYPE token, or\n             * the empty string if the public identifier was missing; the\n             * systemId attribute set to the system identifier given in the\n             * DOCTYPE token, or the empty string if the system identifier\n             * was missing; and the other attributes specific to\n             * DocumentType objects set to null and empty lists as\n             * appropriate. Associate the DocumentType node with the\n             * Document object so that it is returned as the value of the\n             * doctype attribute of the Document object. */\n            if (!isset($token['public'])) $token['public'] = null;\n            if (!isset($token['system'])) $token['system'] = null;\n            // XDOM\n            // Yes this is hacky. I'm kind of annoyed that I can't appendChild\n            // a doctype to DOMDocument. Maybe I haven't chanted the right\n            // syllables.\n            $impl = new DOMImplementation();\n            // This call can fail for particularly pathological cases (namely,\n            // the qualifiedName parameter ($token['name']) could be missing.\n            if ($token['name']) {\n                $doctype = $impl->createDocumentType($token['name'], $token['public'], $token['system']);\n                $this->dom->appendChild($doctype);\n            } else {\n                // It looks like libxml's not actually *able* to express this case.\n                // So... don't.\n                $this->dom->emptyDoctype = true;\n            }\n            $public = is_null($token['public']) ? false : strtolower($token['public']);\n            $system = is_null($token['system']) ? false : strtolower($token['system']);\n            $publicStartsWithForQuirks = array(\n             \"+//silmaril//dtd html pro v0r11 19970101//\",\n             \"-//advasoft ltd//dtd html 3.0 aswedit + extensions//\",\n             \"-//as//dtd html 3.0 aswedit + extensions//\",\n             \"-//ietf//dtd html 2.0 level 1//\",\n             \"-//ietf//dtd html 2.0 level 2//\",\n             \"-//ietf//dtd html 2.0 strict level 1//\",\n             \"-//ietf//dtd html 2.0 strict level 2//\",\n             \"-//ietf//dtd html 2.0 strict//\",\n             \"-//ietf//dtd html 2.0//\",\n             \"-//ietf//dtd html 2.1e//\",\n             \"-//ietf//dtd html 3.0//\",\n             \"-//ietf//dtd html 3.2 final//\",\n             \"-//ietf//dtd html 3.2//\",\n             \"-//ietf//dtd html 3//\",\n             \"-//ietf//dtd html level 0//\",\n             \"-//ietf//dtd html level 1//\",\n             \"-//ietf//dtd html level 2//\",\n             \"-//ietf//dtd html level 3//\",\n             \"-//ietf//dtd html strict level 0//\",\n             \"-//ietf//dtd html strict level 1//\",\n             \"-//ietf//dtd html strict level 2//\",\n             \"-//ietf//dtd html strict level 3//\",\n             \"-//ietf//dtd html strict//\",\n             \"-//ietf//dtd html//\",\n             \"-//metrius//dtd metrius presentational//\",\n             \"-//microsoft//dtd internet explorer 2.0 html strict//\",\n             \"-//microsoft//dtd internet explorer 2.0 html//\",\n             \"-//microsoft//dtd internet explorer 2.0 tables//\",\n             \"-//microsoft//dtd internet explorer 3.0 html strict//\",\n             \"-//microsoft//dtd internet explorer 3.0 html//\",\n             \"-//microsoft//dtd internet explorer 3.0 tables//\",\n             \"-//netscape comm. corp.//dtd html//\",\n             \"-//netscape comm. corp.//dtd strict html//\",\n             \"-//o'reilly and associates//dtd html 2.0//\",\n             \"-//o'reilly and associates//dtd html extended 1.0//\",\n             \"-//o'reilly and associates//dtd html extended relaxed 1.0//\",\n             \"-//spyglass//dtd html 2.0 extended//\",\n             \"-//sq//dtd html 2.0 hotmetal + extensions//\",\n             \"-//sun microsystems corp.//dtd hotjava html//\",\n             \"-//sun microsystems corp.//dtd hotjava strict html//\",\n             \"-//w3c//dtd html 3 1995-03-24//\",\n             \"-//w3c//dtd html 3.2 draft//\",\n             \"-//w3c//dtd html 3.2 final//\",\n             \"-//w3c//dtd html 3.2//\",\n             \"-//w3c//dtd html 3.2s draft//\",\n             \"-//w3c//dtd html 4.0 frameset//\",\n             \"-//w3c//dtd html 4.0 transitional//\",\n             \"-//w3c//dtd html experimental 19960712//\",\n             \"-//w3c//dtd html experimental 970421//\",\n             \"-//w3c//dtd w3 html//\",\n             \"-//w3o//dtd w3 html 3.0//\",\n             \"-//webtechs//dtd mozilla html 2.0//\",\n             \"-//webtechs//dtd mozilla html//\",\n            );\n            $publicSetToForQuirks = array(\n             \"-//w3o//dtd w3 html strict 3.0//\",\n             \"-/w3c/dtd html 4.0 transitional/en\",\n             \"html\",\n            );\n            $publicStartsWithAndSystemForQuirks = array(\n             \"-//w3c//dtd html 4.01 frameset//\",\n             \"-//w3c//dtd html 4.01 transitional//\",\n            );\n            $publicStartsWithForLimitedQuirks = array(\n             \"-//w3c//dtd xhtml 1.0 frameset//\",\n             \"-//w3c//dtd xhtml 1.0 transitional//\",\n            );\n            $publicStartsWithAndSystemForLimitedQuirks = array(\n             \"-//w3c//dtd html 4.01 frameset//\",\n             \"-//w3c//dtd html 4.01 transitional//\",\n            );\n            // first, do easy checks\n            if (\n                !empty($token['force-quirks']) ||\n                strtolower($token['name']) !== 'html'\n            ) {\n                $this->quirks_mode = self::QUIRKS_MODE;\n            } else {\n                do {\n                    if ($system) {\n                        foreach ($publicStartsWithAndSystemForQuirks as $x) {\n                            if (strncmp($public, $x, strlen($x)) === 0) {\n                                $this->quirks_mode = self::QUIRKS_MODE;\n                                break;\n                            }\n                        }\n                        if (!is_null($this->quirks_mode)) break;\n                        foreach ($publicStartsWithAndSystemForLimitedQuirks as $x) {\n                            if (strncmp($public, $x, strlen($x)) === 0) {\n                                $this->quirks_mode = self::LIMITED_QUIRKS_MODE;\n                                break;\n                            }\n                        }\n                        if (!is_null($this->quirks_mode)) break;\n                    }\n                    foreach ($publicSetToForQuirks as $x) {\n                        if ($public === $x) {\n                            $this->quirks_mode = self::QUIRKS_MODE;\n                            break;\n                        }\n                    }\n                    if (!is_null($this->quirks_mode)) break;\n                    foreach ($publicStartsWithForLimitedQuirks as $x) {\n                        if (strncmp($public, $x, strlen($x)) === 0) {\n                            $this->quirks_mode = self::LIMITED_QUIRKS_MODE;\n                        }\n                    }\n                    if (!is_null($this->quirks_mode)) break;\n                    if ($system === \"http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd\") {\n                        $this->quirks_mode = self::QUIRKS_MODE;\n                        break;\n                    }\n                    foreach ($publicStartsWithForQuirks as $x) {\n                        if (strncmp($public, $x, strlen($x)) === 0) {\n                            $this->quirks_mode = self::QUIRKS_MODE;\n                            break;\n                        }\n                    }\n                    if (is_null($this->quirks_mode)) {\n                        $this->quirks_mode = self::NO_QUIRKS;\n                    }\n                } while (false);\n            }\n            $this->mode = self::BEFORE_HTML;\n        } else {\n            // parse error\n            /* Switch the insertion mode to \"before html\", then reprocess the\n             * current token. */\n            $this->mode = self::BEFORE_HTML;\n            $this->quirks_mode = self::QUIRKS_MODE;\n            $this->emitToken($token);\n        }\n        break;\n\n    case self::BEFORE_HTML:\n\n        /* A DOCTYPE token */\n        if($token['type'] === HTML5_Tokenizer::DOCTYPE) {\n            // Parse error. Ignore the token.\n            $this->ignored = true;\n\n        /* A comment token */\n        } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {\n            /* Append a Comment node to the Document object with the data\n            attribute set to the data given in the comment token. */\n            // XDOM\n            $comment = $this->dom->createComment($token['data']);\n            $this->dom->appendChild($comment);\n\n        /* A character token that is one of one of U+0009 CHARACTER TABULATION,\n        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),\n        or U+0020 SPACE */\n        } elseif($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {\n            /* Ignore the token. */\n            $this->ignored = true;\n\n        /* A start tag whose tag name is \"html\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] == 'html') {\n            /* Create an element for the token in the HTML namespace. Append it \n             * to the Document  object. Put this element in the stack of open \n             * elements. */\n            // XDOM\n            $html = $this->insertElement($token, false);\n            $this->dom->appendChild($html);\n            $this->stack[] = $html;\n\n            $this->mode = self::BEFORE_HEAD;\n\n        } else {\n            /* Create an html element. Append it to the Document object. Put\n             * this element in the stack of open elements. */\n            // XDOM\n            $html = $this->dom->createElementNS(self::NS_HTML, 'html');\n            $this->dom->appendChild($html);\n            $this->stack[] = $html;\n\n            /* Switch the insertion mode to \"before head\", then reprocess the\n             * current token. */\n            $this->mode = self::BEFORE_HEAD;\n            $this->emitToken($token);\n        }\n        break;\n\n    case self::BEFORE_HEAD:\n\n        /* A character token that is one of one of U+0009 CHARACTER TABULATION,\n        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),\n        or U+0020 SPACE */\n        if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {\n            /* Ignore the token. */\n            $this->ignored = true;\n\n        /* A comment token */\n        } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {\n            /* Append a Comment node to the current node with the data attribute\n            set to the data given in the comment token. */\n            $this->insertComment($token['data']);\n\n        /* A DOCTYPE token */\n        } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {\n            /* Parse error. Ignore the token */\n            $this->ignored = true;\n            // parse error\n\n        /* A start tag token with the tag name \"html\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {\n            /* Process the token using the rules for the \"in body\"\n             * insertion mode. */\n            $this->processWithRulesFor($token, self::IN_BODY);\n\n        /* A start tag token with the tag name \"head\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'head') {\n            /* Insert an HTML element for the token. */\n            $element = $this->insertElement($token);\n\n            /* Set the head element pointer to this new element node. */\n            $this->head_pointer = $element;\n\n            /* Change the insertion mode to \"in head\". */\n            $this->mode = self::IN_HEAD;\n\n        /* An end tag whose tag name is one of: \"head\", \"body\", \"html\", \"br\" */\n        } elseif(\n            $token['type'] === HTML5_Tokenizer::ENDTAG && (\n                $token['name'] === 'head' || $token['name'] === 'body' ||\n                $token['name'] === 'html' || $token['name'] === 'br'\n        )) {\n            /* Act as if a start tag token with the tag name \"head\" and no\n             * attributes had been seen, then reprocess the current token. */\n            $this->emitToken(array(\n                'name' => 'head',\n                'type' => HTML5_Tokenizer::STARTTAG,\n                'attr' => array()\n            ));\n            $this->emitToken($token);\n\n        /* Any other end tag */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG) {\n            /* Parse error. Ignore the token. */\n            $this->ignored = true;\n\n        } else {\n            /* Act as if a start tag token with the tag name \"head\" and no\n             * attributes had been seen, then reprocess the current token.\n             * Note: This will result in an empty head element being\n             * generated, with the current token being reprocessed in the\n             * \"after head\" insertion mode. */\n            $this->emitToken(array(\n                'name' => 'head',\n                'type' => HTML5_Tokenizer::STARTTAG,\n                'attr' => array()\n            ));\n            $this->emitToken($token);\n        }\n        break;\n\n    case self::IN_HEAD:\n\n        /* A character token that is one of one of U+0009 CHARACTER TABULATION,\n        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),\n        or U+0020 SPACE. */\n        if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {\n            /* Insert the character into the current node. */\n            $this->insertText($token['data']);\n\n        /* A comment token */\n        } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {\n            /* Append a Comment node to the current node with the data attribute\n            set to the data given in the comment token. */\n            $this->insertComment($token['data']);\n\n        /* A DOCTYPE token */\n        } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {\n            /* Parse error. Ignore the token. */\n            $this->ignored = true;\n            // parse error\n\n        /* A start tag whose tag name is \"html\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        $token['name'] === 'html') {\n            $this->processWithRulesFor($token, self::IN_BODY);\n\n        /* A start tag whose tag name is one of: \"base\", \"command\", \"link\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        ($token['name'] === 'base' || $token['name'] === 'command' ||\n        $token['name'] === 'link')) {\n            /* Insert an HTML element for the token. Immediately pop the\n             * current node off the stack of open elements. */\n            $this->insertElement($token);\n            array_pop($this->stack);\n\n            // YYY: Acknowledge the token's self-closing flag, if it is set.\n\n        /* A start tag whose tag name is \"meta\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'meta') {\n            /* Insert an HTML element for the token. Immediately pop the\n             * current node off the stack of open elements. */\n            $this->insertElement($token);\n            array_pop($this->stack);\n\n            // XERROR: Acknowledge the token's self-closing flag, if it is set.\n\n            // XENCODING: If the element has a charset attribute, and its value is a\n            // supported encoding, and the confidence is currently tentative,\n            // then change the encoding to the encoding given by the value of\n            // the charset attribute.\n            //\n            // Otherwise, if the element has a content attribute, and applying\n            // the algorithm for extracting an encoding from a Content-Type to\n            // its value returns a supported encoding encoding, and the\n            // confidence is currently tentative, then change the encoding to\n            // the encoding encoding.\n\n        /* A start tag with the tag name \"title\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'title') {\n            $this->insertRCDATAElement($token);\n\n        /* A start tag whose tag name is \"noscript\", if the scripting flag is enabled, or\n         * A start tag whose tag name is one of: \"noframes\", \"style\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        ($token['name'] === 'noscript' || $token['name'] === 'noframes' || $token['name'] === 'style')) {\n            // XSCRIPT: Scripting flag not respected\n            $this->insertCDATAElement($token);\n\n        // XSCRIPT: Scripting flag disable not implemented\n\n        /* A start tag with the tag name \"script\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'script') {\n            /* 1. Create an element for the token in the HTML namespace. */\n            $node = $this->insertElement($token, false);\n\n            /* 2. Mark the element as being \"parser-inserted\" */\n            // Uhhh... XSCRIPT\n\n            /* 3. If the parser was originally created for the HTML\n             * fragment parsing algorithm, then mark the script element as \n             * \"already executed\". (fragment case) */\n            // ditto... XSCRIPT\n\n            /* 4. Append the new element to the current node  and push it onto \n             * the stack of open elements.  */\n            end($this->stack)->appendChild($node);\n            $this->stack[] = $node;\n            // I guess we could squash these together\n\n            /* 6. Let the original insertion mode be the current insertion mode. */\n            $this->original_mode = $this->mode;\n            /* 7. Switch the insertion mode to \"in CDATA/RCDATA\" */\n            $this->mode = self::IN_CDATA_RCDATA;\n            /* 5. Switch the tokeniser's content model flag to the CDATA state. */\n            $this->content_model = HTML5_Tokenizer::CDATA;\n\n        /* An end tag with the tag name \"head\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'head') {\n            /* Pop the current node (which will be the head element) off the stack of open elements. */\n            array_pop($this->stack);\n\n            /* Change the insertion mode to \"after head\". */\n            $this->mode = self::AFTER_HEAD;\n\n        // Slight logic inversion here to minimize duplication\n        /* A start tag with the tag name \"head\". */\n        /* An end tag whose tag name is not one of: \"body\", \"html\", \"br\" */\n        } elseif(($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'head') ||\n        ($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] !== 'html' &&\n        $token['name'] !== 'body' && $token['name'] !== 'br')) {\n            // Parse error. Ignore the token.\n            $this->ignored = true;\n\n        /* Anything else */\n        } else {\n            /* Act as if an end tag token with the tag name \"head\" had been\n             * seen, and reprocess the current token. */\n            $this->emitToken(array(\n                'name' => 'head',\n                'type' => HTML5_Tokenizer::ENDTAG\n            ));\n\n            /* Then, reprocess the current token. */\n            $this->emitToken($token);\n        }\n        break;\n\n    case self::IN_HEAD_NOSCRIPT:\n        if ($token['type'] === HTML5_Tokenizer::DOCTYPE) {\n            // parse error\n        } elseif ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {\n            $this->processWithRulesFor($token, self::IN_BODY);\n        } elseif ($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'noscript') {\n            /* Pop the current node (which will be a noscript element) from the\n             * stack of open elements; the new current node will be a head\n             * element. */\n            array_pop($this->stack);\n            $this->mode = self::IN_HEAD;\n        } elseif (\n            ($token['type'] === HTML5_Tokenizer::SPACECHARACTER) ||\n            ($token['type'] === HTML5_Tokenizer::COMMENT) ||\n            ($token['type'] === HTML5_Tokenizer::STARTTAG && (\n                $token['name'] === 'link' || $token['name'] === 'meta' ||\n                $token['name'] === 'noframes' || $token['name'] === 'style'))) {\n            $this->processWithRulesFor($token, self::IN_HEAD);\n        // inverted logic\n        } elseif (\n            ($token['type'] === HTML5_Tokenizer::STARTTAG && (\n                $token['name'] === 'head' || $token['name'] === 'noscript')) ||\n            ($token['type'] === HTML5_Tokenizer::ENDTAG &&\n                $token['name'] !== 'br')) {\n            // parse error\n        } else {\n            // parse error\n            $this->emitToken(array(\n                'type' => HTML5_Tokenizer::ENDTAG,\n                'name' => 'noscript',\n            ));\n            $this->emitToken($token);\n        }\n        break;\n\n    case self::AFTER_HEAD:\n        /* Handle the token as follows: */\n\n        /* A character token that is one of one of U+0009 CHARACTER TABULATION,\n        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),\n        or U+0020 SPACE */\n        if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {\n            /* Append the character to the current node. */\n            $this->insertText($token['data']);\n\n        /* A comment token */\n        } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {\n            /* Append a Comment node to the current node with the data attribute\n            set to the data given in the comment token. */\n            $this->insertComment($token['data']);\n\n        } elseif ($token['type'] === HTML5_Tokenizer::DOCTYPE) {\n            // parse error\n\n        } elseif ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {\n            $this->processWithRulesFor($token, self::IN_BODY);\n\n        /* A start tag token with the tag name \"body\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'body') {\n            $this->insertElement($token);\n\n            /* Set the frameset-ok flag to \"not ok\". */\n            $this->flag_frameset_ok = false;\n\n            /* Change the insertion mode to \"in body\". */\n            $this->mode = self::IN_BODY;\n\n        /* A start tag token with the tag name \"frameset\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'frameset') {\n            /* Insert a frameset element for the token. */\n            $this->insertElement($token);\n\n            /* Change the insertion mode to \"in frameset\". */\n            $this->mode = self::IN_FRAMESET;\n\n        /* A start tag token whose tag name is one of: \"base\", \"link\", \"meta\",\n        \"script\", \"style\", \"title\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],\n        array('base', 'link', 'meta', 'noframes', 'script', 'style', 'title'))) {\n            // parse error\n            /* Push the node pointed to by the head element pointer onto the\n             * stack of open elements. */\n            $this->stack[] = $this->head_pointer;\n            $this->processWithRulesFor($token, self::IN_HEAD);\n            array_splice($this->stack, array_search($this->head_pointer, $this->stack, true), 1);\n\n        // inversion of specification\n        } elseif(\n        ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'head') ||\n        ($token['type'] === HTML5_Tokenizer::ENDTAG &&\n            $token['name'] !== 'body' && $token['name'] !== 'html' &&\n            $token['name'] !== 'br')) {\n            // parse error\n\n        /* Anything else */\n        } else {\n            $this->emitToken(array(\n                'name' => 'body',\n                'type' => HTML5_Tokenizer::STARTTAG,\n                'attr' => array()\n            ));\n            $this->flag_frameset_ok = true;\n            $this->emitToken($token);\n        }\n        break;\n\n    case self::IN_BODY:\n        /* Handle the token as follows: */\n\n        switch($token['type']) {\n            /* A character token */\n            case HTML5_Tokenizer::CHARACTER:\n            case HTML5_Tokenizer::SPACECHARACTER:\n                /* Reconstruct the active formatting elements, if any. */\n                $this->reconstructActiveFormattingElements();\n\n                /* Append the token's character to the current node. */\n                $this->insertText($token['data']);\n\n                /* If the token is not one of U+0009 CHARACTER TABULATION,\n                 * U+000A LINE FEED (LF), U+000C FORM FEED (FF),  or U+0020\n                 * SPACE, then set the frameset-ok flag to \"not ok\". */\n                // i.e., if any of the characters is not whitespace\n                if (strlen($token['data']) !== strspn($token['data'], HTML5_Tokenizer::WHITESPACE)) {\n                    $this->flag_frameset_ok = false;\n                }\n            break;\n\n            /* A comment token */\n            case HTML5_Tokenizer::COMMENT:\n                /* Append a Comment node to the current node with the data\n                attribute set to the data given in the comment token. */\n                $this->insertComment($token['data']);\n            break;\n\n            case HTML5_Tokenizer::DOCTYPE:\n                // parse error\n            break;\n\n            case HTML5_Tokenizer::EOF:\n                // parse error\n            break;\n\n            case HTML5_Tokenizer::STARTTAG:\n            switch($token['name']) {\n                case 'html':\n                    // parse error\n                    /* For each attribute on the token, check to see if the\n                     * attribute is already present on the top element of the\n                     * stack of open elements. If it is not, add the attribute\n                     * and its corresponding value to that element. */\n                    foreach($token['attr'] as $attr) {\n                        if(!$this->stack[0]->hasAttribute($attr['name'])) {\n                            $this->stack[0]->setAttribute($attr['name'], $attr['value']);\n                        }\n                    }\n                break;\n\n                case 'base': case 'command': case 'link': case 'meta': case 'noframes':\n                case 'script': case 'style': case 'title':\n                    /* Process the token as if the insertion mode had been \"in\n                    head\". */\n                    $this->processWithRulesFor($token, self::IN_HEAD);\n                break;\n\n                /* A start tag token with the tag name \"body\" */\n                case 'body':\n                    /* Parse error. If the second element on the stack of open\n                    elements is not a body element, or, if the stack of open\n                    elements has only one node on it, then ignore the token.\n                    (fragment case) */\n                    if(count($this->stack) === 1 || $this->stack[1]->tagName !== 'body') {\n                        $this->ignored = true;\n                        // Ignore\n\n                    /* Otherwise, for each attribute on the token, check to see\n                    if the attribute is already present on the body element (the\n                    second element)    on the stack of open elements. If it is not,\n                    add the attribute and its corresponding value to that\n                    element. */\n                    } else {\n                        foreach($token['attr'] as $attr) {\n                            if(!$this->stack[1]->hasAttribute($attr['name'])) {\n                                $this->stack[1]->setAttribute($attr['name'], $attr['value']);\n                            }\n                        }\n                    }\n                break;\n\n                case 'frameset':\n                    // parse error\n                    /* If the second element on the stack of open elements is\n                     * not a body element, or, if the stack of open elements\n                     * has only one node on it, then ignore the token.\n                     * (fragment case) */\n                    if(count($this->stack) === 1 || $this->stack[1]->tagName !== 'body') {\n                        $this->ignored = true;\n                        // Ignore\n                    } elseif (!$this->flag_frameset_ok) {\n                        $this->ignored = true;\n                        // Ignore\n                    } else {\n                        /* 1. Remove the second element on the stack of open \n                         * elements from its parent node, if it has one.  */\n                        if($this->stack[1]->parentNode) {\n                            $this->stack[1]->parentNode->removeChild($this->stack[1]);\n                        }\n\n                        /* 2. Pop all the nodes from the bottom of the stack of \n                         * open elements, from the current node up to the root \n                         * html element. */\n                        array_splice($this->stack, 1);\n\n                        $this->insertElement($token);\n                        $this->mode = self::IN_FRAMESET;\n                    }\n                break;\n\n                // in spec, there is a diversion here\n\n                case 'address': case 'article': case 'aside': case 'blockquote':\n                case 'center': case 'datagrid': case 'details': case 'dir':\n                case 'div': case 'dl': case 'fieldset': case 'figure': case 'footer':\n                case 'header': case 'hgroup': case 'menu': case 'nav':\n                case 'ol': case 'p': case 'section': case 'ul':\n                    /* If the stack of open elements has a p element in scope,\n                    then act as if an end tag with the tag name p had been\n                    seen. */\n                    if($this->elementInScope('p')) {\n                        $this->emitToken(array(\n                            'name' => 'p',\n                            'type' => HTML5_Tokenizer::ENDTAG\n                        ));\n                    }\n\n                    /* Insert an HTML element for the token. */\n                    $this->insertElement($token);\n                break;\n\n                /* A start tag whose tag name is one of: \"h1\", \"h2\", \"h3\", \"h4\",\n                \"h5\", \"h6\" */\n                case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6':\n                    /* If the stack of open elements has a p  element in scope,\n                    then act as if an end tag with the tag name p had been seen. */\n                    if($this->elementInScope('p')) {\n                        $this->emitToken(array(\n                            'name' => 'p',\n                            'type' => HTML5_Tokenizer::ENDTAG\n                        ));\n                    }\n\n                    /* If the current node is an element whose tag name is one\n                     * of \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", or \"h6\", then this is a\n                     * parse error; pop the current node off the stack of open\n                     * elements. */\n                    $peek = array_pop($this->stack);\n                    if (in_array($peek->tagName, array(\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\"))) {\n                        // parse error\n                    } else {\n                        $this->stack[] = $peek;\n                    }\n\n                    /* Insert an HTML element for the token. */\n                    $this->insertElement($token);\n                break;\n\n                case 'pre': case 'listing':\n                    /* If the stack of open elements has a p  element in scope,\n                    then act as if an end tag with the tag name p had been seen. */\n                    if($this->elementInScope('p')) {\n                        $this->emitToken(array(\n                            'name' => 'p',\n                            'type' => HTML5_Tokenizer::ENDTAG\n                        ));\n                    }\n                    $this->insertElement($token);\n                    /* If the next token is a U+000A LINE FEED (LF) character\n                     * token, then ignore that token and move on to the next\n                     * one. (Newlines at the start of pre blocks are ignored as\n                     * an authoring convenience.) */\n                    $this->ignore_lf_token = 2;\n                    $this->flag_frameset_ok = false;\n                break;\n\n                /* A start tag whose tag name is \"form\" */\n                case 'form':\n                    /* If the form element pointer is not null, ignore the\n                    token with a parse error. */\n                    if($this->form_pointer !== null) {\n                        $this->ignored = true;\n                        // Ignore.\n\n                    /* Otherwise: */\n                    } else {\n                        /* If the stack of open elements has a p element in\n                        scope, then act as if an end tag with the tag name p\n                        had been seen. */\n                        if($this->elementInScope('p')) {\n                            $this->emitToken(array(\n                                'name' => 'p',\n                                'type' => HTML5_Tokenizer::ENDTAG\n                            ));\n                        }\n\n                        /* Insert an HTML element for the token, and set the\n                        form element pointer to point to the element created. */\n                        $element = $this->insertElement($token);\n                        $this->form_pointer = $element;\n                    }\n                break;\n\n                // condensed specification\n                case 'li': case 'dc': case 'dd': case 'ds': case 'dt':\n                    /* 1. Set the frameset-ok flag to \"not ok\". */\n                    $this->flag_frameset_ok = false;\n\n                    $stack_length = count($this->stack) - 1;\n                    for($n = $stack_length; 0 <= $n; $n--) {\n                        /* 2. Initialise node to be the current node (the\n                        bottommost node of the stack). */\n                        $stop = false;\n                        $node = $this->stack[$n];\n                        $cat  = $this->getElementCategory($node);\n\n                        // for case 'li':\n                        /* 3. If node is an li element, then act as if an end\n                         * tag with the tag name \"li\" had been seen, then jump\n                         * to the last step.  */\n                        // for case 'dc': case 'dd': case 'ds': case 'dt':\n                        /* If node is a dc, dd, ds or dt element, then act as if an end\n                         * tag with the same tag name as node had been seen, then\n                         * jump to the last step. */\n                        if(($token['name'] === 'li' && $node->tagName === 'li') ||\n                        ($token['name'] !== 'li' && ($node->tagName == 'dc' || $node->tagName === 'dd' || $node->tagName == 'ds' || $node->tagName === 'dt'))) { // limited conditional\n                            $this->emitToken(array(\n                                'type' => HTML5_Tokenizer::ENDTAG,\n                                'name' => $node->tagName,\n                            ));\n                            break;\n                        }\n\n                        /* 4. If node is not in the formatting category, and is\n                        not    in the phrasing category, and is not an address,\n                        div or p element, then stop this algorithm. */\n                        if($cat !== self::FORMATTING && $cat !== self::PHRASING &&\n                        $node->tagName !== 'address' && $node->tagName !== 'div' &&\n                        $node->tagName !== 'p') {\n                            break;\n                        }\n\n                        /* 5. Otherwise, set node to the previous entry in the\n                         * stack of open elements and return to step 2. */\n                    }\n\n                    /* 6. This is the last step. */\n\n                    /* If the stack of open elements has a p  element in scope,\n                    then act as if an end tag with the tag name p had been\n                    seen. */\n                    if($this->elementInScope('p')) {\n                        $this->emitToken(array(\n                            'name' => 'p',\n                            'type' => HTML5_Tokenizer::ENDTAG\n                        ));\n                    }\n\n                    /* Finally, insert an HTML element with the same tag\n                    name as the    token's. */\n                    $this->insertElement($token);\n                break;\n\n                /* A start tag token whose tag name is \"plaintext\" */\n                case 'plaintext':\n                    /* If the stack of open elements has a p  element in scope,\n                    then act as if an end tag with the tag name p had been\n                    seen. */\n                    if($this->elementInScope('p')) {\n                        $this->emitToken(array(\n                            'name' => 'p',\n                            'type' => HTML5_Tokenizer::ENDTAG\n                        ));\n                    }\n\n                    /* Insert an HTML element for the token. */\n                    $this->insertElement($token);\n\n                    $this->content_model = HTML5_Tokenizer::PLAINTEXT;\n                break;\n\n                // more diversions\n\n                /* A start tag whose tag name is \"a\" */\n                case 'a':\n                    /* If the list of active formatting elements contains\n                    an element whose tag name is \"a\" between the end of the\n                    list and the last marker on the list (or the start of\n                    the list if there is no marker on the list), then this\n                    is a parse error; act as if an end tag with the tag name\n                    \"a\" had been seen, then remove that element from the list\n                    of active formatting elements and the stack of open\n                    elements if the end tag didn't already remove it (it\n                    might not have if the element is not in table scope). */\n                    $leng = count($this->a_formatting);\n\n                    for($n = $leng - 1; $n >= 0; $n--) {\n                        if($this->a_formatting[$n] === self::MARKER) {\n                            break;\n\n                        } elseif($this->a_formatting[$n]->tagName === 'a') {\n                            $a = $this->a_formatting[$n];\n                            $this->emitToken(array(\n                                'name' => 'a',\n                                'type' => HTML5_Tokenizer::ENDTAG\n                            ));\n                            if (in_array($a, $this->a_formatting)) {\n                                $a_i = array_search($a, $this->a_formatting, true);\n                                if($a_i !== false) array_splice($this->a_formatting, $a_i, 1);\n                            }\n                            if (in_array($a, $this->stack)) {\n                                $a_i = array_search($a, $this->stack, true);\n                                if ($a_i !== false) array_splice($this->stack, $a_i, 1);\n                            }\n                            break;\n                        }\n                    }\n\n                    /* Reconstruct the active formatting elements, if any. */\n                    $this->reconstructActiveFormattingElements();\n\n                    /* Insert an HTML element for the token. */\n                    $el = $this->insertElement($token);\n\n                    /* Add that element to the list of active formatting\n                    elements. */\n                    $this->a_formatting[] = $el;\n                break;\n\n                case 'b': case 'big': case 'code': case 'em': case 'font': case 'i':\n                case 's': case 'small': case 'strike':\n                case 'strong': case 'tt': case 'u':\n                    /* Reconstruct the active formatting elements, if any. */\n                    $this->reconstructActiveFormattingElements();\n\n                    /* Insert an HTML element for the token. */\n                    $el = $this->insertElement($token);\n\n                    /* Add that element to the list of active formatting\n                    elements. */\n                    $this->a_formatting[] = $el;\n                break;\n\n                case 'nobr':\n                    /* Reconstruct the active formatting elements, if any. */\n                    $this->reconstructActiveFormattingElements();\n\n                    /* If the stack of open elements has a nobr element in\n                     * scope, then this is a parse error; act as if an end tag\n                     * with the tag name \"nobr\" had been seen, then once again\n                     * reconstruct the active formatting elements, if any. */\n                    if ($this->elementInScope('nobr')) {\n                        $this->emitToken(array(\n                            'name' => 'nobr',\n                            'type' => HTML5_Tokenizer::ENDTAG,\n                        ));\n                        $this->reconstructActiveFormattingElements();\n                    }\n\n                    /* Insert an HTML element for the token. */\n                    $el = $this->insertElement($token);\n\n                    /* Add that element to the list of active formatting\n                    elements. */\n                    $this->a_formatting[] = $el;\n                break;\n\n                // another diversion\n\n                /* A start tag token whose tag name is \"button\" */\n                case 'button':\n                    /* If the stack of open elements has a button element in scope,\n                    then this is a parse error; act as if an end tag with the tag\n                    name \"button\" had been seen, then reprocess the token. (We don't\n                    do that. Unnecessary.) (I hope you're right! -- ezyang) */\n                    if($this->elementInScope('button')) {\n                        $this->emitToken(array(\n                            'name' => 'button',\n                            'type' => HTML5_Tokenizer::ENDTAG\n                        ));\n                    }\n\n                    /* Reconstruct the active formatting elements, if any. */\n                    $this->reconstructActiveFormattingElements();\n\n                    /* Insert an HTML element for the token. */\n                    $this->insertElement($token);\n\n                    /* Insert a marker at the end of the list of active\n                    formatting elements. */\n                    $this->a_formatting[] = self::MARKER;\n\n                    $this->flag_frameset_ok = false;\n                break;\n\n                case 'applet': case 'marquee': case 'object':\n                    /* Reconstruct the active formatting elements, if any. */\n                    $this->reconstructActiveFormattingElements();\n\n                    /* Insert an HTML element for the token. */\n                    $this->insertElement($token);\n\n                    /* Insert a marker at the end of the list of active\n                    formatting elements. */\n                    $this->a_formatting[] = self::MARKER;\n\n                    $this->flag_frameset_ok = false;\n                break;\n\n                // spec diversion\n\n                /* A start tag whose tag name is \"table\" */\n                case 'table':\n                    /* If the Document is not set to quirks mode, and the \n                     * stack of open elements has a p element in scope, then \n                     * act as if an end tag with the tag name \"p\" had been \n                     * seen. */\n                    if($this->quirks_mode !== self::QUIRKS_MODE &&\n                    $this->elementInScope('p')) {\n                        $this->emitToken(array(\n                            'name' => 'p',\n                            'type' => HTML5_Tokenizer::ENDTAG\n                        ));\n                    }\n\n                    /* Insert an HTML element for the token. */\n                    $this->insertElement($token);\n\n                    $this->flag_frameset_ok = false;\n\n                    /* Change the insertion mode to \"in table\". */\n                    $this->mode = self::IN_TABLE;\n                break;\n\n                /* A start tag whose tag name is one of: \"area\", \"basefont\",\n                \"bgsound\", \"br\", \"embed\", \"img\", \"param\", \"spacer\", \"wbr\" */\n                case 'area': case 'basefont': case 'bgsound': case 'br':\n                case 'embed': case 'img': case 'input': case 'keygen': case 'spacer':\n                case 'wbr':\n                    /* Reconstruct the active formatting elements, if any. */\n                    $this->reconstructActiveFormattingElements();\n\n                    /* Insert an HTML element for the token. */\n                    $this->insertElement($token);\n\n                    /* Immediately pop the current node off the stack of open elements. */\n                    array_pop($this->stack);\n\n                    // YYY: Acknowledge the token's self-closing flag, if it is set.\n\n                    $this->flag_frameset_ok = false;\n                break;\n\n                case 'param': case 'source':\n                    /* Insert an HTML element for the token. */\n                    $this->insertElement($token);\n\n                    /* Immediately pop the current node off the stack of open elements. */\n                    array_pop($this->stack);\n\n                    // YYY: Acknowledge the token's self-closing flag, if it is set.\n                break;\n\n                /* A start tag whose tag name is \"hr\" */\n                case 'hr':\n                    /* If the stack of open elements has a p element in scope,\n                    then act as if an end tag with the tag name p had been seen. */\n                    if($this->elementInScope('p')) {\n                        $this->emitToken(array(\n                            'name' => 'p',\n                            'type' => HTML5_Tokenizer::ENDTAG\n                        ));\n                    }\n\n                    /* Insert an HTML element for the token. */\n                    $this->insertElement($token);\n\n                    /* Immediately pop the current node off the stack of open elements. */\n                    array_pop($this->stack);\n\n                    // YYY: Acknowledge the token's self-closing flag, if it is set.\n\n                    $this->flag_frameset_ok = false;\n                break;\n\n                /* A start tag whose tag name is \"image\" */\n                case 'image':\n                    /* Parse error. Change the token's tag name to \"img\" and\n                    reprocess it. (Don't ask.) */\n                    $token['name'] = 'img';\n                    $this->emitToken($token);\n                break;\n\n                /* A start tag whose tag name is \"isindex\" */\n                case 'isindex':\n                    /* Parse error. */\n\n                    /* If the form element pointer is not null,\n                    then ignore the token. */\n                    if($this->form_pointer === null) {\n                        /* Act as if a start tag token with the tag name \"form\" had\n                        been seen. */\n                        /* If the token has an attribute called \"action\", set\n                         * the action attribute on the resulting form\n                         * element to the value of the \"action\" attribute of\n                         * the token. */\n                        $attr = array();\n                        $action = $this->getAttr($token, 'action');\n                        if ($action !== false) {\n                            $attr[] = array('name' => 'action', 'value' => $action);\n                        }\n                        $this->emitToken(array(\n                            'name' => 'form',\n                            'type' => HTML5_Tokenizer::STARTTAG,\n                            'attr' => $attr\n                        ));\n\n                        /* Act as if a start tag token with the tag name \"hr\" had\n                        been seen. */\n                        $this->emitToken(array(\n                            'name' => 'hr',\n                            'type' => HTML5_Tokenizer::STARTTAG,\n                            'attr' => array()\n                        ));\n\n                        /* Act as if a start tag token with the tag name \"label\"\n                        had been seen. */\n                        $this->emitToken(array(\n                            'name' => 'label',\n                            'type' => HTML5_Tokenizer::STARTTAG,\n                            'attr' => array()\n                        ));\n\n                        /* Act as if a stream of character tokens had been seen. */\n                        $prompt = $this->getAttr($token, 'prompt');\n                        if ($prompt === false) {\n                            $prompt = 'This is a searchable index. '.\n                            'Insert your search keywords here: ';\n                        }\n                        $this->emitToken(array(\n                            'data' => $prompt,\n                            'type' => HTML5_Tokenizer::CHARACTER,\n                        ));\n\n                        /* Act as if a start tag token with the tag name \"input\"\n                        had been seen, with all the attributes from the \"isindex\"\n                        token, except with the \"name\" attribute set to the value\n                        \"isindex\" (ignoring any explicit \"name\" attribute). */\n                        $attr = array();\n                        foreach ($token['attr'] as $keypair) {\n                            if ($keypair['name'] === 'name' || $keypair['name'] === 'action' ||\n                                $keypair['name'] === 'prompt') continue;\n                            $attr[] = $keypair;\n                        }\n                        $attr[] = array('name' => 'name', 'value' => 'isindex');\n\n                        $this->emitToken(array(\n                            'name' => 'input',\n                            'type' => HTML5_Tokenizer::STARTTAG,\n                            'attr' => $attr\n                        ));\n\n                        /* Act as if an end tag token with the tag name \"label\"\n                        had been seen. */\n                        $this->emitToken(array(\n                            'name' => 'label',\n                            'type' => HTML5_Tokenizer::ENDTAG\n                        ));\n\n                        /* Act as if a start tag token with the tag name \"hr\" had\n                        been seen. */\n                        $this->emitToken(array(\n                            'name' => 'hr',\n                            'type' => HTML5_Tokenizer::STARTTAG\n                        ));\n\n                        /* Act as if an end tag token with the tag name \"form\" had\n                        been seen. */\n                        $this->emitToken(array(\n                            'name' => 'form',\n                            'type' => HTML5_Tokenizer::ENDTAG\n                        ));\n                    } else {\n                        $this->ignored = true;\n                    }\n                break;\n\n                /* A start tag whose tag name is \"textarea\" */\n                case 'textarea':\n                    $this->insertElement($token);\n\n                    /* If the next token is a U+000A LINE FEED (LF)\n                     * character token, then ignore that token and move on to\n                     * the next one. (Newlines at the start of textarea\n                     * elements are ignored as an authoring convenience.)\n                     * need flag, see also <pre> */\n                    $this->ignore_lf_token = 2;\n\n                    $this->original_mode = $this->mode;\n                    $this->flag_frameset_ok = false;\n                    $this->mode = self::IN_CDATA_RCDATA;\n\n                    /* Switch the tokeniser's content model flag to the\n                    RCDATA state. */\n                    $this->content_model = HTML5_Tokenizer::RCDATA;\n                break;\n\n                /* A start tag token whose tag name is \"xmp\" */\n                case 'xmp':\n                    /* If the stack of open elements has a p element in\n                    scope, then act as if an end tag with the tag name\n                    \"p\" has been seen. */\n                    if ($this->elementInScope('p')) {\n                        $this->emitToken(array(\n                            'name' => 'p',\n                            'type' => HTML5_Tokenizer::ENDTAG\n                        ));\n                    }\n\n                    /* Reconstruct the active formatting elements, if any. */\n                    $this->reconstructActiveFormattingElements();\n\n                    $this->flag_frameset_ok = false;\n\n                    $this->insertCDATAElement($token);\n                break;\n\n                case 'iframe':\n                    $this->flag_frameset_ok = false;\n                    $this->insertCDATAElement($token);\n                break;\n\n                case 'noembed': case 'noscript':\n                    // XSCRIPT: should check scripting flag\n                    $this->insertCDATAElement($token);\n                break;\n\n                /* A start tag whose tag name is \"select\" */\n                case 'select':\n                    /* Reconstruct the active formatting elements, if any. */\n                    $this->reconstructActiveFormattingElements();\n\n                    /* Insert an HTML element for the token. */\n                    $this->insertElement($token);\n\n                    $this->flag_frameset_ok = false;\n\n                    /* If the insertion mode is one of in table\", \"in caption\",\n                     * \"in column group\", \"in table body\", \"in row\", or \"in\n                     * cell\", then switch the insertion mode to \"in select in\n                     * table\". Otherwise, switch the insertion mode  to \"in\n                     * select\". */\n                    if (\n                        $this->mode === self::IN_TABLE || $this->mode === self::IN_CAPTION ||\n                        $this->mode === self::IN_COLUMN_GROUP || $this->mode ==+self::IN_TABLE_BODY ||\n                        $this->mode === self::IN_ROW || $this->mode === self::IN_CELL\n                    ) {\n                        $this->mode = self::IN_SELECT_IN_TABLE;\n                    } else {\n                        $this->mode = self::IN_SELECT;\n                    }\n                break;\n\n                case 'option': case 'optgroup':\n                    if ($this->elementInScope('option')) {\n                        $this->emitToken(array(\n                            'name' => 'option',\n                            'type' => HTML5_Tokenizer::ENDTAG,\n                        ));\n                    }\n                    $this->reconstructActiveFormattingElements();\n                    $this->insertElement($token);\n                break;\n\n                case 'rp': case 'rt':\n                    /* If the stack of open elements has a ruby element in scope, then generate\n                     * implied end tags. If the current node is not then a ruby element, this is\n                     * a parse error; pop all the nodes from the current node up to the node\n                     * immediately before the bottommost ruby element on the stack of open elements.\n                     */\n                    if ($this->elementInScope('ruby')) {\n                        $this->generateImpliedEndTags();\n                    }\n                    $peek = false;\n                    do {\n                        if ($peek) {\n                            // parse error\n                        }\n                        $peek = array_pop($this->stack);\n                    } while ($peek->tagName !== 'ruby');\n                    $this->stack[] = $peek; // we popped one too many\n                    $this->insertElement($token);\n                break;\n\n                // spec diversion\n\n                case 'math':\n                    $this->reconstructActiveFormattingElements();\n                    $token = $this->adjustMathMLAttributes($token);\n                    $token = $this->adjustForeignAttributes($token);\n                    $this->insertForeignElement($token, self::NS_MATHML);\n                    if (isset($token['self-closing'])) {\n                        // XERROR: acknowledge the token's self-closing flag\n                        array_pop($this->stack);\n                    }\n                    if ($this->mode !== self::IN_FOREIGN_CONTENT) {\n                        $this->secondary_mode = $this->mode;\n                        $this->mode = self::IN_FOREIGN_CONTENT;\n                    }\n                break;\n\n                case 'svg':\n                    $this->reconstructActiveFormattingElements();\n                    $token = $this->adjustSVGAttributes($token);\n                    $token = $this->adjustForeignAttributes($token);\n                    $this->insertForeignElement($token, self::NS_SVG);\n                    if (isset($token['self-closing'])) {\n                        // XERROR: acknowledge the token's self-closing flag\n                        array_pop($this->stack);\n                    }\n                    if ($this->mode !== self::IN_FOREIGN_CONTENT) {\n                        $this->secondary_mode = $this->mode;\n                        $this->mode = self::IN_FOREIGN_CONTENT;\n                    }\n                break;\n\n                case 'caption': case 'col': case 'colgroup': case 'frame': case 'head':\n                case 'tbody': case 'td': case 'tfoot': case 'th': case 'thead': case 'tr':\n                    // parse error\n                break;\n\n                /* A start tag token not covered by the previous entries */\n                default:\n                    /* Reconstruct the active formatting elements, if any. */\n                    $this->reconstructActiveFormattingElements();\n\n                    $this->insertElement($token);\n                    /* This element will be a phrasing  element. */\n                break;\n            }\n            break;\n\n            case HTML5_Tokenizer::ENDTAG:\n            switch($token['name']) {\n                /* An end tag with the tag name \"body\" */\n                case 'body':\n                    /* If the stack of open elements does not have a body \n                     * element in scope, this is a parse error; ignore the \n                     * token. */\n                    if(!$this->elementInScope('body')) {\n                        $this->ignored = true;\n\n                    /* Otherwise, if there is a node in the stack of open \n                     * elements that is not either a dc element, a dd element, \n                     * a ds element, a dt element, an li element, an optgroup \n                     * element, an option element, a p element, an rp element, \n                     * an rt element, a tbody element, a td element, a tfoot \n                     * element, a th element, a thead element, a tr element, \n                     * the body element, or the html element, then this is a \n                     * parse error.\n                     */\n                    } else {\n                        // XERROR: implement this check for parse error\n                    }\n\n                    /* Change the insertion mode to \"after body\". */\n                    $this->mode = self::AFTER_BODY;\n                break;\n\n                /* An end tag with the tag name \"html\" */\n                case 'html':\n                    /* Act as if an end tag with tag name \"body\" had been seen,\n                    then, if that token wasn't ignored, reprocess the current\n                    token. */\n                    $this->emitToken(array(\n                        'name' => 'body',\n                        'type' => HTML5_Tokenizer::ENDTAG\n                    ));\n\n                    if (!$this->ignored) $this->emitToken($token);\n                break;\n\n                case 'address': case 'article': case 'aside': case 'blockquote':\n                case 'center': case 'datagrid': case 'details': case 'dir':\n                case 'div': case 'dl': case 'fieldset': case 'footer':\n                case 'header': case 'hgroup': case 'listing': case 'menu':\n                case 'nav': case 'ol': case 'pre': case 'section': case 'ul':\n                    /* If the stack of open elements has an element in scope\n                    with the same tag name as that of the token, then generate\n                    implied end tags. */\n                    if($this->elementInScope($token['name'])) {\n                        $this->generateImpliedEndTags();\n\n                        /* Now, if the current node is not an element with\n                        the same tag name as that of the token, then this\n                        is a parse error. */\n                        // XERROR: implement parse error logic\n\n                        /* If the stack of open elements has an element in\n                        scope with the same tag name as that of the token,\n                        then pop elements from this stack until an element\n                        with that tag name has been popped from the stack. */\n                        do {\n                            $node = array_pop($this->stack);\n                        } while ($node->tagName !== $token['name']);\n                    } else {\n                        // parse error\n                    }\n                break;\n\n                /* An end tag whose tag name is \"form\" */\n                case 'form':\n                    /* Let node be the element that the form element pointer is set to. */\n                    $node = $this->form_pointer;\n                    /* Set the form element pointer  to null. */\n                    $this->form_pointer = null;\n                    /* If node is null or the stack of open elements does not \n                        * have node in scope, then this is a parse error; ignore the token. */\n                    if ($node === null || !in_array($node, $this->stack)) {\n                        // parse error\n                        $this->ignored = true;\n                    } else {\n                        /* 1. Generate implied end tags. */\n                        $this->generateImpliedEndTags();\n                        /* 2. If the current node is not node, then this is a parse error.  */\n                        if (end($this->stack) !== $node) {\n                            // parse error\n                        }\n                        /* 3. Remove node from the stack of open elements. */\n                        array_splice($this->stack, array_search($node, $this->stack, true), 1);\n                    }\n\n                break;\n\n                /* An end tag whose tag name is \"p\" */\n                case 'p':\n                    /* If the stack of open elements has a p element in scope,\n                    then generate implied end tags, except for p elements. */\n                    if($this->elementInScope('p')) {\n                        /* Generate implied end tags, except for elements with\n                         * the same tag name as the token. */\n                        $this->generateImpliedEndTags(array('p'));\n\n                        /* If the current node is not a p element, then this is\n                        a parse error. */\n                        // XERROR: implement\n\n                        /* Pop elements from the stack of open elements  until\n                         * an element with the same tag name as the token has\n                         * been popped from the stack. */\n                        do {\n                            $node = array_pop($this->stack);\n                        } while ($node->tagName !== 'p');\n\n                    } else {\n                        // parse error\n                        $this->emitToken(array(\n                            'name' => 'p',\n                            'type' => HTML5_Tokenizer::STARTTAG,\n                        ));\n                        $this->emitToken($token);\n                    }\n                break;\n\n                /* An end tag whose tag name is \"li\" */\n                case 'li':\n                    /* If the stack of open elements does not have an element\n                     * in list item scope with the same tag name as that of the\n                     * token, then this is a parse error; ignore the token. */\n                    if ($this->elementInScope($token['name'], self::SCOPE_LISTITEM)) {\n                        /* Generate implied end tags, except for elements with the\n                         * same tag name as the token. */\n                        $this->generateImpliedEndTags(array($token['name']));\n                        /* If the current node is not an element with the same tag\n                         * name as that of the token, then this is a parse error. */\n                        // XERROR: parse error\n                        /* Pop elements from the stack of open elements  until an\n                         * element with the same tag name as the token has been\n                         * popped from the stack. */\n                        do {\n                            $node = array_pop($this->stack);\n                        } while ($node->tagName !== $token['name']);\n                    } else {\n                        // XERROR: parse error\n                    }\n                break;\n\n                /* An end tag whose tag name is \"dc\", \"dd\", \"ds\", \"dt\" */\n                case 'dc': case 'dd': case 'ds': case 'dt':\n                    if($this->elementInScope($token['name'])) {\n                        $this->generateImpliedEndTags(array($token['name']));\n\n                        /* If the current node is not an element with the same\n                        tag name as the token, then this is a parse error. */\n                        // XERROR: implement parse error\n\n                        /* Pop elements from the stack of open elements  until\n                         * an element with the same tag name as the token has\n                         * been popped from the stack. */\n                        do {\n                            $node = array_pop($this->stack);\n                        } while ($node->tagName !== $token['name']);\n\n                    } else {\n                        // XERROR: parse error\n                    }\n                break;\n\n                /* An end tag whose tag name is one of: \"h1\", \"h2\", \"h3\", \"h4\",\n                \"h5\", \"h6\" */\n                case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6':\n                    $elements = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6');\n\n                    /* If the stack of open elements has in scope an element whose\n                    tag name is one of \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", or \"h6\", then\n                    generate implied end tags. */\n                    if($this->elementInScope($elements)) {\n                        $this->generateImpliedEndTags();\n\n                        /* Now, if the current node is not an element with the same\n                        tag name as that of the token, then this is a parse error. */\n                        // XERROR: implement parse error\n\n                        /* If the stack of open elements has in scope an element\n                        whose tag name is one of \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", or\n                        \"h6\", then pop elements from the stack until an element\n                        with one of those tag names has been popped from the stack. */\n                        do {\n                            $node = array_pop($this->stack);\n                        } while (!in_array($node->tagName, $elements));\n                    } else {\n                        // parse error\n                    }\n                break;\n\n                /* An end tag whose tag name is one of: \"a\", \"b\", \"big\", \"em\",\n                \"font\", \"i\", \"nobr\", \"s\", \"small\", \"strike\", \"strong\", \"tt\", \"u\" */\n                case 'a': case 'b': case 'big': case 'code': case 'em': case 'font':\n                case 'i': case 'nobr': case 's': case 'small': case 'strike':\n                case 'strong': case 'tt': case 'u':\n                    // XERROR: generally speaking this needs parse error logic\n                    /* 1. Let the formatting element be the last element in\n                    the list of active formatting elements that:\n                        * is between the end of the list and the last scope\n                        marker in the list, if any, or the start of the list\n                        otherwise, and\n                        * has the same tag name as the token.\n                    */\n                    while(true) {\n                        for($a = count($this->a_formatting) - 1; $a >= 0; $a--) {\n                            if($this->a_formatting[$a] === self::MARKER) {\n                                break;\n\n                            } elseif($this->a_formatting[$a]->tagName === $token['name']) {\n                                $formatting_element = $this->a_formatting[$a];\n                                $in_stack = in_array($formatting_element, $this->stack, true);\n                                $fe_af_pos = $a;\n                                break;\n                            }\n                        }\n\n                        /* If there is no such node, or, if that node is\n                        also in the stack of open elements but the element\n                        is not in scope, then this is a parse error. Abort\n                        these steps. The token is ignored. */\n                        if(!isset($formatting_element) || ($in_stack &&\n                        !$this->elementInScope($token['name']))) {\n                            $this->ignored = true;\n                            break;\n\n                        /* Otherwise, if there is such a node, but that node\n                        is not in the stack of open elements, then this is a\n                        parse error; remove the element from the list, and\n                        abort these steps. */\n                        } elseif(isset($formatting_element) && !$in_stack) {\n                            unset($this->a_formatting[$fe_af_pos]);\n                            $this->a_formatting = array_merge($this->a_formatting);\n                            break;\n                        }\n\n                        /* Otherwise, there is a formatting element and that\n                         * element is in the stack and is in scope. If the\n                         * element is not the current node, this is a parse\n                         * error. In any case, proceed with the algorithm as\n                         * written in the following steps. */\n                        // XERROR: implement me\n\n                        /* 2. Let the furthest block be the topmost node in the\n                        stack of open elements that is lower in the stack\n                        than the formatting element, and is not an element in\n                        the phrasing or formatting categories. There might\n                        not be one. */\n                        $fe_s_pos = array_search($formatting_element, $this->stack, true);\n                        $length = count($this->stack);\n\n                        for($s = $fe_s_pos + 1; $s < $length; $s++) {\n                            $category = $this->getElementCategory($this->stack[$s]);\n\n                            if($category !== self::PHRASING && $category !== self::FORMATTING) {\n                                $furthest_block = $this->stack[$s];\n                                break;\n                            }\n                        }\n\n                        /* 3. If there is no furthest block, then the UA must\n                        skip the subsequent steps and instead just pop all\n                        the nodes from the bottom of the stack of open\n                        elements, from the current node up to the formatting\n                        element, and remove the formatting element from the\n                        list of active formatting elements. */\n                        if(!isset($furthest_block)) {\n                            for($n = $length - 1; $n >= $fe_s_pos; $n--) {\n                                array_pop($this->stack);\n                            }\n\n                            unset($this->a_formatting[$fe_af_pos]);\n                            $this->a_formatting = array_merge($this->a_formatting);\n                            break;\n                        }\n\n                        /* 4. Let the common ancestor be the element\n                        immediately above the formatting element in the stack\n                        of open elements. */\n                        $common_ancestor = $this->stack[$fe_s_pos - 1];\n\n                        /* 5. Let a bookmark note the position of the\n                        formatting element in the list of active formatting\n                        elements relative to the elements on either side\n                        of it in the list. */\n                        $bookmark = $fe_af_pos;\n\n                        /* 6. Let node and last node  be the furthest block.\n                        Follow these steps: */\n                        $node = $furthest_block;\n                        $last_node = $furthest_block;\n\n                        while(true) {\n                            for($n = array_search($node, $this->stack, true) - 1; $n >= 0; $n--) {\n                                /* 6.1 Let node be the element immediately\n                                prior to node in the stack of open elements. */\n                                $node = $this->stack[$n];\n\n                                /* 6.2 If node is not in the list of active\n                                formatting elements, then remove node from\n                                the stack of open elements and then go back\n                                to step 1. */\n                                if(!in_array($node, $this->a_formatting, true)) {\n                                    array_splice($this->stack, $n, 1);\n\n                                } else {\n                                    break;\n                                }\n                            }\n\n                            /* 6.3 Otherwise, if node is the formatting\n                            element, then go to the next step in the overall\n                            algorithm. */\n                            if($node === $formatting_element) {\n                                break;\n\n                            /* 6.4 Otherwise, if last node is the furthest\n                            block, then move the aforementioned bookmark to\n                            be immediately after the node in the list of\n                            active formatting elements. */\n                            } elseif($last_node === $furthest_block) {\n                                $bookmark = array_search($node, $this->a_formatting, true) + 1;\n                            }\n\n                            /* 6.5 Create an element for the token for which\n                             * the element node was created, replace the entry\n                             * for node in the list of active formatting\n                             * elements with an entry for the new element,\n                             * replace the entry for node in the stack of open\n                             * elements with an entry for the new element, and\n                             * let node be the new element. */\n                            // we don't know what the token is anymore\n                            // XDOM\n                            $clone = $node->cloneNode();\n                            $a_pos = array_search($node, $this->a_formatting, true);\n                            $s_pos = array_search($node, $this->stack, true);\n                            $this->a_formatting[$a_pos] = $clone;\n                            $this->stack[$s_pos] = $clone;\n                            $node = $clone;\n\n                            /* 6.6 Insert last node into node, first removing\n                            it from its previous parent node if any. */\n                            // XDOM\n                            if($last_node->parentNode !== null) {\n                                $last_node->parentNode->removeChild($last_node);\n                            }\n\n                            // XDOM\n                            $node->appendChild($last_node);\n\n                            /* 6.7 Let last node be node. */\n                            $last_node = $node;\n\n                            /* 6.8 Return to step 1 of this inner set of steps. */\n                        }\n\n                        /* 7. If the common ancestor node is a table, tbody,\n                         * tfoot, thead, or tr element, then, foster parent\n                         * whatever last node ended up being in the previous\n                         * step, first removing it from its previous parent\n                         * node if any. */\n                        // XDOM\n                        if ($last_node->parentNode) { // common step\n                            $last_node->parentNode->removeChild($last_node);\n                        }\n                        if (in_array($common_ancestor->tagName, array('table', 'tbody', 'tfoot', 'thead', 'tr'))) {\n                            $this->fosterParent($last_node);\n                        /* Otherwise, append whatever last node  ended up being\n                         * in the previous step to the common ancestor node,\n                         * first removing it from its previous parent node if\n                         * any. */\n                        } else {\n                            // XDOM\n                            $common_ancestor->appendChild($last_node);\n                        }\n\n                        /* 8. Create an element for the token for which the\n                         * formatting element was created. */\n                        // XDOM\n                        $clone = $formatting_element->cloneNode();\n\n                        /* 9. Take all of the child nodes of the furthest\n                        block and append them to the element created in the\n                        last step. */\n                        // XDOM\n                        while($furthest_block->hasChildNodes()) {\n                            $child = $furthest_block->firstChild;\n                            $furthest_block->removeChild($child);\n                            $clone->appendChild($child);\n                        }\n\n                        /* 10. Append that clone to the furthest block. */\n                        // XDOM\n                        $furthest_block->appendChild($clone);\n\n                        /* 11. Remove the formatting element from the list\n                        of active formatting elements, and insert the new element\n                        into the list of active formatting elements at the\n                        position of the aforementioned bookmark. */\n                        $fe_af_pos = array_search($formatting_element, $this->a_formatting, true);\n                        array_splice($this->a_formatting, $fe_af_pos, 1);\n\n                        $af_part1 = array_slice($this->a_formatting, 0, $bookmark - 1);\n                        $af_part2 = array_slice($this->a_formatting, $bookmark);\n                        $this->a_formatting = array_merge($af_part1, array($clone), $af_part2);\n\n                        /* 12. Remove the formatting element from the stack\n                        of open elements, and insert the new element into the stack\n                        of open elements immediately below the position of the\n                        furthest block in that stack. */\n                        $fe_s_pos = array_search($formatting_element, $this->stack, true);\n                        array_splice($this->stack, $fe_s_pos, 1);\n\n                        $fb_s_pos = array_search($furthest_block, $this->stack, true);\n                        $s_part1 = array_slice($this->stack, 0, $fb_s_pos + 1);\n                        $s_part2 = array_slice($this->stack, $fb_s_pos + 1);\n                        $this->stack = array_merge($s_part1, array($clone), $s_part2);\n\n                        /* 13. Jump back to step 1 in this series of steps. */\n                        unset($formatting_element, $fe_af_pos, $fe_s_pos, $furthest_block);\n                    }\n                break;\n\n                case 'applet': case 'button': case 'marquee': case 'object':\n                    /* If the stack of open elements has an element in scope whose\n                    tag name matches the tag name of the token, then generate implied\n                    tags. */\n                    if($this->elementInScope($token['name'])) {\n                        $this->generateImpliedEndTags();\n\n                        /* Now, if the current node is not an element with the same\n                        tag name as the token, then this is a parse error. */\n                        // XERROR: implement logic\n\n                        /* Pop elements from the stack of open elements  until\n                         * an element with the same tag name as the token has\n                         * been popped from the stack. */\n                        do {\n                            $node = array_pop($this->stack);\n                        } while ($node->tagName !== $token['name']);\n\n                        /* Clear the list of active formatting elements up to the\n                         * last marker. */\n                        $keys = array_keys($this->a_formatting, self::MARKER, true);\n                        $marker = end($keys);\n\n                        for($n = count($this->a_formatting) - 1; $n > $marker; $n--) {\n                            array_pop($this->a_formatting);\n                        }\n                    } else {\n                        // parse error\n                    }\n                break;\n\n                case 'br':\n                    // Parse error\n                    $this->emitToken(array(\n                        'name' => 'br',\n                        'type' => HTML5_Tokenizer::STARTTAG,\n                    ));\n                break;\n\n                /* An end tag token not covered by the previous entries */\n                default:\n                    for($n = count($this->stack) - 1; $n >= 0; $n--) {\n                        /* Initialise node to be the current node (the bottommost\n                        node of the stack). */\n                        $node = $this->stack[$n];\n\n                        /* If node has the same tag name as the end tag token,\n                        then: */\n                        if($token['name'] === $node->tagName) {\n                            /* Generate implied end tags. */\n                            $this->generateImpliedEndTags();\n\n                            /* If the tag name of the end tag token does not\n                            match the tag name of the current node, this is a\n                            parse error. */\n                            // XERROR: implement this\n\n                            /* Pop all the nodes from the current node up to\n                            node, including node, then stop these steps. */\n                            // XSKETCHY\n                            do {\n                                $pop = array_pop($this->stack);\n                            } while ($pop !== $node);\n                            break;\n\n                        } else {\n                            $category = $this->getElementCategory($node);\n\n                            if($category !== self::FORMATTING && $category !== self::PHRASING) {\n                                /* Otherwise, if node is in neither the formatting\n                                category nor the phrasing category, then this is a\n                                parse error. Stop this algorithm. The end tag token\n                                is ignored. */\n                                $this->ignored = true;\n                                break;\n                                // parse error\n                            }\n                        }\n                        /* Set node to the previous entry in the stack of open elements. Loop. */\n                    }\n                break;\n            }\n            break;\n        }\n        break;\n\n    case self::IN_CDATA_RCDATA:\n        if (\n            $token['type'] === HTML5_Tokenizer::CHARACTER ||\n            $token['type'] === HTML5_Tokenizer::SPACECHARACTER\n        ) {\n            $this->insertText($token['data']);\n        } elseif ($token['type'] === HTML5_Tokenizer::EOF) {\n            // parse error\n            /* If the current node is a script  element, mark the script\n             * element as \"already executed\". */\n            // probably not necessary\n            array_pop($this->stack);\n            $this->mode = $this->original_mode;\n            $this->emitToken($token);\n        } elseif ($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'script') {\n            array_pop($this->stack);\n            $this->mode = $this->original_mode;\n            // we're ignoring all of the execution stuff\n        } elseif ($token['type'] === HTML5_Tokenizer::ENDTAG) {\n            array_pop($this->stack);\n            $this->mode = $this->original_mode;\n        }\n    break;\n\n    case self::IN_TABLE:\n        $clear = array('html', 'table');\n\n        /* A character token */\n        if ($token['type'] === HTML5_Tokenizer::CHARACTER ||\n            $token['type'] === HTML5_Tokenizer::SPACECHARACTER) {\n            /* Let the pending table character tokens\n             * be an empty list of tokens. */\n            $this->pendingTableCharacters = \"\";\n            $this->pendingTableCharactersDirty = false;\n            /* Let the original insertion mode be the current\n             * insertion mode. */\n            $this->original_mode = $this->mode;\n            /* Switch the insertion mode to\n             * \"in table text\" and\n             * reprocess the token. */\n            $this->mode = self::IN_TABLE_TEXT;\n            $this->emitToken($token);\n\n        /* A comment token */\n        } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {\n            /* Append a Comment node to the current node with the data\n            attribute set to the data given in the comment token. */\n            $this->insertComment($token['data']);\n\n        } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {\n            // parse error\n\n        /* A start tag whose tag name is \"caption\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        $token['name'] === 'caption') {\n            /* Clear the stack back to a table context. */\n            $this->clearStackToTableContext($clear);\n\n            /* Insert a marker at the end of the list of active\n            formatting elements. */\n            $this->a_formatting[] = self::MARKER;\n\n            /* Insert an HTML element for the token, then switch the\n            insertion mode to \"in caption\". */\n            $this->insertElement($token);\n            $this->mode = self::IN_CAPTION;\n\n        /* A start tag whose tag name is \"colgroup\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        $token['name'] === 'colgroup') {\n            /* Clear the stack back to a table context. */\n            $this->clearStackToTableContext($clear);\n\n            /* Insert an HTML element for the token, then switch the\n            insertion mode to \"in column group\". */\n            $this->insertElement($token);\n            $this->mode = self::IN_COLUMN_GROUP;\n\n        /* A start tag whose tag name is \"col\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        $token['name'] === 'col') {\n            $this->emitToken(array(\n                'name' => 'colgroup',\n                'type' => HTML5_Tokenizer::STARTTAG,\n                'attr' => array()\n            ));\n\n            $this->emitToken($token);\n\n        /* A start tag whose tag name is one of: \"tbody\", \"tfoot\", \"thead\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],\n        array('tbody', 'tfoot', 'thead'))) {\n            /* Clear the stack back to a table context. */\n            $this->clearStackToTableContext($clear);\n\n            /* Insert an HTML element for the token, then switch the insertion\n            mode to \"in table body\". */\n            $this->insertElement($token);\n            $this->mode = self::IN_TABLE_BODY;\n\n        /* A start tag whose tag name is one of: \"td\", \"th\", \"tr\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        in_array($token['name'], array('td', 'th', 'tr'))) {\n            /* Act as if a start tag token with the tag name \"tbody\" had been\n            seen, then reprocess the current token. */\n            $this->emitToken(array(\n                'name' => 'tbody',\n                'type' => HTML5_Tokenizer::STARTTAG,\n                'attr' => array()\n            ));\n\n            $this->emitToken($token);\n\n        /* A start tag whose tag name is \"table\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        $token['name'] === 'table') {\n            /* Parse error. Act as if an end tag token with the tag name \"table\"\n            had been seen, then, if that token wasn't ignored, reprocess the\n            current token. */\n            $this->emitToken(array(\n                'name' => 'table',\n                'type' => HTML5_Tokenizer::ENDTAG\n            ));\n\n            if (!$this->ignored) $this->emitToken($token);\n\n        /* An end tag whose tag name is \"table\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&\n        $token['name'] === 'table') {\n            /* If the stack of open elements does not have an element in table\n            scope with the same tag name as the token, this is a parse error.\n            Ignore the token. (fragment case) */\n            if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {\n                $this->ignored = true;\n\n            /* Otherwise: */\n            } else {\n                do {\n                    $node = array_pop($this->stack);\n                } while ($node->tagName !== 'table');\n\n                /* Reset the insertion mode appropriately. */\n                $this->resetInsertionMode();\n            }\n\n        /* An end tag whose tag name is one of: \"body\", \"caption\", \"col\",\n        \"colgroup\", \"html\", \"tbody\", \"td\", \"tfoot\", \"th\", \"thead\", \"tr\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],\n        array('body', 'caption', 'col', 'colgroup', 'html', 'tbody', 'td',\n        'tfoot', 'th', 'thead', 'tr'))) {\n            // Parse error. Ignore the token.\n\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        ($token['name'] === 'style' || $token['name'] === 'script')) {\n            $this->processWithRulesFor($token, self::IN_HEAD);\n\n        } elseif ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'input' &&\n        // assignment is intentional\n        /* If the token does not have an attribute with the name \"type\", or\n         * if it does, but that attribute's value is not an ASCII\n         * case-insensitive match for the string \"hidden\", then: act as\n         * described in the \"anything else\" entry below. */\n        ($type = $this->getAttr($token, 'type')) && strtolower($type) === 'hidden') {\n            // I.e., if its an input with the type attribute == 'hidden'\n            /* Otherwise */\n            // parse error\n            $this->insertElement($token);\n            array_pop($this->stack);\n        } elseif ($token['type'] === HTML5_Tokenizer::EOF) {\n            /* If the current node is not the root html element, then this is a parse error. */\n            if (end($this->stack)->tagName !== 'html') {\n                // Note: It can only be the current node in the fragment case.\n                // parse error\n            }\n            /* Stop parsing. */\n        /* Anything else */\n        } else {\n            /* Parse error. Process the token as if the insertion mode was \"in\n            body\", with the following exception: */\n\n            $old = $this->foster_parent;\n            $this->foster_parent = true;\n            $this->processWithRulesFor($token, self::IN_BODY);\n            $this->foster_parent = $old;\n        }\n    break;\n\n    case self::IN_TABLE_TEXT:\n        /* A character token */\n        if($token['type'] === HTML5_Tokenizer::CHARACTER) {\n            /* Append the character token to the pending table\n             * character tokens list. */\n            $this->pendingTableCharacters .= $token['data'];\n            $this->pendingTableCharactersDirty = true;\n        } elseif ($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {\n            $this->pendingTableCharacters .= $token['data'];\n        /* Anything else */\n        } else {\n            if ($this->pendingTableCharacters !== '' && is_string($this->pendingTableCharacters)) {\n                /* If any of the tokens in the pending table character tokens list \n                 * are character tokens that are not one of U+0009 CHARACTER \n                 * TABULATION, U+000A LINE FEED (LF), U+000C FORM FEED (FF), or \n                 * U+0020 SPACE, then reprocess those character tokens using the \n                 * rules given in the \"anything else\" entry in the in table\" \n                 * insertion mode.*/\n                if ($this->pendingTableCharactersDirty) {\n                    /* Parse error. Process the token using the rules for the \n                     * \"in body\" insertion mode, except that if the current \n                     * node is a table, tbody, tfoot, thead, or tr element, \n                     * then, whenever a node would be inserted into the current \n                     * node, it must instead be foster parented. */\n                    // XERROR\n                    $old = $this->foster_parent;\n                    $this->foster_parent = true;\n                    $text_token = array(\n                        'type' => HTML5_Tokenizer::CHARACTER,\n                        'data' => $this->pendingTableCharacters,\n                    );\n                    $this->processWithRulesFor($text_token, self::IN_BODY);\n                    $this->foster_parent = $old;\n\n                /* Otherwise, insert the characters given by the pending table \n                 * character tokens list into the current node. */\n                } else {\n                    $this->insertText($this->pendingTableCharacters);\n                }\n                $this->pendingTableCharacters = null;\n                $this->pendingTableCharactersNull = null;\n            }\n\n            /* Switch the insertion mode to the original insertion mode and \n             * reprocess the token.\n             */\n            $this->mode = $this->original_mode;\n            $this->emitToken($token);\n        }\n    break;\n\n    case self::IN_CAPTION:\n        /* An end tag whose tag name is \"caption\" */\n        if($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'caption') {\n            /* If the stack of open elements does not have an element in table\n            scope with the same tag name as the token, this is a parse error.\n            Ignore the token. (fragment case) */\n            if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {\n                $this->ignored = true;\n                // Ignore\n\n            /* Otherwise: */\n            } else {\n                /* Generate implied end tags. */\n                $this->generateImpliedEndTags();\n\n                /* Now, if the current node is not a caption element, then this\n                is a parse error. */\n                // XERROR: implement\n\n                /* Pop elements from this stack until a caption element has\n                been popped from the stack. */\n                do {\n                    $node = array_pop($this->stack);\n                } while ($node->tagName !== 'caption');\n\n                /* Clear the list of active formatting elements up to the last\n                marker. */\n                $this->clearTheActiveFormattingElementsUpToTheLastMarker();\n\n                /* Switch the insertion mode to \"in table\". */\n                $this->mode = self::IN_TABLE;\n            }\n\n        /* A start tag whose tag name is one of: \"caption\", \"col\", \"colgroup\",\n        \"tbody\", \"td\", \"tfoot\", \"th\", \"thead\", \"tr\", or an end tag whose tag\n        name is \"table\" */\n        } elseif(($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],\n        array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th',\n        'thead', 'tr'))) || ($token['type'] === HTML5_Tokenizer::ENDTAG &&\n        $token['name'] === 'table')) {\n            /* Parse error. Act as if an end tag with the tag name \"caption\"\n            had been seen, then, if that token wasn't ignored, reprocess the\n            current token. */\n            $this->emitToken(array(\n                'name' => 'caption',\n                'type' => HTML5_Tokenizer::ENDTAG\n            ));\n\n            if (!$this->ignored) $this->emitToken($token);\n\n        /* An end tag whose tag name is one of: \"body\", \"col\", \"colgroup\",\n        \"html\", \"tbody\", \"td\", \"tfoot\", \"th\", \"thead\", \"tr\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],\n        array('body', 'col', 'colgroup', 'html', 'tbody', 'tfoot', 'th',\n        'thead', 'tr'))) {\n            // Parse error. Ignore the token.\n            $this->ignored = true;\n\n        /* Anything else */\n        } else {\n            /* Process the token as if the insertion mode was \"in body\". */\n            $this->processWithRulesFor($token, self::IN_BODY);\n        }\n    break;\n\n    case self::IN_COLUMN_GROUP:\n        /* A character token that is one of one of U+0009 CHARACTER TABULATION,\n        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),\n        or U+0020 SPACE */\n        if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {\n            /* Append the character to the current node. */\n            $this->insertText($token['data']);\n\n        /* A comment token */\n        } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {\n            /* Append a Comment node to the current node with the data\n            attribute set to the data given in the comment token. */\n            $this->insertToken($token['data']);\n\n        } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {\n            // parse error\n\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {\n            $this->processWithRulesFor($token, self::IN_BODY);\n\n        /* A start tag whose tag name is \"col\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'col') {\n            /* Insert a col element for the token. Immediately pop the current\n            node off the stack of open elements. */\n            $this->insertElement($token);\n            array_pop($this->stack);\n            // XERROR: Acknowledge the token's self-closing flag, if it is set.\n\n        /* An end tag whose tag name is \"colgroup\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&\n        $token['name'] === 'colgroup') {\n            /* If the current node is the root html element, then this is a\n            parse error, ignore the token. (fragment case) */\n            if(end($this->stack)->tagName === 'html') {\n                $this->ignored = true;\n\n            /* Otherwise, pop the current node (which will be a colgroup\n            element) from the stack of open elements. Switch the insertion\n            mode to \"in table\". */\n            } else {\n                array_pop($this->stack);\n                $this->mode = self::IN_TABLE;\n            }\n\n        /* An end tag whose tag name is \"col\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'col') {\n            /* Parse error. Ignore the token. */\n            $this->ignored = true;\n\n        /* An end-of-file token */\n        /* If the current node is the root html  element */\n        } elseif($token['type'] === HTML5_Tokenizer::EOF && end($this->stack)->tagName === 'html') {\n            /* Stop parsing */\n\n        /* Anything else */\n        } else {\n            /* Act as if an end tag with the tag name \"colgroup\" had been seen,\n            and then, if that token wasn't ignored, reprocess the current token. */\n            $this->emitToken(array(\n                'name' => 'colgroup',\n                'type' => HTML5_Tokenizer::ENDTAG\n            ));\n\n            if (!$this->ignored) $this->emitToken($token);\n        }\n    break;\n\n    case self::IN_TABLE_BODY:\n        $clear = array('tbody', 'tfoot', 'thead', 'html');\n\n        /* A start tag whose tag name is \"tr\" */\n        if($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'tr') {\n            /* Clear the stack back to a table body context. */\n            $this->clearStackToTableContext($clear);\n\n            /* Insert a tr element for the token, then switch the insertion\n            mode to \"in row\". */\n            $this->insertElement($token);\n            $this->mode = self::IN_ROW;\n\n        /* A start tag whose tag name is one of: \"th\", \"td\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        ($token['name'] === 'th' ||    $token['name'] === 'td')) {\n            /* Parse error. Act as if a start tag with the tag name \"tr\" had\n            been seen, then reprocess the current token. */\n            $this->emitToken(array(\n                'name' => 'tr',\n                'type' => HTML5_Tokenizer::STARTTAG,\n                'attr' => array()\n            ));\n\n            $this->emitToken($token);\n\n        /* An end tag whose tag name is one of: \"tbody\", \"tfoot\", \"thead\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&\n        in_array($token['name'], array('tbody', 'tfoot', 'thead'))) {\n            /* If the stack of open elements does not have an element in table\n            scope with the same tag name as the token, this is a parse error.\n            Ignore the token. */\n            if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {\n                // Parse error\n                $this->ignored = true;\n\n            /* Otherwise: */\n            } else {\n                /* Clear the stack back to a table body context. */\n                $this->clearStackToTableContext($clear);\n\n                /* Pop the current node from the stack of open elements. Switch\n                the insertion mode to \"in table\". */\n                array_pop($this->stack);\n                $this->mode = self::IN_TABLE;\n            }\n\n        /* A start tag whose tag name is one of: \"caption\", \"col\", \"colgroup\",\n        \"tbody\", \"tfoot\", \"thead\", or an end tag whose tag name is \"table\" */\n        } elseif(($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],\n        array('caption', 'col', 'colgroup', 'tbody', 'tfoot', 'thead'))) ||\n        ($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'table')) {\n            /* If the stack of open elements does not have a tbody, thead, or\n            tfoot element in table scope, this is a parse error. Ignore the\n            token. (fragment case) */\n            if(!$this->elementInScope(array('tbody', 'thead', 'tfoot'), self::SCOPE_TABLE)) {\n                // parse error\n                $this->ignored = true;\n\n            /* Otherwise: */\n            } else {\n                /* Clear the stack back to a table body context. */\n                $this->clearStackToTableContext($clear);\n\n                /* Act as if an end tag with the same tag name as the current\n                node (\"tbody\", \"tfoot\", or \"thead\") had been seen, then\n                reprocess the current token. */\n                $this->emitToken(array(\n                    'name' => end($this->stack)->tagName,\n                    'type' => HTML5_Tokenizer::ENDTAG\n                ));\n\n                $this->emitToken($token);\n            }\n\n        /* An end tag whose tag name is one of: \"body\", \"caption\", \"col\",\n        \"colgroup\", \"html\", \"td\", \"th\", \"tr\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],\n        array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th', 'tr'))) {\n            /* Parse error. Ignore the token. */\n            $this->ignored = true;\n\n        /* Anything else */\n        } else {\n            /* Process the token as if the insertion mode was \"in table\". */\n            $this->processWithRulesFor($token, self::IN_TABLE);\n        }\n    break;\n\n    case self::IN_ROW:\n        $clear = array('tr', 'html');\n\n        /* A start tag whose tag name is one of: \"th\", \"td\" */\n        if($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        ($token['name'] === 'th' || $token['name'] === 'td')) {\n            /* Clear the stack back to a table row context. */\n            $this->clearStackToTableContext($clear);\n\n            /* Insert an HTML element for the token, then switch the insertion\n            mode to \"in cell\". */\n            $this->insertElement($token);\n            $this->mode = self::IN_CELL;\n\n            /* Insert a marker at the end of the list of active formatting\n            elements. */\n            $this->a_formatting[] = self::MARKER;\n\n        /* An end tag whose tag name is \"tr\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'tr') {\n            /* If the stack of open elements does not have an element in table\n            scope with the same tag name as the token, this is a parse error.\n            Ignore the token. (fragment case) */\n            if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {\n                // Ignore.\n                $this->ignored = true;\n\n            /* Otherwise: */\n            } else {\n                /* Clear the stack back to a table row context. */\n                $this->clearStackToTableContext($clear);\n\n                /* Pop the current node (which will be a tr element) from the\n                stack of open elements. Switch the insertion mode to \"in table\n                body\". */\n                array_pop($this->stack);\n                $this->mode = self::IN_TABLE_BODY;\n            }\n\n        /* A start tag whose tag name is one of: \"caption\", \"col\", \"colgroup\",\n        \"tbody\", \"tfoot\", \"thead\", \"tr\" or an end tag whose tag name is \"table\" */\n        } elseif(($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],\n        array('caption', 'col', 'colgroup', 'tbody', 'tfoot', 'thead', 'tr'))) ||\n        ($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'table')) {\n            /* Act as if an end tag with the tag name \"tr\" had been seen, then,\n            if that token wasn't ignored, reprocess the current token. */\n            $this->emitToken(array(\n                'name' => 'tr',\n                'type' => HTML5_Tokenizer::ENDTAG\n            ));\n            if (!$this->ignored) $this->emitToken($token);\n\n        /* An end tag whose tag name is one of: \"tbody\", \"tfoot\", \"thead\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&\n        in_array($token['name'], array('tbody', 'tfoot', 'thead'))) {\n            /* If the stack of open elements does not have an element in table\n            scope with the same tag name as the token, this is a parse error.\n            Ignore the token. */\n            if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {\n                $this->ignored = true;\n\n            /* Otherwise: */\n            } else {\n                /* Otherwise, act as if an end tag with the tag name \"tr\" had\n                been seen, then reprocess the current token. */\n                $this->emitToken(array(\n                    'name' => 'tr',\n                    'type' => HTML5_Tokenizer::ENDTAG\n                ));\n\n                $this->emitToken($token);\n            }\n\n        /* An end tag whose tag name is one of: \"body\", \"caption\", \"col\",\n        \"colgroup\", \"html\", \"td\", \"th\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],\n        array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th'))) {\n            /* Parse error. Ignore the token. */\n            $this->ignored = true;\n\n        /* Anything else */\n        } else {\n            /* Process the token as if the insertion mode was \"in table\". */\n            $this->processWithRulesFor($token, self::IN_TABLE);\n        }\n    break;\n\n    case self::IN_CELL:\n        /* An end tag whose tag name is one of: \"td\", \"th\" */\n        if($token['type'] === HTML5_Tokenizer::ENDTAG &&\n        ($token['name'] === 'td' || $token['name'] === 'th')) {\n            /* If the stack of open elements does not have an element in table\n            scope with the same tag name as that of the token, then this is a\n            parse error and the token must be ignored. */\n            if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {\n                $this->ignored = true;\n\n            /* Otherwise: */\n            } else {\n                /* Generate implied end tags, except for elements with the same\n                tag name as the token. */\n                $this->generateImpliedEndTags(array($token['name']));\n\n                /* Now, if the current node is not an element with the same tag\n                name as the token, then this is a parse error. */\n                // XERROR: Implement parse error code\n\n                /* Pop elements from this stack until an element with the same\n                tag name as the token has been popped from the stack. */\n                do {\n                    $node = array_pop($this->stack);\n                } while ($node->tagName !== $token['name']);\n\n                /* Clear the list of active formatting elements up to the last\n                marker. */\n                $this->clearTheActiveFormattingElementsUpToTheLastMarker();\n\n                /* Switch the insertion mode to \"in row\". (The current node\n                will be a tr element at this point.) */\n                $this->mode = self::IN_ROW;\n            }\n\n        /* A start tag whose tag name is one of: \"caption\", \"col\", \"colgroup\",\n        \"tbody\", \"td\", \"tfoot\", \"th\", \"thead\", \"tr\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && in_array($token['name'],\n        array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th',\n        'thead', 'tr'))) {\n            /* If the stack of open elements does not have a td or th element\n            in table scope, then this is a parse error; ignore the token.\n            (fragment case) */\n            if(!$this->elementInScope(array('td', 'th'), self::SCOPE_TABLE)) {\n                // parse error\n                $this->ignored = true;\n\n            /* Otherwise, close the cell (see below) and reprocess the current\n            token. */\n            } else {\n                $this->closeCell();\n                $this->emitToken($token);\n            }\n\n        /* An end tag whose tag name is one of: \"body\", \"caption\", \"col\",\n        \"colgroup\", \"html\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],\n        array('body', 'caption', 'col', 'colgroup', 'html'))) {\n            /* Parse error. Ignore the token. */\n            $this->ignored = true;\n\n        /* An end tag whose tag name is one of: \"table\", \"tbody\", \"tfoot\",\n        \"thead\", \"tr\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && in_array($token['name'],\n        array('table', 'tbody', 'tfoot', 'thead', 'tr'))) {\n            /* If the stack of open elements does not have a td or th element\n            in table scope, then this is a parse error; ignore the token.\n            (innerHTML case) */\n            if(!$this->elementInScope(array('td', 'th'), self::SCOPE_TABLE)) {\n                // Parse error\n                $this->ignored = true;\n\n            /* Otherwise, close the cell (see below) and reprocess the current\n            token. */\n            } else {\n                $this->closeCell();\n                $this->emitToken($token);\n            }\n\n        /* Anything else */\n        } else {\n            /* Process the token as if the insertion mode was \"in body\". */\n            $this->processWithRulesFor($token, self::IN_BODY);\n        }\n    break;\n\n    case self::IN_SELECT:\n        /* Handle the token as follows: */\n\n        /* A character token */\n        if(\n            $token['type'] === HTML5_Tokenizer::CHARACTER ||\n            $token['type'] === HTML5_Tokenizer::SPACECHARACTER\n        ) {\n            /* Append the token's character to the current node. */\n            $this->insertText($token['data']);\n\n        /* A comment token */\n        } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {\n            /* Append a Comment node to the current node with the data\n            attribute set to the data given in the comment token. */\n            $this->insertComment($token['data']);\n\n        } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {\n            // parse error\n\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {\n            $this->processWithRulesFor($token, self::INBODY);\n\n        /* A start tag token whose tag name is \"option\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        $token['name'] === 'option') {\n            /* If the current node is an option element, act as if an end tag\n            with the tag name \"option\" had been seen. */\n            if(end($this->stack)->tagName === 'option') {\n                $this->emitToken(array(\n                    'name' => 'option',\n                    'type' => HTML5_Tokenizer::ENDTAG\n                ));\n            }\n\n            /* Insert an HTML element for the token. */\n            $this->insertElement($token);\n\n        /* A start tag token whose tag name is \"optgroup\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        $token['name'] === 'optgroup') {\n            /* If the current node is an option element, act as if an end tag\n            with the tag name \"option\" had been seen. */\n            if(end($this->stack)->tagName === 'option') {\n                $this->emitToken(array(\n                    'name' => 'option',\n                    'type' => HTML5_Tokenizer::ENDTAG\n                ));\n            }\n\n            /* If the current node is an optgroup element, act as if an end tag\n            with the tag name \"optgroup\" had been seen. */\n            if(end($this->stack)->tagName === 'optgroup') {\n                $this->emitToken(array(\n                    'name' => 'optgroup',\n                    'type' => HTML5_Tokenizer::ENDTAG\n                ));\n            }\n\n            /* Insert an HTML element for the token. */\n            $this->insertElement($token);\n\n        /* An end tag token whose tag name is \"optgroup\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&\n        $token['name'] === 'optgroup') {\n            /* First, if the current node is an option element, and the node\n            immediately before it in the stack of open elements is an optgroup\n            element, then act as if an end tag with the tag name \"option\" had\n            been seen. */\n            $elements_in_stack = count($this->stack);\n\n            if($this->stack[$elements_in_stack - 1]->tagName === 'option' &&\n            $this->stack[$elements_in_stack - 2]->tagName === 'optgroup') {\n                $this->emitToken(array(\n                    'name' => 'option',\n                    'type' => HTML5_Tokenizer::ENDTAG\n                ));\n            }\n\n            /* If the current node is an optgroup element, then pop that node\n            from the stack of open elements. Otherwise, this is a parse error,\n            ignore the token. */\n            if(end($this->stack)->tagName === 'optgroup') {\n                array_pop($this->stack);\n            } else {\n                // parse error\n                $this->ignored = true;\n            }\n\n        /* An end tag token whose tag name is \"option\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&\n        $token['name'] === 'option') {\n            /* If the current node is an option element, then pop that node\n            from the stack of open elements. Otherwise, this is a parse error,\n            ignore the token. */\n            if(end($this->stack)->tagName === 'option') {\n                array_pop($this->stack);\n            } else {\n                // parse error\n                $this->ignored = true;\n            }\n\n        /* An end tag whose tag name is \"select\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&\n        $token['name'] === 'select') {\n            /* If the stack of open elements does not have an element in table\n            scope with the same tag name as the token, this is a parse error.\n            Ignore the token. (fragment case) */\n            if(!$this->elementInScope($token['name'], self::SCOPE_TABLE)) {\n                $this->ignored = true;\n                // parse error\n\n            /* Otherwise: */\n            } else {\n                /* Pop elements from the stack of open elements until a select\n                element has been popped from the stack. */\n                do {\n                    $node = array_pop($this->stack);\n                } while ($node->tagName !== 'select');\n\n                /* Reset the insertion mode appropriately. */\n                $this->resetInsertionMode();\n            }\n\n        /* A start tag whose tag name is \"select\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'select') {\n            /* Parse error. Act as if the token had been an end tag with the\n            tag name \"select\" instead. */\n            $this->emitToken(array(\n                'name' => 'select',\n                'type' => HTML5_Tokenizer::ENDTAG\n            ));\n\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        ($token['name'] === 'input' || $token['name'] === 'keygen' ||  $token['name'] === 'textarea')) {\n            // parse error\n            $this->emitToken(array(\n                'name' => 'select',\n                'type' => HTML5_Tokenizer::ENDTAG\n            ));\n            $this->emitToken($token);\n\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'script') {\n            $this->processWithRulesFor($token, self::IN_HEAD);\n\n        } elseif($token['type'] === HTML5_Tokenizer::EOF) {\n            // XERROR: If the current node is not the root html element, then this is a parse error.\n            /* Stop parsing */\n\n        /* Anything else */\n        } else {\n            /* Parse error. Ignore the token. */\n            $this->ignored = true;\n        }\n    break;\n\n    case self::IN_SELECT_IN_TABLE:\n\n        if($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        in_array($token['name'], array('caption', 'table', 'tbody',\n        'tfoot', 'thead', 'tr', 'td', 'th'))) {\n            // parse error\n            $this->emitToken(array(\n                'name' => 'select',\n                'type' => HTML5_Tokenizer::ENDTAG,\n            ));\n            $this->emitToken($token);\n\n        /* An end tag whose tag name is one of: \"caption\", \"table\", \"tbody\",\n        \"tfoot\", \"thead\", \"tr\", \"td\", \"th\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&\n        in_array($token['name'], array('caption', 'table', 'tbody', 'tfoot', 'thead', 'tr', 'td', 'th')))  {\n            /* Parse error. */\n            // parse error\n\n            /* If the stack of open elements has an element in table scope with\n            the same tag name as that of the token, then act as if an end tag\n            with the tag name \"select\" had been seen, and reprocess the token.\n            Otherwise, ignore the token. */\n            if($this->elementInScope($token['name'], self::SCOPE_TABLE)) {\n                $this->emitToken(array(\n                    'name' => 'select',\n                    'type' => HTML5_Tokenizer::ENDTAG\n                ));\n\n                $this->emitToken($token);\n            } else {\n                $this->ignored = true;\n            }\n        } else {\n            $this->processWithRulesFor($token, self::IN_SELECT);\n        }\n    break;\n\n    case self::IN_FOREIGN_CONTENT:\n        if ($token['type'] === HTML5_Tokenizer::CHARACTER ||\n        $token['type'] === HTML5_Tokenizer::SPACECHARACTER) {\n            $this->insertText($token['data']);\n        } elseif ($token['type'] === HTML5_Tokenizer::COMMENT) {\n            $this->insertComment($token['data']);\n        } elseif ($token['type'] === HTML5_Tokenizer::DOCTYPE) {\n            // XERROR: parse error\n        } elseif ($token['type'] === HTML5_Tokenizer::ENDTAG &&\n        $token['name'] === 'script' && end($this->stack)->tagName === 'script' &&\n        // XDOM\n        end($this->stack)->namespaceURI === self::NS_SVG) {\n            array_pop($this->stack);\n            // a bunch of script running mumbo jumbo\n        } elseif (\n            ($token['type'] === HTML5_Tokenizer::STARTTAG &&\n                ((\n                    $token['name'] !== 'mglyph' &&\n                    $token['name'] !== 'malignmark' &&\n                    // XDOM\n                    end($this->stack)->namespaceURI === self::NS_MATHML &&\n                    in_array(end($this->stack)->tagName, array('mi', 'mo', 'mn', 'ms', 'mtext'))\n                ) ||\n                (\n                    $token['name'] === 'svg' &&\n                    // XDOM\n                    end($this->stack)->namespaceURI === self::NS_MATHML &&\n                    end($this->stack)->tagName === 'annotation-xml'\n                ) ||\n                (\n                    // XDOM\n                    end($this->stack)->namespaceURI === self::NS_SVG &&\n                    in_array(end($this->stack)->tagName, array('foreignObject', 'desc', 'title'))\n                ) ||\n                (\n                    // XSKETCHY && XDOM\n                    end($this->stack)->namespaceURI === self::NS_HTML\n                ))\n            ) || $token['type'] === HTML5_Tokenizer::ENDTAG\n        ) {\n            $this->processWithRulesFor($token, $this->secondary_mode);\n            /* If, after doing so, the insertion mode is still \"in foreign \n             * content\", but there is no element in scope that has a namespace \n             * other than the HTML namespace, switch the insertion mode to the \n             * secondary insertion mode. */\n            if ($this->mode === self::IN_FOREIGN_CONTENT) {\n                $found = false;\n                // this basically duplicates elementInScope()\n                for ($i = count($this->stack) - 1; $i >= 0; $i--) {\n                    // XDOM\n                    $node = $this->stack[$i];\n                    if ($node->namespaceURI !== self::NS_HTML) {\n                        $found = true;\n                        break;\n                    } elseif (in_array($node->tagName, array('table', 'html',\n                    'applet', 'caption', 'td', 'th', 'button', 'marquee',\n                    'object')) || ($node->tagName === 'foreignObject' &&\n                    $node->namespaceURI === self::NS_SVG)) {\n                        break;\n                    }\n                }\n                if (!$found) {\n                    $this->mode = $this->secondary_mode;\n                }\n            }\n        } elseif ($token['type'] === HTML5_Tokenizer::EOF || (\n        $token['type'] === HTML5_Tokenizer::STARTTAG &&\n        (in_array($token['name'], array('b', \"big\", \"blockquote\", \"body\", \"br\", \n        \"center\", \"code\", \"dc\", \"dd\", \"div\", \"dl\", \"ds\", \"dt\", \"em\", \"embed\", \"h1\", \"h2\", \n        \"h3\", \"h4\", \"h5\", \"h6\", \"head\", \"hr\", \"i\", \"img\", \"li\", \"listing\", \n        \"menu\", \"meta\", \"nobr\", \"ol\", \"p\", \"pre\", \"ruby\", \"s\",  \"small\", \n        \"span\", \"strong\", \"strike\",  \"sub\", \"sup\", \"table\", \"tt\", \"u\", \"ul\", \n        \"var\")) || ($token['name'] === 'font' && ($this->getAttr($token, 'color') ||\n        $this->getAttr($token, 'face') || $this->getAttr($token, 'size')))))) {\n            // XERROR: parse error\n            do {\n                $node = array_pop($this->stack);\n                // XDOM\n            } while ($node->namespaceURI !== self::NS_HTML);\n            $this->stack[] = $node;\n            $this->mode = $this->secondary_mode;\n            $this->emitToken($token);\n        } elseif ($token['type'] === HTML5_Tokenizer::STARTTAG) {\n            static $svg_lookup = array(\n                'altglyph' => 'altGlyph',\n                'altglyphdef' => 'altGlyphDef',\n                'altglyphitem' => 'altGlyphItem',\n                'animatecolor' => 'animateColor',\n                'animatemotion' => 'animateMotion',\n                'animatetransform' => 'animateTransform',\n                'clippath' => 'clipPath',\n                'feblend' => 'feBlend',\n                'fecolormatrix' => 'feColorMatrix',\n                'fecomponenttransfer' => 'feComponentTransfer',\n                'fecomposite' => 'feComposite',\n                'feconvolvematrix' => 'feConvolveMatrix',\n                'fediffuselighting' => 'feDiffuseLighting',\n                'fedisplacementmap' => 'feDisplacementMap',\n                'fedistantlight' => 'feDistantLight',\n                'feflood' => 'feFlood',\n                'fefunca' => 'feFuncA',\n                'fefuncb' => 'feFuncB',\n                'fefuncg' => 'feFuncG',\n                'fefuncr' => 'feFuncR',\n                'fegaussianblur' => 'feGaussianBlur',\n                'feimage' => 'feImage',\n                'femerge' => 'feMerge',\n                'femergenode' => 'feMergeNode',\n                'femorphology' => 'feMorphology',\n                'feoffset' => 'feOffset',\n                'fepointlight' => 'fePointLight',\n                'fespecularlighting' => 'feSpecularLighting',\n                'fespotlight' => 'feSpotLight',\n                'fetile' => 'feTile',\n                'feturbulence' => 'feTurbulence',\n                'foreignobject' => 'foreignObject',\n                'glyphref' => 'glyphRef',\n                'lineargradient' => 'linearGradient',\n                'radialgradient' => 'radialGradient',\n                'textpath' => 'textPath',\n            );\n            // XDOM\n            $current = end($this->stack);\n            if ($current->namespaceURI === self::NS_MATHML) {\n                $token = $this->adjustMathMLAttributes($token);\n            }\n            if ($current->namespaceURI === self::NS_SVG &&\n            isset($svg_lookup[$token['name']])) {\n                $token['name'] = $svg_lookup[$token['name']];\n            }\n            if ($current->namespaceURI === self::NS_SVG) {\n                $token = $this->adjustSVGAttributes($token);\n            }\n            $token = $this->adjustForeignAttributes($token);\n            $this->insertForeignElement($token, $current->namespaceURI);\n            if (isset($token['self-closing'])) {\n                array_pop($this->stack);\n                // XERROR: acknowledge self-closing flag\n            }\n        }\n    break;\n\n    case self::AFTER_BODY:\n        /* Handle the token as follows: */\n\n        /* A character token that is one of one of U+0009 CHARACTER TABULATION,\n        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),\n        or U+0020 SPACE */\n        if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {\n            /* Process the token as it would be processed if the insertion mode\n            was \"in body\". */\n            $this->processWithRulesFor($token, self::IN_BODY);\n\n        /* A comment token */\n        } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {\n            /* Append a Comment node to the first element in the stack of open\n            elements (the html element), with the data attribute set to the\n            data given in the comment token. */\n            // XDOM\n            $comment = $this->dom->createComment($token['data']);\n            $this->stack[0]->appendChild($comment);\n\n        } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {\n            // parse error\n\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {\n            $this->processWithRulesFor($token, self::IN_BODY);\n\n        /* An end tag with the tag name \"html\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG && $token['name'] === 'html') {\n            /*     If the parser was originally created as part of the HTML\n             *     fragment parsing algorithm, this is a parse error; ignore\n             *     the token. (fragment case) */\n            $this->ignored = true;\n            // XERROR: implement this\n\n            $this->mode = self::AFTER_AFTER_BODY;\n\n        } elseif($token['type'] === HTML5_Tokenizer::EOF) {\n            /* Stop parsing */\n\n        /* Anything else */\n        } else {\n            /* Parse error. Set the insertion mode to \"in body\" and reprocess\n            the token. */\n            $this->mode = self::IN_BODY;\n            $this->emitToken($token);\n        }\n    break;\n\n    case self::IN_FRAMESET:\n        /* Handle the token as follows: */\n\n        /* A character token that is one of one of U+0009 CHARACTER TABULATION,\n        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),\n        U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */\n        if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {\n            /* Append the character to the current node. */\n            $this->insertText($token['data']);\n\n        /* A comment token */\n        } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {\n            /* Append a Comment node to the current node with the data\n            attribute set to the data given in the comment token. */\n            $this->insertComment($token['data']);\n\n        } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {\n            // parse error\n\n        /* A start tag with the tag name \"frameset\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        $token['name'] === 'frameset') {\n            $this->insertElement($token);\n\n        /* An end tag with the tag name \"frameset\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&\n        $token['name'] === 'frameset') {\n            /* If the current node is the root html element, then this is a\n            parse error; ignore the token. (fragment case) */\n            if(end($this->stack)->tagName === 'html') {\n                $this->ignored = true;\n                // Parse error\n\n            } else {\n                /* Otherwise, pop the current node from the stack of open\n                elements. */\n                array_pop($this->stack);\n\n                /* If the parser was not originally created as part of the HTML \n                 * fragment parsing algorithm  (fragment case), and the current \n                 * node is no longer a frameset element, then switch the \n                 * insertion mode to \"after frameset\". */\n                $this->mode = self::AFTER_FRAMESET;\n            }\n\n        /* A start tag with the tag name \"frame\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        $token['name'] === 'frame') {\n            /* Insert an HTML element for the token. */\n            $this->insertElement($token);\n\n            /* Immediately pop the current node off the stack of open elements. */\n            array_pop($this->stack);\n\n            // XERROR: Acknowledge the token's self-closing flag, if it is set.\n\n        /* A start tag with the tag name \"noframes\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        $token['name'] === 'noframes') {\n            /* Process the token using the rules for the \"in head\" insertion mode. */\n            $this->processwithRulesFor($token, self::IN_HEAD);\n\n        } elseif($token['type'] === HTML5_Tokenizer::EOF) {\n            // XERROR: If the current node is not the root html element, then this is a parse error.\n            /* Stop parsing */\n        /* Anything else */\n        } else {\n            /* Parse error. Ignore the token. */\n            $this->ignored = true;\n        }\n    break;\n\n    case self::AFTER_FRAMESET:\n        /* Handle the token as follows: */\n\n        /* A character token that is one of one of U+0009 CHARACTER TABULATION,\n        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),\n        U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */\n        if($token['type'] === HTML5_Tokenizer::SPACECHARACTER) {\n            /* Append the character to the current node. */\n            $this->insertText($token['data']);\n\n        /* A comment token */\n        } elseif($token['type'] === HTML5_Tokenizer::COMMENT) {\n            /* Append a Comment node to the current node with the data\n            attribute set to the data given in the comment token. */\n            $this->insertComment($token['data']);\n\n        } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE) {\n            // parse error\n\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html') {\n            $this->processWithRulesFor($token, self::IN_BODY);\n\n        /* An end tag with the tag name \"html\" */\n        } elseif($token['type'] === HTML5_Tokenizer::ENDTAG &&\n        $token['name'] === 'html') {\n            $this->mode = self::AFTER_AFTER_FRAMESET;\n\n        /* A start tag with the tag name \"noframes\" */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG &&\n        $token['name'] === 'noframes') {\n            $this->processWithRulesFor($token, self::IN_HEAD);\n\n        } elseif($token['type'] === HTML5_Tokenizer::EOF) {\n            /* Stop parsing */\n\n        /* Anything else */\n        } else {\n            /* Parse error. Ignore the token. */\n            $this->ignored = true;\n        }\n    break;\n\n    case self::AFTER_AFTER_BODY:\n        /* A comment token */\n        if($token['type'] === HTML5_Tokenizer::COMMENT) {\n            /* Append a Comment node to the Document object with the data\n            attribute set to the data given in the comment token. */\n            // XDOM\n            $comment = $this->dom->createComment($token['data']);\n            $this->dom->appendChild($comment);\n\n        } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE ||\n        $token['type'] === HTML5_Tokenizer::SPACECHARACTER ||\n        ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html')) {\n            $this->processWithRulesFor($token, self::IN_BODY);\n\n        /* An end-of-file token */\n        } elseif($token['type'] === HTML5_Tokenizer::EOF) {\n            /* OMG DONE!! */\n        } else {\n            // parse error\n            $this->mode = self::IN_BODY;\n            $this->emitToken($token);\n        }\n    break;\n\n    case self::AFTER_AFTER_FRAMESET:\n        /* A comment token */\n        if($token['type'] === HTML5_Tokenizer::COMMENT) {\n            /* Append a Comment node to the Document object with the data\n            attribute set to the data given in the comment token. */\n            // XDOM\n            $comment = $this->dom->createComment($token['data']);\n            $this->dom->appendChild($comment);\n\n        } elseif($token['type'] === HTML5_Tokenizer::DOCTYPE ||\n        $token['type'] === HTML5_Tokenizer::SPACECHARACTER ||\n        ($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'html')) {\n            $this->processWithRulesFor($token, self::IN_BODY);\n\n        /* An end-of-file token */\n        } elseif($token['type'] === HTML5_Tokenizer::EOF) {\n            /* OMG DONE!! */\n        } elseif($token['type'] === HTML5_Tokenizer::STARTTAG && $token['name'] === 'nofrmaes') {\n            $this->processWithRulesFor($token, self::IN_HEAD);\n        } else {\n            // parse error\n        }\n    break;\n    }\n        // end funky indenting\n        }\n\n    private function insertElement($token, $append = true) {\n        //$el = $this->dom->createElementNS(self::NS_HTML, $token['name']);\n        $namespaceURI = strpos($token['name'], ':') ? self::NS_XHTML : self::NS_HTML;\n        $el = $this->dom->createElementNS($namespaceURI, $token['name']);\n\n        if (!empty($token['attr'])) {\n            foreach($token['attr'] as $attr) {\n                // mike@macgirvin.com 2011-11-17, check attribute name for\n                // validity (ignoring extenders and combiners) as illegal chars in names\n                // causes everything to abort\n\n                $valid = preg_match('/^[a-zA-Z\\_\\:]([\\-a-zA-Z0-9\\_\\:\\.]+$)/',$attr['name']);\n                if($attr['name'] && (!$el->hasAttribute($attr['name'])) && ($valid)) {\n                    $el->setAttribute($attr['name'], $attr['value']);\n                }\n            }\n        }\n        if ($append) {\n            $this->appendToRealParent($el);\n            $this->stack[] = $el;\n        }\n\n        return $el;\n    }\n\n    private function insertText($data) {\n        if ($data === '') return;\n        if ($this->ignore_lf_token) {\n            if ($data[0] === \"\\n\") {\n                $data = substr($data, 1);\n                if ($data === false) return;\n            }\n        }\n        $text = $this->dom->createTextNode($data);\n        $this->appendToRealParent($text);\n    }\n\n    private function insertComment($data) {\n        $comment = $this->dom->createComment($data);\n        $this->appendToRealParent($comment);\n    }\n\n    private function appendToRealParent($node) {\n        // this is only for the foster_parent case\n        /* If the current node is a table, tbody, tfoot, thead, or tr\n        element, then, whenever a node would be inserted into the current\n        node, it must instead be inserted into the foster parent element. */\n        if(!$this->foster_parent || !in_array(end($this->stack)->tagName,\n        array('table', 'tbody', 'tfoot', 'thead', 'tr'))) {\n            end($this->stack)->appendChild($node);\n        } else {\n            $this->fosterParent($node);\n        }\n    }\n\n    private function elementInScope($el, $scope = self::SCOPE) {\n        if(is_array($el)) {\n            foreach($el as $element) {\n                if($this->elementInScope($element, $scope)) {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n\n        $leng = count($this->stack);\n\n        for($n = 0; $n < $leng; $n++) {\n            /* 1. Initialise node to be the current node (the bottommost node of\n            the stack). */\n            $node = $this->stack[$leng - 1 - $n];\n\n            if($node->tagName === $el) {\n                /* 2. If node is the target node, terminate in a match state. */\n                return true;\n\n                // We've expanded the logic for these states a little differently;\n                // Hixie's refactoring into \"specific scope\" is more general, but\n                // this \"gets the job done\"\n\n            // these are the common states for all scopes\n            } elseif($node->tagName === 'table' || $node->tagName === 'html') {\n                return false;\n\n            // these are valid for \"in scope\" and \"in list item scope\"\n            } elseif($scope !== self::SCOPE_TABLE &&\n            (in_array($node->tagName, array('applet', 'caption', 'td',\n                'th', 'button', 'marquee', 'object')) ||\n                $node->tagName === 'foreignObject' && $node->namespaceURI === self::NS_SVG)) {\n                return false;\n\n\n            // these are valid for \"in list item scope\"\n            } elseif($scope === self::SCOPE_LISTITEM && in_array($node->tagName, array('ol', 'ul'))) {\n                return false;\n            }\n\n            /* Otherwise, set node to the previous entry in the stack of open\n            elements and return to step 2. (This will never fail, since the loop\n            will always terminate in the previous step if the top of the stack\n            is reached.) */\n        }\n    }\n\n    private function reconstructActiveFormattingElements() {\n        /* 1. If there are no entries in the list of active formatting elements,\n        then there is nothing to reconstruct; stop this algorithm. */\n        $formatting_elements = count($this->a_formatting);\n\n        if($formatting_elements === 0) {\n            return false;\n        }\n\n        /* 3. Let entry be the last (most recently added) element in the list\n        of active formatting elements. */\n        $entry = end($this->a_formatting);\n\n        /* 2. If the last (most recently added) entry in the list of active\n        formatting elements is a marker, or if it is an element that is in the\n        stack of open elements, then there is nothing to reconstruct; stop this\n        algorithm. */\n        if($entry === self::MARKER || in_array($entry, $this->stack, true)) {\n            return false;\n        }\n\n        for($a = $formatting_elements - 1; $a >= 0; true) {\n            /* 4. If there are no entries before entry in the list of active\n            formatting elements, then jump to step 8. */\n            if($a === 0) {\n                $step_seven = false;\n                break;\n            }\n\n            /* 5. Let entry be the entry one earlier than entry in the list of\n            active formatting elements. */\n            $a--;\n            $entry = $this->a_formatting[$a];\n\n            /* 6. If entry is neither a marker nor an element that is also in\n            thetack of open elements, go to step 4. */\n            if($entry === self::MARKER || in_array($entry, $this->stack, true)) {\n                break;\n            }\n        }\n\n        while(true) {\n            /* 7. Let entry be the element one later than entry in the list of\n            active formatting elements. */\n            if(isset($step_seven) && $step_seven === true) {\n                $a++;\n                $entry = $this->a_formatting[$a];\n            }\n\n            /* 8. Perform a shallow clone of the element entry to obtain clone. */\n            $clone = $entry->cloneNode();\n\n            /* 9. Append clone to the current node and push it onto the stack\n            of open elements  so that it is the new current node. */\n            $this->appendToRealParent($clone);\n            $this->stack[] = $clone;\n\n            /* 10. Replace the entry for entry in the list with an entry for\n            clone. */\n            $this->a_formatting[$a] = $clone;\n\n            /* 11. If the entry for clone in the list of active formatting\n            elements is not the last entry in the list, return to step 7. */\n            if(end($this->a_formatting) !== $clone) {\n                $step_seven = true;\n            } else {\n                break;\n            }\n        }\n    }\n\n    private function clearTheActiveFormattingElementsUpToTheLastMarker() {\n        /* When the steps below require the UA to clear the list of active\n        formatting elements up to the last marker, the UA must perform the\n        following steps: */\n\n        while(true) {\n            /* 1. Let entry be the last (most recently added) entry in the list\n            of active formatting elements. */\n            $entry = end($this->a_formatting);\n\n            /* 2. Remove entry from the list of active formatting elements. */\n            array_pop($this->a_formatting);\n\n            /* 3. If entry was a marker, then stop the algorithm at this point.\n            The list has been cleared up to the last marker. */\n            if($entry === self::MARKER) {\n                break;\n            }\n        }\n    }\n\n    private function generateImpliedEndTags($exclude = array()) {\n        /* When the steps below require the UA to generate implied end tags, \n         * then, while the current node is a dc element, a dd element, a ds \n         * element, a dt element, an li element, an option element, an optgroup \n         * element, a p element, an rp element, or an rt element, the UA must \n         * pop the current node off the stack of open elements. */\n        $node = end($this->stack);\n        $elements = array_diff(array('dc', 'dd', 'ds', 'dt', 'li', 'p', 'td', 'th', 'tr'), $exclude);\n\n        while(in_array(end($this->stack)->tagName, $elements)) {\n            array_pop($this->stack);\n        }\n    }\n\n    private function getElementCategory($node) {\n        if (!is_object($node)) debug_print_backtrace();\n        $name = $node->tagName;\n        if(in_array($name, $this->special))\n            return self::SPECIAL;\n\n        elseif(in_array($name, $this->scoping))\n            return self::SCOPING;\n\n        elseif(in_array($name, $this->formatting))\n            return self::FORMATTING;\n\n        else\n            return self::PHRASING;\n    }\n\n    private function clearStackToTableContext($elements) {\n        /* When the steps above require the UA to clear the stack back to a\n        table context, it means that the UA must, while the current node is not\n        a table element or an html element, pop elements from the stack of open\n        elements. */\n        while(true) {\n            $name = end($this->stack)->tagName;\n\n            if(in_array($name, $elements)) {\n                break;\n            } else {\n                array_pop($this->stack);\n            }\n        }\n    }\n\n    private function resetInsertionMode($context = null) {\n        /* 1. Let last be false. */\n        $last = false;\n        $leng = count($this->stack);\n\n        for($n = $leng - 1; $n >= 0; $n--) {\n            /* 2. Let node be the last node in the stack of open elements. */\n            $node = $this->stack[$n];\n\n            /* 3. If node is the first node in the stack of open elements, then \n             * set last to true and set node to the context  element. (fragment \n             * case) */\n            if($this->stack[0]->isSameNode($node)) {\n                $last = true;\n                $node = $context;\n            }\n\n            /* 4. If node is a select element, then switch the insertion mode to\n            \"in select\" and abort these steps. (fragment case) */\n            if($node->tagName === 'select') {\n                $this->mode = self::IN_SELECT;\n                break;\n\n            /* 5. If node is a td or th element, then switch the insertion mode\n            to \"in cell\" and abort these steps. */\n            } elseif($node->tagName === 'td' || $node->nodeName === 'th') {\n                $this->mode = self::IN_CELL;\n                break;\n\n            /* 6. If node is a tr element, then switch the insertion mode to\n            \"in    row\" and abort these steps. */\n            } elseif($node->tagName === 'tr') {\n                $this->mode = self::IN_ROW;\n                break;\n\n            /* 7. If node is a tbody, thead, or tfoot element, then switch the\n            insertion mode to \"in table body\" and abort these steps. */\n            } elseif(in_array($node->tagName, array('tbody', 'thead', 'tfoot'))) {\n                $this->mode = self::IN_TABLE_BODY;\n                break;\n\n            /* 8. If node is a caption element, then switch the insertion mode\n            to \"in caption\" and abort these steps. */\n            } elseif($node->tagName === 'caption') {\n                $this->mode = self::IN_CAPTION;\n                break;\n\n            /* 9. If node is a colgroup element, then switch the insertion mode\n            to \"in column group\" and abort these steps. (innerHTML case) */\n            } elseif($node->tagName === 'colgroup') {\n                $this->mode = self::IN_COLUMN_GROUP;\n                break;\n\n            /* 10. If node is a table element, then switch the insertion mode\n            to \"in table\" and abort these steps. */\n            } elseif($node->tagName === 'table') {\n                $this->mode = self::IN_TABLE;\n                break;\n\n            /* 11. If node is an element from the MathML namespace or the SVG \n             * namespace, then switch the insertion mode to \"in foreign \n             * content\", let the secondary insertion mode be \"in body\", and \n             * abort these steps. */\n            } elseif($node->namespaceURI === self::NS_SVG ||\n            $node->namespaceURI === self::NS_MATHML) {\n                $this->mode = self::IN_FOREIGN_CONTENT;\n                $this->secondary_mode = self::IN_BODY;\n                break;\n\n            /* 12. If node is a head element, then switch the insertion mode\n            to \"in body\" (\"in body\"! not \"in head\"!) and abort these steps.\n            (fragment case) */\n            } elseif($node->tagName === 'head') {\n                $this->mode = self::IN_BODY;\n                break;\n\n            /* 13. If node is a body element, then switch the insertion mode to\n            \"in body\" and abort these steps. */\n            } elseif($node->tagName === 'body') {\n                $this->mode = self::IN_BODY;\n                break;\n\n            /* 14. If node is a frameset element, then switch the insertion\n            mode to \"in frameset\" and abort these steps. (fragment case) */\n            } elseif($node->tagName === 'frameset') {\n                $this->mode = self::IN_FRAMESET;\n                break;\n\n            /* 15. If node is an html element, then: if the head element\n            pointer is null, switch the insertion mode to \"before head\",\n            otherwise, switch the insertion mode to \"after head\". In either\n            case, abort these steps. (fragment case) */\n            } elseif($node->tagName === 'html') {\n                $this->mode = ($this->head_pointer === null)\n                    ? self::BEFORE_HEAD\n                    : self::AFTER_HEAD;\n\n                break;\n\n            /* 16. If last is true, then set the insertion mode to \"in body\"\n            and    abort these steps. (fragment case) */\n            } elseif($last) {\n                $this->mode = self::IN_BODY;\n                break;\n            }\n        }\n    }\n\n    private function closeCell() {\n        /* If the stack of open elements has a td or th element in table scope,\n        then act as if an end tag token with that tag name had been seen. */\n        foreach(array('td', 'th') as $cell) {\n            if($this->elementInScope($cell, self::SCOPE_TABLE)) {\n                $this->emitToken(array(\n                    'name' => $cell,\n                    'type' => HTML5_Tokenizer::ENDTAG\n                ));\n\n                break;\n            }\n        }\n    }\n\n    private function processWithRulesFor($token, $mode) {\n        /* \"using the rules for the m insertion mode\", where m is one of these\n         * modes, the user agent must use the rules described under the m\n         * insertion mode's section, but must leave the insertion mode\n         * unchanged unless the rules in m themselves switch the insertion mode\n         * to a new value. */\n        return $this->emitToken($token, $mode);\n    }\n\n    private function insertCDATAElement($token) {\n        $this->insertElement($token);\n        $this->original_mode = $this->mode;\n        $this->mode = self::IN_CDATA_RCDATA;\n        $this->content_model = HTML5_Tokenizer::CDATA;\n    }\n\n    private function insertRCDATAElement($token) {\n        $this->insertElement($token);\n        $this->original_mode = $this->mode;\n        $this->mode = self::IN_CDATA_RCDATA;\n        $this->content_model = HTML5_Tokenizer::RCDATA;\n    }\n\n    private function getAttr($token, $key) {\n        if (!isset($token['attr'])) return false;\n        $ret = false;\n        foreach ($token['attr'] as $keypair) {\n            if ($keypair['name'] === $key) $ret = $keypair['value'];\n        }\n        return $ret;\n    }\n\n    private function getCurrentTable() {\n        /* The current table is the last table  element in the stack of open \n         * elements, if there is one. If there is no table element in the stack \n         * of open elements (fragment case), then the current table is the \n         * first element in the stack of open elements (the html element). */\n        for ($i = count($this->stack) - 1; $i >= 0; $i--) {\n            if ($this->stack[$i]->tagName === 'table') {\n                return $this->stack[$i];\n            }\n        }\n        return $this->stack[0];\n    }\n\n    private function getFosterParent() {\n        /* The foster parent element is the parent element of the last\n        table element in the stack of open elements, if there is a\n        table element and it has such a parent element. If there is no\n        table element in the stack of open elements (innerHTML case),\n        then the foster parent element is the first element in the\n        stack of open elements (the html  element). Otherwise, if there\n        is a table element in the stack of open elements, but the last\n        table element in the stack of open elements has no parent, or\n        its parent node is not an element, then the foster parent\n        element is the element before the last table element in the\n        stack of open elements. */\n        for($n = count($this->stack) - 1; $n >= 0; $n--) {\n            if($this->stack[$n]->tagName === 'table') {\n                $table = $this->stack[$n];\n                break;\n            }\n        }\n\n        if(isset($table) && $table->parentNode !== null) {\n            return $table->parentNode;\n\n        } elseif(!isset($table)) {\n            return $this->stack[0];\n\n        } elseif(isset($table) && ($table->parentNode === null ||\n        $table->parentNode->nodeType !== XML_ELEMENT_NODE)) {\n            return $this->stack[$n - 1];\n        }\n    }\n\n    public function fosterParent($node) {\n        $foster_parent = $this->getFosterParent();\n        $table = $this->getCurrentTable(); // almost equivalent to last table element, except it can be html\n        /* When a node node is to be foster parented, the node node must be\n         * be inserted into the foster parent element. */\n        /* If the foster parent element is the parent element of the last table \n         * element in the stack of open elements, then node must be inserted \n         * immediately before the last table element in the stack of open \n         * elements in the foster parent element; otherwise, node must be \n         * appended to the foster parent element. */\n        if ($table->tagName === 'table' && $table->parentNode->isSameNode($foster_parent)) {\n            $foster_parent->insertBefore($node, $table);\n        } else {\n            $foster_parent->appendChild($node);\n        }\n    }\n\n    /**\n     * For debugging, prints the stack\n     */\n    private function printStack() {\n        $names = array();\n        foreach ($this->stack as $i => $element) {\n            $names[] = $element->tagName;\n        }\n        echo \"  -> stack [\" . implode(', ', $names) . \"]\\n\";\n    }\n\n    /**\n     * For debugging, prints active formatting elements\n     */\n    private function printActiveFormattingElements() {\n        if (!$this->a_formatting) return;\n        $names = array();\n        foreach ($this->a_formatting as $node) {\n            if ($node === self::MARKER) $names[] = 'MARKER';\n            else $names[] = $node->tagName;\n        }\n        echo \"  -> active formatting [\" . implode(', ', $names) . \"]\\n\";\n    }\n\n    public function currentTableIsTainted() {\n        return !empty($this->getCurrentTable()->tainted);\n    }\n\n    /**\n     * Sets up the tree constructor for building a fragment.\n     */\n    public function setupContext($context = null) {\n        $this->fragment = true;\n        if ($context) {\n            $context = $this->dom->createElementNS(self::NS_HTML, $context);\n            /* 4.1. Set the HTML parser's tokenization  stage's content model\n             * flag according to the context element, as follows: */\n            switch ($context->tagName) {\n            case 'title': case 'textarea':\n                $this->content_model = HTML5_Tokenizer::RCDATA;\n                break;\n            case 'style': case 'script': case 'xmp': case 'iframe':\n            case 'noembed': case 'noframes':\n                $this->content_model = HTML5_Tokenizer::CDATA;\n                break;\n            case 'noscript':\n                // XSCRIPT: assuming scripting is enabled\n                $this->content_model = HTML5_Tokenizer::CDATA;\n                break;\n            case 'plaintext':\n                $this->content_model = HTML5_Tokenizer::PLAINTEXT;\n                break;\n            }\n            /* 4.2. Let root be a new html element with no attributes. */\n            $root = $this->dom->createElementNS(self::NS_HTML, 'html');\n            $this->root = $root;\n            /* 4.3 Append the element root to the Document node created above. */\n            $this->dom->appendChild($root);\n            /* 4.4 Set up the parser's stack of open elements so that it \n             * contains just the single element root. */\n            $this->stack = array($root);\n            /* 4.5 Reset the parser's insertion mode appropriately. */\n            $this->resetInsertionMode($context);\n            /* 4.6 Set the parser's form element pointer  to the nearest node \n             * to the context element that is a form element (going straight up \n             * the ancestor chain, and including the element itself, if it is a \n             * form element), or, if there is no such form element, to null. */\n            $node = $context;\n            do {\n                if ($node->tagName === 'form') {\n                    $this->form_pointer = $node;\n                    break;\n                }\n            } while ($node = $node->parentNode);\n        }\n    }\n\n    public function adjustMathMLAttributes($token) {\n        foreach ($token['attr'] as &$kp) {\n            if ($kp['name'] === 'definitionurl') {\n                $kp['name'] = 'definitionURL';\n            }\n        }\n        return $token;\n    }\n\n    public function adjustSVGAttributes($token) {\n        static $lookup = array(\n            'attributename' => 'attributeName',\n            'attributetype' => 'attributeType',\n            'basefrequency' => 'baseFrequency',\n            'baseprofile' => 'baseProfile',\n            'calcmode' => 'calcMode',\n            'clippathunits' => 'clipPathUnits',\n            'contentscripttype' => 'contentScriptType',\n            'contentstyletype' => 'contentStyleType',\n            'diffuseconstant' => 'diffuseConstant',\n            'edgemode' => 'edgeMode',\n            'externalresourcesrequired' => 'externalResourcesRequired',\n            'filterres' => 'filterRes',\n            'filterunits' => 'filterUnits',\n            'glyphref' => 'glyphRef',\n            'gradienttransform' => 'gradientTransform',\n            'gradientunits' => 'gradientUnits',\n            'kernelmatrix' => 'kernelMatrix',\n            'kernelunitlength' => 'kernelUnitLength',\n            'keypoints' => 'keyPoints',\n            'keysplines' => 'keySplines',\n            'keytimes' => 'keyTimes',\n            'lengthadjust' => 'lengthAdjust',\n            'limitingconeangle' => 'limitingConeAngle',\n            'markerheight' => 'markerHeight',\n            'markerunits' => 'markerUnits',\n            'markerwidth' => 'markerWidth',\n            'maskcontentunits' => 'maskContentUnits',\n            'maskunits' => 'maskUnits',\n            'numoctaves' => 'numOctaves',\n            'pathlength' => 'pathLength',\n            'patterncontentunits' => 'patternContentUnits',\n            'patterntransform' => 'patternTransform',\n            'patternunits' => 'patternUnits',\n            'pointsatx' => 'pointsAtX',\n            'pointsaty' => 'pointsAtY',\n            'pointsatz' => 'pointsAtZ',\n            'preservealpha' => 'preserveAlpha',\n            'preserveaspectratio' => 'preserveAspectRatio',\n            'primitiveunits' => 'primitiveUnits',\n            'refx' => 'refX',\n            'refy' => 'refY',\n            'repeatcount' => 'repeatCount',\n            'repeatdur' => 'repeatDur',\n            'requiredextensions' => 'requiredExtensions',\n            'requiredfeatures' => 'requiredFeatures',\n            'specularconstant' => 'specularConstant',\n            'specularexponent' => 'specularExponent',\n            'spreadmethod' => 'spreadMethod',\n            'startoffset' => 'startOffset',\n            'stddeviation' => 'stdDeviation',\n            'stitchtiles' => 'stitchTiles',\n            'surfacescale' => 'surfaceScale',\n            'systemlanguage' => 'systemLanguage',\n            'tablevalues' => 'tableValues',\n            'targetx' => 'targetX',\n            'targety' => 'targetY',\n            'textlength' => 'textLength',\n            'viewbox' => 'viewBox',\n            'viewtarget' => 'viewTarget',\n            'xchannelselector' => 'xChannelSelector',\n            'ychannelselector' => 'yChannelSelector',\n            'zoomandpan' => 'zoomAndPan',\n        );\n        foreach ($token['attr'] as &$kp) {\n            if (isset($lookup[$kp['name']])) {\n                $kp['name'] = $lookup[$kp['name']];\n            }\n        }\n        return $token;\n    }\n\n    public function adjustForeignAttributes($token) {\n        static $lookup = array(\n            'xlink:actuate' => array('xlink', 'actuate', self::NS_XLINK),\n            'xlink:arcrole' => array('xlink', 'arcrole', self::NS_XLINK),\n            'xlink:href' => array('xlink', 'href', self::NS_XLINK),\n            'xlink:role' => array('xlink', 'role', self::NS_XLINK),\n            'xlink:show' => array('xlink', 'show', self::NS_XLINK),\n            'xlink:title' => array('xlink', 'title', self::NS_XLINK),\n            'xlink:type' => array('xlink', 'type', self::NS_XLINK),\n            'xml:base' => array('xml', 'base', self::NS_XML),\n            'xml:lang' => array('xml', 'lang', self::NS_XML),\n            'xml:space' => array('xml', 'space', self::NS_XML),\n            'xmlns' => array(null, 'xmlns', self::NS_XMLNS),\n            'xmlns:xlink' => array('xmlns', 'xlink', self::NS_XMLNS),\n        );\n        foreach ($token['attr'] as &$kp) {\n            if (isset($lookup[$kp['name']])) {\n                $kp['name'] = $lookup[$kp['name']];\n            }\n        }\n        return $token;\n    }\n\n    public function insertForeignElement($token, $namespaceURI) {\n        $el = $this->dom->createElementNS($namespaceURI, $token['name']);\n        if (!empty($token['attr'])) {\n            foreach ($token['attr'] as $kp) {\n                $attr = $kp['name'];\n                if (is_array($attr)) {\n                    $ns = $attr[2];\n                    $attr = $attr[1];\n                } else {\n                    $ns = self::NS_HTML;\n                }\n                if (!$el->hasAttributeNS($ns, $attr)) {\n                    // XSKETCHY: work around godawful libxml bug\n                    if ($ns === self::NS_XLINK) {\n                        $el->setAttribute('xlink:'.$attr, $kp['value']);\n                    } elseif ($ns === self::NS_HTML) {\n                        // Another godawful libxml bug\n                        $el->setAttribute($attr, $kp['value']);\n                    } else {\n                        $el->setAttributeNS($ns, $attr, $kp['value']);\n                    }\n                }\n            }\n        }\n        $this->appendToRealParent($el);\n        $this->stack[] = $el;\n        // XERROR: see below\n        /* If the newly created element has an xmlns attribute in the XMLNS \n         * namespace  whose value is not exactly the same as the element's \n         * namespace, that is a parse error. Similarly, if the newly created \n         * element has an xmlns:xlink attribute in the XMLNS namespace whose \n         * value is not the XLink Namespace, that is a parse error. */\n    }\n\n    public function save() {\n        $this->dom->normalize();\n        if (!$this->fragment) {\n            return $this->dom;\n        } else {\n            if ($this->root) {\n                return $this->root->childNodes;\n            } else {\n                return $this->dom->childNodes;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "libraries/html5/named-character-references.ser",
    "content": "a:52:{s:1:\"A\";a:16:{s:1:\"E\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:198;}s:9:\"codepoint\";i:198;}}}}s:1:\"M\";a:1:{s:1:\"P\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:38;}s:9:\"codepoint\";i:38;}}s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:193;}s:9:\"codepoint\";i:193;}}}}}s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:258;}}}}}}s:1:\"c\";a:2:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:194;}s:9:\"codepoint\";i:194;}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1040;}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120068;}}}s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:192;}s:9:\"codepoint\";i:192;}}}}}s:1:\"l\";a:1:{s:1:\"p\";a:1:{s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:913;}}}}}s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:256;}}}}}s:1:\"n\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10835;}}}s:1:\"o\";a:2:{s:1:\"g\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:260;}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120120;}}}}s:1:\"p\";a:1:{s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"y\";a:1:{s:1:\"F\";a:1:{s:1:\"u\";a:1:{s:1:\"n\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8289;}}}}}}}}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:197;}s:9:\"codepoint\";i:197;}}}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119964;}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8788;}}}}}}s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:195;}s:9:\"codepoint\";i:195;}}}}}s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:196;}s:9:\"codepoint\";i:196;}}}}s:1:\"B\";a:8:{s:1:\"a\";a:2:{s:1:\"c\";a:1:{s:1:\"k\";a:1:{s:1:\"s\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8726;}}}}}}}}s:1:\"r\";a:2:{s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10983;}}s:1:\"w\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8966;}}}}}}s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1041;}}}s:1:\"e\";a:3:{s:1:\"c\";a:1:{s:1:\"a\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8757;}}}}}}s:1:\"r\";a:1:{s:1:\"n\";a:1:{s:1:\"o\";a:1:{s:1:\"u\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8492;}}}}}}}}}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:914;}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120069;}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120121;}}}}s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:728;}}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8492;}}}}s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\"p\";a:1:{s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8782;}}}}}}}s:1:\"C\";a:14:{s:1:\"H\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1063;}}}}s:1:\"O\";a:1:{s:1:\"P\";a:1:{s:1:\"Y\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:169;}s:9:\"codepoint\";i:169;}}}s:1:\"a\";a:3:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:262;}}}}}s:1:\"p\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8914;}s:1:\"i\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"D\";a:1:{s:1:\"i\";a:1:{s:1:\"f\";a:1:{s:1:\"f\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"D\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8517;}}}}}}}}}}}}}}}}}}}s:1:\"y\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"y\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8493;}}}}}}}s:1:\"c\";a:4:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:268;}}}}}s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:199;}s:9:\"codepoint\";i:199;}}}}s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:264;}}}}s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8752;}}}}}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:266;}}}}s:1:\"e\";a:2:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:184;}}}}}}s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:183;}}}}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8493;}}}s:1:\"h\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:935;}}}s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:4:{s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8857;}}}}s:1:\"M\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8854;}}}}}}s:1:\"P\";a:1:{s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8853;}}}}}s:1:\"T\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8855;}}}}}}}}}}}s:1:\"l\";a:1:{s:1:\"o\";a:2:{s:1:\"c\";a:1:{s:1:\"k\";a:1:{s:1:\"w\";a:1:{s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"C\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"u\";a:1:{s:1:\"r\";a:1:{s:1:\"I\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8754;}}}}}}}}}}}}}}}}}}}}}}s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"C\";a:1:{s:1:\"u\";a:1:{s:1:\"r\";a:1:{s:1:\"l\";a:1:{s:1:\"y\";a:2:{s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"u\";a:1:{s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"Q\";a:1:{s:1:\"u\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8221;}}}}}}}}}}}}s:1:\"Q\";a:1:{s:1:\"u\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8217;}}}}}}}}}}}}}}}s:1:\"o\";a:4:{s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8759;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10868;}}}}}s:1:\"n\";a:3:{s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"u\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8801;}}}}}}}s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8751;}}}}s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"u\";a:1:{s:1:\"r\";a:1:{s:1:\"I\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8750;}}}}}}}}}}}}}}s:1:\"p\";a:2:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8450;}}s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"d\";a:1:{s:1:\"u\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8720;}}}}}}}}s:1:\"u\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"C\";a:1:{s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"c\";a:1:{s:1:\"k\";a:1:{s:1:\"w\";a:1:{s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"C\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"u\";a:1:{s:1:\"r\";a:1:{s:1:\"I\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8755;}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"s\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10799;}}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119966;}}}}s:1:\"u\";a:1:{s:1:\"p\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8915;}s:1:\"C\";a:1:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8781;}}}}}}}s:1:\"D\";a:11:{s:1:\"D\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8517;}s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"h\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10513;}}}}}}}}s:1:\"J\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1026;}}}}s:1:\"S\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1029;}}}}s:1:\"Z\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1039;}}}}s:1:\"a\";a:3:{s:1:\"g\";a:1:{s:1:\"g\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8225;}}}}}s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8609;}}}s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10980;}}}}}s:1:\"c\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:270;}}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1044;}}}s:1:\"e\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8711;}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:916;}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120071;}}}s:1:\"i\";a:2:{s:1:\"a\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"c\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:4:{s:1:\"A\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:180;}}}}}}s:1:\"D\";a:1:{s:1:\"o\";a:2:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:729;}}s:1:\"u\";a:1:{s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"A\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:733;}}}}}}}}}}}}s:1:\"G\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:96;}}}}}}s:1:\"T\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:732;}}}}}}}}}}}}}}s:1:\"m\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8900;}}}}}}s:1:\"f\";a:1:{s:1:\"f\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"D\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8518;}}}}}}}}}}}}}s:1:\"o\";a:4:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120123;}}}s:1:\"t\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:168;}s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8412;}}}}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8784;}}}}}}}s:1:\"u\";a:1:{s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:6:{s:1:\"C\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"u\";a:1:{s:1:\"r\";a:1:{s:1:\"I\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8751;}}}}}}}}}}}}}}}}s:1:\"D\";a:1:{s:1:\"o\";a:2:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:168;}}s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8659;}}}}}}}}}}s:1:\"L\";a:2:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:3:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8656;}}}}}}s:1:\"R\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8660;}}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10980;}}}}}}}s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:2:{s:1:\"L\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:2:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10232;}}}}}}s:1:\"R\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10234;}}}}}}}}}}}}}}}s:1:\"R\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10233;}}}}}}}}}}}}}}}s:1:\"R\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:2:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8658;}}}}}}s:1:\"T\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8872;}}}}}}}}}s:1:\"U\";a:1:{s:1:\"p\";a:2:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8657;}}}}}}s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8661;}}}}}}}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"c\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8741;}}}}}}}}}}}}}}}}s:1:\"w\";a:1:{s:1:\"n\";a:6:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8595;}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10515;}}}}s:1:\"U\";a:1:{s:1:\"p\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8693;}}}}}}}}}}}}}s:1:\"B\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:785;}}}}}}s:1:\"L\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:3:{s:1:\"R\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10576;}}}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10590;}}}}}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8637;}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10582;}}}}}}}}}}}}}}s:1:\"R\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:2:{s:1:\"T\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10591;}}}}}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8641;}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10583;}}}}}}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8868;}s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8615;}}}}}}}}}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8659;}}}}}}}}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119967;}}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:272;}}}}}}}s:1:\"E\";a:16:{s:1:\"N\";a:1:{s:1:\"G\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:330;}}}s:1:\"T\";a:1:{s:1:\"H\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:208;}s:9:\"codepoint\";i:208;}}s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:201;}s:9:\"codepoint\";i:201;}}}}}s:1:\"c\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:282;}}}}}s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:202;}s:9:\"codepoint\";i:202;}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1069;}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:278;}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120072;}}}s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:200;}s:9:\"codepoint\";i:200;}}}}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8712;}}}}}}}s:1:\"m\";a:2:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:274;}}}}s:1:\"p\";a:1:{s:1:\"t\";a:1:{s:1:\"y\";a:2:{s:1:\"S\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"S\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9723;}}}}}}}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"y\";a:1:{s:1:\"S\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"S\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9643;}}}}}}}}}}}}}}}}}}}}s:1:\"o\";a:2:{s:1:\"g\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:280;}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120124;}}}}s:1:\"p\";a:1:{s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:917;}}}}}}}s:1:\"q\";a:1:{s:1:\"u\";a:2:{s:1:\"a\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10869;}s:1:\"T\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8770;}}}}}}}}s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8652;}}}}}}}}}}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8496;}}}s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10867;}}}}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:919;}}}s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:203;}s:9:\"codepoint\";i:203;}}}s:1:\"x\";a:2:{s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8707;}}}}}s:1:\"p\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8519;}}}}}}}}}}}}}s:1:\"F\";a:5:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1060;}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120073;}}}s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:2:{s:1:\"S\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"S\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9724;}}}}}}}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"y\";a:1:{s:1:\"S\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"S\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9642;}}}}}}}}}}}}}}}}}}}}}s:1:\"o\";a:3:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120125;}}}s:1:\"r\";a:1:{s:1:\"A\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8704;}}}}}s:1:\"u\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8497;}}}}}}}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8497;}}}}}s:1:\"G\";a:12:{s:1:\"J\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1027;}}}}s:1:\"T\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:62;}s:9:\"codepoint\";i:62;}s:1:\"a\";a:1:{s:1:\"m\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:915;}s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:988;}}}}}}s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:286;}}}}}}s:1:\"c\";a:3:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:290;}}}}}s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:284;}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1043;}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:288;}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120074;}}}s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8921;}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120126;}}}}s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:6:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8805;}s:1:\"L\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8923;}}}}}}}}}}s:1:\"F\";a:1:{s:1:\"u\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8807;}}}}}}}}}}s:1:\"G\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10914;}}}}}}}}s:1:\"L\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8823;}}}}}s:1:\"S\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10878;}}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8819;}}}}}}}}}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119970;}}}}s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8811;}}}s:1:\"H\";a:8:{s:1:\"A\";a:1:{s:1:\"R\";a:1:{s:1:\"D\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1066;}}}}}}s:1:\"a\";a:2:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:711;}}}}s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:94;}}}s:1:\"c\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:292;}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8460;}}}s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"b\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:1:{s:1:\"S\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8459;}}}}}}}}}}}}s:1:\"o\";a:2:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8461;}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"z\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"L\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9472;}}}}}}}}}}}}}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8459;}}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:294;}}}}}}s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\"p\";a:2:{s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\"H\";a:1:{s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8782;}}}}}}}}}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8783;}}}}}}}}}}s:1:\"I\";a:14:{s:1:\"E\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1045;}}}}s:1:\"J\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:306;}}}}}s:1:\"O\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1025;}}}}s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:205;}s:9:\"codepoint\";i:205;}}}}}s:1:\"c\";a:2:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:206;}s:9:\"codepoint\";i:206;}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1048;}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:304;}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8465;}}}s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:204;}s:9:\"codepoint\";i:204;}}}}}s:1:\"m\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8465;}s:1:\"a\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:298;}}}s:1:\"g\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"y\";a:1:{s:1:\"I\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8520;}}}}}}}}}s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8658;}}}}}}}s:1:\"n\";a:2:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8748;}s:1:\"e\";a:2:{s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8747;}}}}}s:1:\"r\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8898;}}}}}}}}}}}s:1:\"v\";a:1:{s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:2:{s:1:\"C\";a:1:{s:1:\"o\";a:1:{s:1:\"m\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8291;}}}}}}s:1:\"T\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8290;}}}}}}}}}}}}}}s:1:\"o\";a:3:{s:1:\"g\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:302;}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120128;}}}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:921;}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8464;}}}}s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:296;}}}}}}s:1:\"u\";a:2:{s:1:\"k\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1030;}}}}s:1:\"m\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:207;}s:9:\"codepoint\";i:207;}}}}s:1:\"J\";a:5:{s:1:\"c\";a:2:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:308;}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1049;}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120077;}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120129;}}}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119973;}}}s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1032;}}}}}}s:1:\"u\";a:1:{s:1:\"k\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1028;}}}}}}s:1:\"K\";a:7:{s:1:\"H\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1061;}}}}s:1:\"J\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1036;}}}}s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:922;}}}}}s:1:\"c\";a:2:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:310;}}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1050;}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120078;}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120130;}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119974;}}}}}s:1:\"L\";a:11:{s:1:\"J\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1033;}}}}s:1:\"T\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:60;}s:9:\"codepoint\";i:60;}s:1:\"a\";a:5:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:313;}}}}}s:1:\"m\";a:1:{s:1:\"b\";a:1:{s:1:\"d\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:923;}}}}}s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10218;}}}s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8466;}}}}}}}}}s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8606;}}}}s:1:\"c\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:317;}}}}}s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:315;}}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1051;}}}s:1:\"e\";a:2:{s:1:\"f\";a:1:{s:1:\"t\";a:10:{s:1:\"A\";a:2:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"B\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"k\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10216;}}}}}}}}}}}}s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8592;}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8676;}}}}s:1:\"R\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8646;}}}}}}}}}}}}}}}}s:1:\"C\";a:1:{s:1:\"e\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8968;}}}}}}}}s:1:\"D\";a:1:{s:1:\"o\";a:2:{s:1:\"u\";a:1:{s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"B\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"k\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10214;}}}}}}}}}}}}s:1:\"w\";a:1:{s:1:\"n\";a:2:{s:1:\"T\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10593;}}}}}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8643;}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10585;}}}}}}}}}}}}}}s:1:\"F\";a:1:{s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8970;}}}}}}s:1:\"R\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:2:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8596;}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10574;}}}}}}}}}}}}s:1:\"T\";a:2:{s:1:\"e\";a:1:{s:1:\"e\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8867;}s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8612;}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10586;}}}}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8882;}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10703;}}}}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8884;}}}}}}}}}}}}}}s:1:\"U\";a:1:{s:1:\"p\";a:3:{s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10577;}}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10592;}}}}}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8639;}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10584;}}}}}}}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8636;}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10578;}}}}}}}}}}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8656;}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8660;}}}}}}}}}}}}}s:1:\"s\";a:1:{s:1:\"s\";a:6:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"G\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8922;}}}}}}}}}}}}}s:1:\"F\";a:1:{s:1:\"u\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8806;}}}}}}}}}}s:1:\"G\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8822;}}}}}}}}s:1:\"L\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10913;}}}}}s:1:\"S\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10877;}}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8818;}}}}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120079;}}}s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8920;}s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8666;}}}}}}}}}}s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:319;}}}}}}s:1:\"o\";a:3:{s:1:\"n\";a:1:{s:1:\"g\";a:4:{s:1:\"L\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:2:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10229;}}}}}}s:1:\"R\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10231;}}}}}}}}}}}}}}}s:1:\"R\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10230;}}}}}}}}}}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10232;}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10234;}}}}}}}}}}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10233;}}}}}}}}}}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120131;}}}s:1:\"w\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:2:{s:1:\"L\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8601;}}}}}}}}}}s:1:\"R\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8600;}}}}}}}}}}}}}}}s:1:\"s\";a:3:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8466;}}}s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8624;}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:321;}}}}}}s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8810;}}}s:1:\"M\";a:8:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10501;}}}s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1052;}}}s:1:\"e\";a:2:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\"S\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8287;}}}}}}}}}}s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8499;}}}}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120080;}}}s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\"P\";a:1:{s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8723;}}}}}}}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120132;}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8499;}}}}s:1:\"u\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:924;}}}s:1:\"N\";a:9:{s:1:\"J\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1034;}}}}s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:323;}}}}}}s:1:\"c\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:327;}}}}}s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:325;}}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1053;}}}s:1:\"e\";a:3:{s:1:\"g\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:3:{s:1:\"M\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\"S\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8203;}}}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"h\";a:1:{s:1:\"i\";a:2:{s:1:\"c\";a:1:{s:1:\"k\";a:1:{s:1:\"S\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8203;}}}}}}}}s:1:\"n\";a:1:{s:1:\"S\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8203;}}}}}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"y\";a:1:{s:1:\"T\";a:1:{s:1:\"h\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"S\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8203;}}}}}}}}}}}}}}}}}}}}s:1:\"s\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:2:{s:1:\"G\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"G\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8811;}}}}}}}}}}}}}}}s:1:\"L\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"s\";a:1:{s:1:\"L\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8810;}}}}}}}}}}}}}s:1:\"w\";a:1:{s:1:\"L\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10;}}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120081;}}}s:1:\"o\";a:4:{s:1:\"B\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8288;}}}}}}s:1:\"n\";a:1:{s:1:\"B\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"k\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"S\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:160;}}}}}}}}}}}}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8469;}}}s:1:\"t\";a:11:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10988;}s:1:\"C\";a:2:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"u\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8802;}}}}}}}}}s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\"C\";a:1:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8813;}}}}}}}s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"u\";a:1:{s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"c\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8742;}}}}}}}}}}}}}}}}}}s:1:\"E\";a:3:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8713;}}}}}}}s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8800;}}}}}s:1:\"x\";a:1:{s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8708;}}}}}}}s:1:\"G\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8815;}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8817;}}}}}}s:1:\"L\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8825;}}}}}s:1:\"T\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8821;}}}}}}}}}}}}}s:1:\"L\";a:1:{s:1:\"e\";a:2:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\"T\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8938;}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8940;}}}}}}}}}}}}}}}}s:1:\"s\";a:1:{s:1:\"s\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8814;}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8816;}}}}}}s:1:\"G\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8824;}}}}}}}}s:1:\"T\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8820;}}}}}}}}}}s:1:\"P\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8832;}s:1:\"S\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8928;}}}}}}}}}}}}}}}}}}}s:1:\"R\";a:2:{s:1:\"e\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"E\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8716;}}}}}}}}}}}}}}s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"T\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8939;}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8941;}}}}}}}}}}}}}}}}}}}s:1:\"S\";a:2:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"S\";a:1:{s:1:\"u\";a:2:{s:1:\"b\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8930;}}}}}}}}}}s:1:\"p\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8931;}}}}}}}}}}}}}}}}}}}s:1:\"u\";a:3:{s:1:\"b\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8840;}}}}}}}}}}s:1:\"c\";a:1:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"s\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8833;}s:1:\"S\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8929;}}}}}}}}}}}}}}}}}s:1:\"p\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8841;}}}}}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8769;}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8772;}}}}}}s:1:\"F\";a:1:{s:1:\"u\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8775;}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8777;}}}}}}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"c\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8740;}}}}}}}}}}}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119977;}}}}s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:209;}s:9:\"codepoint\";i:209;}}}}}s:1:\"u\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:925;}}}s:1:\"O\";a:14:{s:1:\"E\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:338;}}}}}s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:211;}s:9:\"codepoint\";i:211;}}}}}s:1:\"c\";a:2:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:212;}s:9:\"codepoint\";i:212;}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1054;}}}s:1:\"d\";a:1:{s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:336;}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120082;}}}s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:210;}s:9:\"codepoint\";i:210;}}}}}s:1:\"m\";a:3:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:332;}}}}s:1:\"e\";a:1:{s:1:\"g\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:937;}}}}s:1:\"i\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:927;}}}}}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120134;}}}}s:1:\"p\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"C\";a:1:{s:1:\"u\";a:1:{s:1:\"r\";a:1:{s:1:\"l\";a:1:{s:1:\"y\";a:2:{s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"u\";a:1:{s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"Q\";a:1:{s:1:\"u\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8220;}}}}}}}}}}}}s:1:\"Q\";a:1:{s:1:\"u\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8216;}}}}}}}}}}}}}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10836;}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119978;}}}s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:216;}s:9:\"codepoint\";i:216;}}}}}s:1:\"t\";a:1:{s:1:\"i\";a:2:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:213;}s:9:\"codepoint\";i:213;}}}s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10807;}}}}}}s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:214;}s:9:\"codepoint\";i:214;}}}s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:2:{s:1:\"B\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:175;}}}s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:2:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9182;}}s:1:\"k\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9140;}}}}}}}}s:1:\"P\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"h\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9180;}}}}}}}}}}}}}}}}s:1:\"P\";a:9:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"D\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8706;}}}}}}}}s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1055;}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120083;}}}s:1:\"h\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:934;}}}s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:928;}}s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\"M\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:177;}}}}}}}}}s:1:\"o\";a:2:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"c\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8460;}}}}}}}}}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8473;}}}}s:1:\"r\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10939;}s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8826;}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10927;}}}}}}s:1:\"S\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8828;}}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8830;}}}}}}}}}}}}s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8243;}}}}s:1:\"o\";a:2:{s:1:\"d\";a:1:{s:1:\"u\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8719;}}}}}s:1:\"p\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8759;}s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8733;}}}}}}}}}}}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119979;}}}s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:936;}}}}s:1:\"Q\";a:4:{s:1:\"U\";a:1:{s:1:\"O\";a:1:{s:1:\"T\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:34;}s:9:\"codepoint\";i:34;}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120084;}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8474;}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119980;}}}}}s:1:\"R\";a:12:{s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10512;}}}}}s:1:\"E\";a:1:{s:1:\"G\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:174;}s:9:\"codepoint\";i:174;}}s:1:\"a\";a:3:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:340;}}}}}s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10219;}}}s:1:\"r\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8608;}s:1:\"t\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10518;}}}}}}s:1:\"c\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:344;}}}}}s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:342;}}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1056;}}}s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8476;}s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:2:{s:1:\"E\";a:2:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8715;}}}}}}}s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8651;}}}}}}}}}}}}s:1:\"U\";a:1:{s:1:\"p\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10607;}}}}}}}}}}}}}}}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8476;}}}s:1:\"h\";a:1:{s:1:\"o\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:929;}}}s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:8:{s:1:\"A\";a:2:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"B\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"k\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10217;}}}}}}}}}}}}s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8594;}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8677;}}}}s:1:\"L\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8644;}}}}}}}}}}}}}}}s:1:\"C\";a:1:{s:1:\"e\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8969;}}}}}}}}s:1:\"D\";a:1:{s:1:\"o\";a:2:{s:1:\"u\";a:1:{s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"B\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"k\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10215;}}}}}}}}}}}}s:1:\"w\";a:1:{s:1:\"n\";a:2:{s:1:\"T\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10589;}}}}}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8642;}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10581;}}}}}}}}}}}}}}s:1:\"F\";a:1:{s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8971;}}}}}}s:1:\"T\";a:2:{s:1:\"e\";a:1:{s:1:\"e\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8866;}s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8614;}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10587;}}}}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8883;}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10704;}}}}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8885;}}}}}}}}}}}}}}s:1:\"U\";a:1:{s:1:\"p\";a:3:{s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10575;}}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10588;}}}}}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8638;}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10580;}}}}}}}}}}}}s:1:\"V\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8640;}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10579;}}}}}}}}}}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8658;}}}}}}}}}}s:1:\"o\";a:2:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8477;}}}s:1:\"u\";a:1:{s:1:\"n\";a:1:{s:1:\"d\";a:1:{s:1:\"I\";a:1:{s:1:\"m\";a:1:{s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10608;}}}}}}}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8667;}}}}}}}}}}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8475;}}}s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8625;}}}s:1:\"u\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"D\";a:1:{s:1:\"e\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"y\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10740;}}}}}}}}}}}}s:1:\"S\";a:13:{s:1:\"H\";a:2:{s:1:\"C\";a:1:{s:1:\"H\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1065;}}}}}s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1064;}}}}s:1:\"O\";a:1:{s:1:\"F\";a:1:{s:1:\"T\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1068;}}}}}}s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:346;}}}}}}s:1:\"c\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10940;}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:352;}}}}}s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:350;}}}}}s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:348;}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1057;}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120086;}}}s:1:\"h\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:4:{s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8595;}}}}}}}}}}s:1:\"L\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8592;}}}}}}}}}}s:1:\"R\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8594;}}}}}}}}}}}s:1:\"U\";a:1:{s:1:\"p\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8593;}}}}}}}}}}}}s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:931;}}}}}s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"C\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8728;}}}}}}}}}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120138;}}}}s:1:\"q\";a:2:{s:1:\"r\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8730;}}}s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9633;}s:1:\"I\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8851;}}}}}}}}}}}}}s:1:\"S\";a:1:{s:1:\"u\";a:2:{s:1:\"b\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8847;}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8849;}}}}}}}}}}s:1:\"p\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8848;}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8850;}}}}}}}}}}}}}}s:1:\"U\";a:1:{s:1:\"n\";a:1:{s:1:\"i\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8852;}}}}}}}}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119982;}}}}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8902;}}}}s:1:\"u\";a:4:{s:1:\"b\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8912;}s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8912;}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8838;}}}}}}}}}}s:1:\"c\";a:2:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"s\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8827;}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10928;}}}}}}s:1:\"S\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8829;}}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8831;}}}}}}}}}}}s:1:\"h\";a:1:{s:1:\"T\";a:1:{s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8715;}}}}}}}s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8721;}}s:1:\"p\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8913;}s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8835;}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8839;}}}}}}}}}}}s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8913;}}}}}}}s:1:\"T\";a:11:{s:1:\"H\";a:1:{s:1:\"O\";a:1:{s:1:\"R\";a:1:{s:1:\"N\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:222;}s:9:\"codepoint\";i:222;}}}}s:1:\"R\";a:1:{s:1:\"A\";a:1:{s:1:\"D\";a:1:{s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8482;}}}}}s:1:\"S\";a:2:{s:1:\"H\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1035;}}}}s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1062;}}}}s:1:\"a\";a:2:{s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9;}}s:1:\"u\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:932;}}}s:1:\"c\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:356;}}}}}s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:354;}}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1058;}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120087;}}}s:1:\"h\";a:2:{s:1:\"e\";a:2:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8756;}}}}}}}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:920;}}}}s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"S\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8201;}}}}}}}}}s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8764;}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8771;}}}}}}s:1:\"F\";a:1:{s:1:\"u\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8773;}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8776;}}}}}}}}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120139;}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8411;}}}}}}}}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119983;}}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:358;}}}}}}}s:1:\"U\";a:14:{s:1:\"a\";a:2:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:218;}s:9:\"codepoint\";i:218;}}}}s:1:\"r\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8607;}s:1:\"o\";a:1:{s:1:\"c\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10569;}}}}}}}}s:1:\"b\";a:1:{s:1:\"r\";a:2:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1038;}}}s:1:\"e\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:364;}}}}}}s:1:\"c\";a:2:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:219;}s:9:\"codepoint\";i:219;}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1059;}}}s:1:\"d\";a:1:{s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:368;}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120088;}}}s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:217;}s:9:\"codepoint\";i:217;}}}}}s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:362;}}}}}s:1:\"n\";a:2:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:2:{s:1:\"B\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:818;}}}s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:2:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9183;}}s:1:\"k\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9141;}}}}}}}}s:1:\"P\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"h\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9181;}}}}}}}}}}}}}}}s:1:\"i\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8899;}s:1:\"P\";a:1:{s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8846;}}}}}}}}}s:1:\"o\";a:2:{s:1:\"g\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:370;}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120140;}}}}s:1:\"p\";a:8:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8593;}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10514;}}}}s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8645;}}}}}}}}}}}}}}}s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8597;}}}}}}}}}}s:1:\"E\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10606;}}}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8869;}s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8613;}}}}}}}}}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8657;}}}}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8661;}}}}}}}}}}s:1:\"p\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:2:{s:1:\"L\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8598;}}}}}}}}}}s:1:\"R\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8599;}}}}}}}}}}}}}}s:1:\"s\";a:1:{s:1:\"i\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:978;}s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:933;}}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:366;}}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119984;}}}}s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:360;}}}}}}s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:220;}s:9:\"codepoint\";i:220;}}}}s:1:\"V\";a:9:{s:1:\"D\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8875;}}}}}s:1:\"b\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10987;}}}}s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1042;}}}s:1:\"d\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8873;}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10982;}}}}}}s:1:\"e\";a:2:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8897;}}s:1:\"r\";a:3:{s:1:\"b\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8214;}}}}s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8214;}s:1:\"i\";a:1:{s:1:\"c\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:4:{s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8739;}}}}s:1:\"L\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:124;}}}}}s:1:\"S\";a:1:{s:1:\"e\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10072;}}}}}}}}}}s:1:\"T\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8768;}}}}}}}}}}}s:1:\"y\";a:1:{s:1:\"T\";a:1:{s:1:\"h\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"S\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8202;}}}}}}}}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120089;}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120141;}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119985;}}}}s:1:\"v\";a:1:{s:1:\"d\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8874;}}}}}}}s:1:\"W\";a:5:{s:1:\"c\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:372;}}}}}s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"g\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8896;}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120090;}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120142;}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119986;}}}}}s:1:\"X\";a:4:{s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120091;}}}s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:926;}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120143;}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119987;}}}}}s:1:\"Y\";a:9:{s:1:\"A\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1071;}}}}s:1:\"I\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1031;}}}}s:1:\"U\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1070;}}}}s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:221;}s:9:\"codepoint\";i:221;}}}}}s:1:\"c\";a:2:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:374;}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1067;}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120092;}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120144;}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119988;}}}}s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:376;}}}}}s:1:\"Z\";a:8:{s:1:\"H\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1046;}}}}s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:377;}}}}}}s:1:\"c\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:381;}}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1047;}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:379;}}}}s:1:\"e\";a:2:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"W\";a:1:{s:1:\"i\";a:1:{s:1:\"d\";a:1:{s:1:\"t\";a:1:{s:1:\"h\";a:1:{s:1:\"S\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8203;}}}}}}}}}}}}}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:918;}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8488;}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8484;}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119989;}}}}}s:1:\"a\";a:16:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:225;}s:9:\"codepoint\";i:225;}}}}}s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:259;}}}}}}s:1:\"c\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8766;}s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8767;}}s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:226;}s:9:\"codepoint\";i:226;}}}s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:180;}s:9:\"codepoint\";i:180;}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1072;}}}s:1:\"e\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:230;}s:9:\"codepoint\";i:230;}}}}s:1:\"f\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8289;}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120094;}}}s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:224;}s:9:\"codepoint\";i:224;}}}}}s:1:\"l\";a:2:{s:1:\"e\";a:2:{s:1:\"f\";a:1:{s:1:\"s\";a:1:{s:1:\"y\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8501;}}}}}s:1:\"p\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8501;}}}}s:1:\"p\";a:1:{s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:945;}}}}}s:1:\"m\";a:2:{s:1:\"a\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:257;}}}s:1:\"l\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10815;}}}}s:1:\"p\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:38;}s:9:\"codepoint\";i:38;}}s:1:\"n\";a:2:{s:1:\"d\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8743;}s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10837;}}}}s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10844;}}s:1:\"s\";a:1:{s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10840;}}}}}}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10842;}}}s:1:\"g\";a:7:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8736;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10660;}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8736;}}}s:1:\"m\";a:1:{s:1:\"s\";a:1:{s:1:\"d\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8737;}s:1:\"a\";a:8:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10664;}}s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10665;}}s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10666;}}s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10667;}}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10668;}}s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10669;}}s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10670;}}s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10671;}}}}}}s:1:\"r\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8735;}s:1:\"v\";a:1:{s:1:\"b\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8894;}s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10653;}}}}}}s:1:\"s\";a:2:{s:1:\"p\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8738;}}}s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8491;}}}s:1:\"z\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9084;}}}}}}}s:1:\"o\";a:2:{s:1:\"g\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:261;}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120146;}}}}s:1:\"p\";a:7:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8776;}s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10864;}}s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10863;}}}}}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8778;}}s:1:\"i\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8779;}}}s:1:\"o\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:39;}}}s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"x\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8776;}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8778;}}}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:229;}s:9:\"codepoint\";i:229;}}}}s:1:\"s\";a:3:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119990;}}}s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:42;}}s:1:\"y\";a:1:{s:1:\"m\";a:1:{s:1:\"p\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8776;}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8781;}}}}}}}s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:227;}s:9:\"codepoint\";i:227;}}}}}s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:228;}s:9:\"codepoint\";i:228;}}}s:1:\"w\";a:2:{s:1:\"c\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8755;}}}}}}}s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10769;}}}}}}s:1:\"b\";a:16:{s:1:\"N\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10989;}}}}s:1:\"a\";a:2:{s:1:\"c\";a:1:{s:1:\"k\";a:4:{s:1:\"c\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8780;}}}}}s:1:\"e\";a:1:{s:1:\"p\";a:1:{s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1014;}}}}}}}}s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8245;}}}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8765;}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8909;}}}}}}}}s:1:\"r\";a:2:{s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8893;}}}}s:1:\"w\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8965;}s:1:\"g\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8965;}}}}}}}}s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"k\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9141;}s:1:\"t\";a:1:{s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9142;}}}}}}}}s:1:\"c\";a:2:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8780;}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1073;}}}s:1:\"d\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"o\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8222;}}}}}s:1:\"e\";a:5:{s:1:\"c\";a:1:{s:1:\"a\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8757;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8757;}}}}}}s:1:\"m\";a:1:{s:1:\"p\";a:1:{s:1:\"t\";a:1:{s:1:\"y\";a:1:{s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10672;}}}}}}s:1:\"p\";a:1:{s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1014;}}}}s:1:\"r\";a:1:{s:1:\"n\";a:1:{s:1:\"o\";a:1:{s:1:\"u\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8492;}}}}}s:1:\"t\";a:3:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:946;}}s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8502;}}s:1:\"w\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8812;}}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120095;}}}s:1:\"i\";a:1:{s:1:\"g\";a:7:{s:1:\"c\";a:3:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8898;}}}s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9711;}}}}s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8899;}}}}s:1:\"o\";a:3:{s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10752;}}}}s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10753;}}}}}s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10754;}}}}}}}s:1:\"s\";a:2:{s:1:\"q\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10758;}}}}}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9733;}}}}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:2:{s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9661;}}}}}s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9651;}}}}}}}}}}}s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10756;}}}}}}s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8897;}}}}s:1:\"w\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"g\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8896;}}}}}}}}s:1:\"k\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10509;}}}}}}s:1:\"l\";a:3:{s:1:\"a\";a:2:{s:1:\"c\";a:1:{s:1:\"k\";a:3:{s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"z\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10731;}}}}}}}}s:1:\"s\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9642;}}}}}}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9652;}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9662;}}}}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9666;}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9656;}}}}}}}}}}}}}}}}s:1:\"n\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9251;}}}}s:1:\"k\";a:2:{i:1;a:2:{i:2;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9618;}}i:4;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9617;}}}i:3;a:1:{i:4;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9619;}}}}s:1:\"o\";a:1:{s:1:\"c\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9608;}}}}}s:1:\"n\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8976;}}}}s:1:\"o\";a:4:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120147;}}}s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8869;}s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8869;}}}}}s:1:\"w\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8904;}}}}}s:1:\"x\";a:12:{s:1:\"D\";a:4:{s:1:\"L\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9559;}}s:1:\"R\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9556;}}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9558;}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9555;}}}s:1:\"H\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9552;}s:1:\"D\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9574;}}s:1:\"U\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9577;}}s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9572;}}s:1:\"u\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9575;}}}s:1:\"U\";a:4:{s:1:\"L\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9565;}}s:1:\"R\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9562;}}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9564;}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9561;}}}s:1:\"V\";a:7:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9553;}s:1:\"H\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9580;}}s:1:\"L\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9571;}}s:1:\"R\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9568;}}s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9579;}}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9570;}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9567;}}}s:1:\"b\";a:1:{s:1:\"o\";a:1:{s:1:\"x\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10697;}}}}s:1:\"d\";a:4:{s:1:\"L\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9557;}}s:1:\"R\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9554;}}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9488;}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9484;}}}s:1:\"h\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9472;}s:1:\"D\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9573;}}s:1:\"U\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9576;}}s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9516;}}s:1:\"u\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9524;}}}s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8863;}}}}}}s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8862;}}}}}s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8864;}}}}}}s:1:\"u\";a:4:{s:1:\"L\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9563;}}s:1:\"R\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9560;}}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9496;}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9492;}}}s:1:\"v\";a:7:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9474;}s:1:\"H\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9578;}}s:1:\"L\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9569;}}s:1:\"R\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9566;}}s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9532;}}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9508;}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9500;}}}}}s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8245;}}}}}}s:1:\"r\";a:2:{s:1:\"e\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:728;}}}}s:1:\"v\";a:1:{s:1:\"b\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:166;}s:9:\"codepoint\";i:166;}}}}}s:1:\"s\";a:4:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119991;}}}s:1:\"e\";a:1:{s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8271;}}}}s:1:\"i\";a:1:{s:1:\"m\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8765;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8909;}}}}s:1:\"o\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:92;}s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10693;}}}}}s:1:\"u\";a:2:{s:1:\"l\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8226;}s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8226;}}}}}s:1:\"m\";a:1:{s:1:\"p\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8782;}s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10926;}}s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8783;}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8783;}}}}}}}s:1:\"c\";a:15:{s:1:\"a\";a:3:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:263;}}}}}s:1:\"p\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8745;}s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10820;}}}}s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10825;}}}}}}s:1:\"c\";a:2:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10827;}}}s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10823;}}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10816;}}}}}s:1:\"r\";a:2:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8257;}}}s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:711;}}}}}s:1:\"c\";a:4:{s:1:\"a\";a:2:{s:1:\"p\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10829;}}}s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:269;}}}}}s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:231;}s:9:\"codepoint\";i:231;}}}}s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:265;}}}}s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\"s\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10828;}s:1:\"s\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10832;}}}}}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:267;}}}}s:1:\"e\";a:3:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:184;}s:9:\"codepoint\";i:184;}}}s:1:\"m\";a:1:{s:1:\"p\";a:1:{s:1:\"t\";a:1:{s:1:\"y\";a:1:{s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10674;}}}}}}s:1:\"n\";a:1:{s:1:\"t\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:162;}s:9:\"codepoint\";i:162;s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:183;}}}}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120096;}}}s:1:\"h\";a:3:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1095;}}}s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"k\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10003;}s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10003;}}}}}}}}s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:967;}}}s:1:\"i\";a:1:{s:1:\"r\";a:7:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9675;}s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10691;}}s:1:\"c\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:710;}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8791;}}}s:1:\"l\";a:1:{s:1:\"e\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:2:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8634;}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8635;}}}}}}}}}}}s:1:\"d\";a:5:{s:1:\"R\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:174;}}s:1:\"S\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9416;}}s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8859;}}}}s:1:\"c\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8858;}}}}}s:1:\"d\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8861;}}}}}}}}}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8791;}}s:1:\"f\";a:1:{s:1:\"n\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10768;}}}}}}s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10991;}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10690;}}}}}}}s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"b\";a:1:{s:1:\"s\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9827;}s:1:\"u\";a:1:{s:1:\"i\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9827;}}}}}}}}s:1:\"o\";a:4:{s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:58;}s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8788;}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8788;}}}}}}s:1:\"m\";a:2:{s:1:\"m\";a:1:{s:1:\"a\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:44;}s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:64;}}}}s:1:\"p\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8705;}s:1:\"f\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8728;}}}s:1:\"l\";a:1:{s:1:\"e\";a:2:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8705;}}}}}s:1:\"x\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8450;}}}}}}}}s:1:\"n\";a:2:{s:1:\"g\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8773;}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10861;}}}}}s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8750;}}}}}s:1:\"p\";a:3:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120148;}}s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8720;}}}}s:1:\"y\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:169;}s:9:\"codepoint\";i:169;s:1:\"s\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8471;}}}}}}s:1:\"r\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8629;}}}}s:1:\"o\";a:1:{s:1:\"s\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10007;}}}}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119992;}}}s:1:\"u\";a:2:{s:1:\"b\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10959;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10961;}}}s:1:\"p\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10960;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10962;}}}}}s:1:\"t\";a:1:{s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8943;}}}}}s:1:\"u\";a:7:{s:1:\"d\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:2:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10552;}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10549;}}}}}}s:1:\"e\";a:2:{s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8926;}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8927;}}}}s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8630;}s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10557;}}}}}}s:1:\"p\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8746;}s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10824;}}}}}}s:1:\"c\";a:2:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10822;}}}s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10826;}}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8845;}}}}s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10821;}}}}s:1:\"r\";a:4:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8631;}s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10556;}}}}}s:1:\"l\";a:1:{s:1:\"y\";a:3:{s:1:\"e\";a:1:{s:1:\"q\";a:2:{s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8926;}}}}}s:1:\"s\";a:1:{s:1:\"u\";a:1:{s:1:\"c\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8927;}}}}}}}s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8910;}}}}s:1:\"w\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"g\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8911;}}}}}}}}s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:164;}s:9:\"codepoint\";i:164;}}}s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:2:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8630;}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8631;}}}}}}}}}}}}}}s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8910;}}}}s:1:\"w\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8911;}}}}}s:1:\"w\";a:2:{s:1:\"c\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8754;}}}}}}}s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8753;}}}}}s:1:\"y\";a:1:{s:1:\"l\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9005;}}}}}}}s:1:\"d\";a:19:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8659;}}}}s:1:\"H\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10597;}}}}s:1:\"a\";a:4:{s:1:\"g\";a:1:{s:1:\"g\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8224;}}}}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8504;}}}}}s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8595;}}}s:1:\"s\";a:1:{s:1:\"h\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8208;}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8867;}}}}}s:1:\"b\";a:2:{s:1:\"k\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10511;}}}}}}s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:733;}}}}}s:1:\"c\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:271;}}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1076;}}}s:1:\"d\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8518;}s:1:\"a\";a:2:{s:1:\"g\";a:1:{s:1:\"g\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8225;}}}}}s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8650;}}}}s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10871;}}}}}}}s:1:\"e\";a:3:{s:1:\"g\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:176;}s:9:\"codepoint\";i:176;}s:1:\"l\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:948;}}}}s:1:\"m\";a:1:{s:1:\"p\";a:1:{s:1:\"t\";a:1:{s:1:\"y\";a:1:{s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10673;}}}}}}}s:1:\"f\";a:2:{s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10623;}}}}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120097;}}}s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8643;}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8642;}}}}}s:1:\"i\";a:5:{s:1:\"a\";a:1:{s:1:\"m\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8900;}s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"d\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8900;}s:1:\"s\";a:1:{s:1:\"u\";a:1:{s:1:\"i\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9830;}}}}}}}}s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9830;}}}}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:168;}}s:1:\"g\";a:1:{s:1:\"a\";a:1:{s:1:\"m\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:989;}}}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8946;}}}}s:1:\"v\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:247;}s:1:\"i\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:247;}s:9:\"codepoint\";i:247;s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8903;}}}}}}}}}}}s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"x\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8903;}}}}}}s:1:\"j\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1106;}}}}s:1:\"l\";a:1:{s:1:\"c\";a:2:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8990;}}}}s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8973;}}}}}}s:1:\"o\";a:5:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:36;}}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120149;}}}s:1:\"t\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:729;}s:1:\"e\";a:1:{s:1:\"q\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8784;}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8785;}}}}}}s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8760;}}}}}}s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8724;}}}}}s:1:\"s\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8865;}}}}}}}}s:1:\"u\";a:1:{s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"b\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"w\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"g\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8966;}}}}}}}}}}}}}s:1:\"w\";a:1:{s:1:\"n\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8595;}}}}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8650;}}}}}}}}}}}s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"p\";a:1:{s:1:\"o\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:2:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8643;}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8642;}}}}}}}}}}}}}}}}s:1:\"r\";a:2:{s:1:\"b\";a:1:{s:1:\"k\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10512;}}}}}}}s:1:\"c\";a:2:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8991;}}}}s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8972;}}}}}}s:1:\"s\";a:3:{s:1:\"c\";a:2:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119993;}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1109;}}}s:1:\"o\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10742;}}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:273;}}}}}}s:1:\"t\";a:2:{s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8945;}}}}s:1:\"r\";a:1:{s:1:\"i\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9663;}s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9662;}}}}}s:1:\"u\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8693;}}}}s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10607;}}}}}s:1:\"w\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10662;}}}}}}}s:1:\"z\";a:2:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1119;}}}s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10239;}}}}}}}}}s:1:\"e\";a:18:{s:1:\"D\";a:2:{s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10871;}}}}s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8785;}}}}s:1:\"a\";a:2:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:233;}s:9:\"codepoint\";i:233;}}}}s:1:\"s\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10862;}}}}}}s:1:\"c\";a:4:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:283;}}}}}s:1:\"i\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8790;}s:1:\"c\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:234;}s:9:\"codepoint\";i:234;}}}s:1:\"o\";a:1:{s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8789;}}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1101;}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:279;}}}}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8519;}}s:1:\"f\";a:2:{s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8786;}}}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120098;}}}s:1:\"g\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10906;}s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:232;}s:9:\"codepoint\";i:232;}}}}s:1:\"s\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10902;}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10904;}}}}}}s:1:\"l\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10905;}s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9191;}}}}}}}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8467;}}s:1:\"s\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10901;}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10903;}}}}}}s:1:\"m\";a:3:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:275;}}}}s:1:\"p\";a:1:{s:1:\"t\";a:1:{s:1:\"y\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8709;}s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8709;}}}}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8709;}}}}}s:1:\"s\";a:1:{s:1:\"p\";a:2:{i:1;a:2:{i:3;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8196;}}i:4;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8197;}}}s:1:\";\";a:1:{s:9:\"codepoint\";i:8195;}}}}s:1:\"n\";a:2:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:331;}}s:1:\"s\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8194;}}}}s:1:\"o\";a:2:{s:1:\"g\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:281;}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120150;}}}}s:1:\"p\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8917;}s:1:\"s\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10723;}}}}}s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10865;}}}}s:1:\"s\";a:1:{s:1:\"i\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1013;}s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:949;}}}}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:949;}}}}}s:1:\"q\";a:4:{s:1:\"c\";a:2:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8790;}}}}s:1:\"o\";a:1:{s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8789;}}}}}}s:1:\"s\";a:2:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8770;}}}s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:2:{s:1:\"g\";a:1:{s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10902;}}}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10901;}}}}}}}}}}s:1:\"u\";a:3:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:61;}}}}s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8799;}}}}s:1:\"i\";a:1:{s:1:\"v\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8801;}s:1:\"D\";a:1:{s:1:\"D\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10872;}}}}}}s:1:\"v\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"s\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10725;}}}}}}}}s:1:\"r\";a:2:{s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8787;}}}}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10609;}}}}}s:1:\"s\";a:3:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8495;}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8784;}}}}s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8770;}}}}s:1:\"t\";a:2:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:951;}}s:1:\"h\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:240;}s:9:\"codepoint\";i:240;}}s:1:\"u\";a:2:{s:1:\"m\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:235;}s:9:\"codepoint\";i:235;}}s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8364;}}}}s:1:\"x\";a:3:{s:1:\"c\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:33;}}}s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8707;}}}}s:1:\"p\";a:2:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8496;}}}}}}}}}s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8519;}}}}}}}}}}}}}s:1:\"f\";a:11:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8786;}}}}}}}}}}}}}s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1092;}}}s:1:\"e\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9792;}}}}}}s:1:\"f\";a:3:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:64259;}}}}}s:1:\"l\";a:2:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:64256;}}}s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:64260;}}}}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120099;}}}s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:64257;}}}}}s:1:\"l\";a:3:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9837;}}}s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:64258;}}}}s:1:\"t\";a:1:{s:1:\"n\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9649;}}}}}s:1:\"n\";a:1:{s:1:\"o\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:402;}}}}s:1:\"o\";a:2:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120151;}}}s:1:\"r\";a:2:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8704;}}}}s:1:\"k\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8916;}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10969;}}}}}s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10765;}}}}}}}}s:1:\"r\";a:2:{s:1:\"a\";a:2:{s:1:\"c\";a:6:{i:1;a:6:{i:2;a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:189;}s:9:\"codepoint\";i:189;}i:3;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8531;}}i:4;a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:188;}s:9:\"codepoint\";i:188;}i:5;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8533;}}i:6;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8537;}}i:8;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8539;}}}i:2;a:2:{i:3;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8532;}}i:5;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8534;}}}i:3;a:3:{i:4;a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:190;}s:9:\"codepoint\";i:190;}i:5;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8535;}}i:8;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8540;}}}i:4;a:1:{i:5;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8536;}}}i:5;a:2:{i:6;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8538;}}i:8;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8541;}}}i:7;a:1:{i:8;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8542;}}}}s:1:\"s\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8260;}}}}s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8994;}}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119995;}}}}}s:1:\"g\";a:16:{s:1:\"E\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8807;}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10892;}}}s:1:\"a\";a:3:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:501;}}}}}s:1:\"m\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:947;}s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:989;}}}}}s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10886;}}}s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:287;}}}}}}s:1:\"c\";a:2:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:285;}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1075;}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:289;}}}}s:1:\"e\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8805;}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8923;}}s:1:\"q\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8805;}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8807;}}s:1:\"s\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10878;}}}}}}}s:1:\"s\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10878;}s:1:\"c\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10921;}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10880;}s:1:\"o\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10882;}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10884;}}}}}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10900;}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120100;}}}s:1:\"g\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8811;}s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8921;}}}s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8503;}}}}}s:1:\"j\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1107;}}}}s:1:\"l\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8823;}s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10898;}}s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10917;}}s:1:\"j\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10916;}}}s:1:\"n\";a:4:{s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8809;}}s:1:\"a\";a:1:{s:1:\"p\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10890;}s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"x\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10890;}}}}}}}s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10888;}s:1:\"q\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10888;}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8809;}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8935;}}}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120152;}}}}s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:96;}}}}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8458;}}}s:1:\"i\";a:1:{s:1:\"m\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8819;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10894;}}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10896;}}}}}s:1:\"t\";a:7:{s:1:\";\";a:1:{s:9:\"codepoint\";i:62;}s:9:\"codepoint\";i:62;s:1:\"c\";a:2:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10919;}}s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10874;}}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8919;}}}}s:1:\"l\";a:1:{s:1:\"P\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10645;}}}}}s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10876;}}}}}}s:1:\"r\";a:5:{s:1:\"a\";a:2:{s:1:\"p\";a:1:{s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"x\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10886;}}}}}}s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10616;}}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8919;}}}}s:1:\"e\";a:1:{s:1:\"q\";a:2:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8923;}}}}}s:1:\"q\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10892;}}}}}}}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8823;}}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8819;}}}}}}}s:1:\"h\";a:10:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8660;}}}}s:1:\"a\";a:4:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"s\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8202;}}}}}s:1:\"l\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:189;}}}s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8459;}}}}}s:1:\"r\";a:2:{s:1:\"d\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1098;}}}}s:1:\"r\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8596;}s:1:\"c\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10568;}}}}s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8621;}}}}}s:1:\"b\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8463;}}}}s:1:\"c\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:293;}}}}}s:1:\"e\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:1:{s:1:\"s\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9829;}s:1:\"u\";a:1:{s:1:\"i\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9829;}}}}}}}}s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8230;}}}}}s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8889;}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120101;}}}s:1:\"k\";a:1:{s:1:\"s\";a:2:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10533;}}}}}}s:1:\"w\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10534;}}}}}}}}s:1:\"o\";a:5:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8703;}}}}s:1:\"m\";a:1:{s:1:\"t\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8763;}}}}}s:1:\"o\";a:1:{s:1:\"k\";a:2:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8617;}}}}}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8618;}}}}}}}}}}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120153;}}}s:1:\"r\";a:1:{s:1:\"b\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8213;}}}}}}s:1:\"s\";a:3:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119997;}}}s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8463;}}}}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:295;}}}}}}s:1:\"y\";a:2:{s:1:\"b\";a:1:{s:1:\"u\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8259;}}}}}s:1:\"p\";a:1:{s:1:\"h\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8208;}}}}}}}s:1:\"i\";a:15:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:237;}s:9:\"codepoint\";i:237;}}}}}s:1:\"c\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8291;}s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:238;}s:9:\"codepoint\";i:238;}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1080;}}}s:1:\"e\";a:2:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1077;}}}s:1:\"x\";a:1:{s:1:\"c\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:161;}s:9:\"codepoint\";i:161;}}}}s:1:\"f\";a:2:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8660;}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120102;}}}s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:236;}s:9:\"codepoint\";i:236;}}}}}s:1:\"i\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8520;}s:1:\"i\";a:2:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10764;}}}}s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8749;}}}}s:1:\"n\";a:1:{s:1:\"f\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10716;}}}}}s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8489;}}}}}s:1:\"j\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:307;}}}}}s:1:\"m\";a:3:{s:1:\"a\";a:3:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:299;}}}s:1:\"g\";a:3:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8465;}}s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8464;}}}}}s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8465;}}}}}}s:1:\"t\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:305;}}}}s:1:\"o\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8887;}}}s:1:\"p\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:437;}}}}}s:1:\"n\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8712;}s:1:\"c\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8453;}}}}}s:1:\"f\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8734;}s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10717;}}}}}}}s:1:\"o\";a:1:{s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:305;}}}}}s:1:\"t\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8747;}s:1:\"c\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8890;}}}}s:1:\"e\";a:2:{s:1:\"g\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8484;}}}}}s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8890;}}}}}}s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"h\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10775;}}}}}}s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10812;}}}}}}}s:1:\"o\";a:4:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1105;}}}s:1:\"g\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:303;}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120154;}}}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:953;}}}}s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10812;}}}}}s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:191;}s:9:\"codepoint\";i:191;}}}}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119998;}}}s:1:\"i\";a:1:{s:1:\"n\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8712;}s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8953;}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8949;}}}}s:1:\"s\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8948;}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8947;}}}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8712;}}}}}s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8290;}s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:297;}}}}}}s:1:\"u\";a:2:{s:1:\"k\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1110;}}}}s:1:\"m\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:239;}s:9:\"codepoint\";i:239;}}}}s:1:\"j\";a:6:{s:1:\"c\";a:2:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:309;}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1081;}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120103;}}}s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:567;}}}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120155;}}}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:119999;}}}s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1112;}}}}}}s:1:\"u\";a:1:{s:1:\"k\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1108;}}}}}}s:1:\"k\";a:8:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:954;}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1008;}}}}}}s:1:\"c\";a:2:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:311;}}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1082;}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120104;}}}s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:312;}}}}}}s:1:\"h\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1093;}}}}s:1:\"j\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1116;}}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120156;}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120000;}}}}}s:1:\"l\";a:22:{s:1:\"A\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8666;}}}}s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8656;}}}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10523;}}}}}}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10510;}}}}}s:1:\"E\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8806;}s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10891;}}}s:1:\"H\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10594;}}}}s:1:\"a\";a:9:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:314;}}}}}s:1:\"e\";a:1:{s:1:\"m\";a:1:{s:1:\"p\";a:1:{s:1:\"t\";a:1:{s:1:\"y\";a:1:{s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10676;}}}}}}}s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8466;}}}}}s:1:\"m\";a:1:{s:1:\"b\";a:1:{s:1:\"d\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:955;}}}}}s:1:\"n\";a:1:{s:1:\"g\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10216;}s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10641;}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10216;}}}}}s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10885;}}s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"o\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:171;}s:9:\"codepoint\";i:171;}}}s:1:\"r\";a:1:{s:1:\"r\";a:8:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8592;}s:1:\"b\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8676;}s:1:\"f\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10527;}}}}s:1:\"f\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10525;}}}s:1:\"h\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8617;}}}s:1:\"l\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8619;}}}s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10553;}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10611;}}}}s:1:\"t\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8610;}}}}}s:1:\"t\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10923;}s:1:\"a\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10521;}}}}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10925;}}}}s:1:\"b\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10508;}}}}s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10098;}}}}s:1:\"r\";a:2:{s:1:\"a\";a:1:{s:1:\"c\";a:2:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:123;}}s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:91;}}}}s:1:\"k\";a:2:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10635;}}s:1:\"s\";a:1:{s:1:\"l\";a:2:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10639;}}s:1:\"u\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10637;}}}}}}}s:1:\"c\";a:4:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:318;}}}}}s:1:\"e\";a:2:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:316;}}}}s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8968;}}}}s:1:\"u\";a:1:{s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:123;}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1083;}}}s:1:\"d\";a:4:{s:1:\"c\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10550;}}}s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"o\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8220;}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8222;}}}}}s:1:\"r\";a:2:{s:1:\"d\";a:1:{s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10599;}}}}}s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10571;}}}}}}}s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8626;}}}}s:1:\"e\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8804;}s:1:\"f\";a:1:{s:1:\"t\";a:5:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8592;}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8610;}}}}}}}}}}s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"p\";a:1:{s:1:\"o\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:2:{s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8637;}}}}}s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8636;}}}}}}}}}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8647;}}}}}}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8596;}s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8646;}}}}}}}s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"p\";a:1:{s:1:\"o\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8651;}}}}}}}}}s:1:\"s\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8621;}}}}}}}}}}}}}}}}s:1:\"t\";a:1:{s:1:\"h\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8907;}}}}}}}}}}}}}s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8922;}}s:1:\"q\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8804;}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8806;}}s:1:\"s\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10877;}}}}}}}s:1:\"s\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10877;}s:1:\"c\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10920;}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10879;}s:1:\"o\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10881;}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10883;}}}}}}s:1:\"g\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10899;}}}}s:1:\"s\";a:5:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"x\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10885;}}}}}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8918;}}}}s:1:\"e\";a:1:{s:1:\"q\";a:2:{s:1:\"g\";a:1:{s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8922;}}}}s:1:\"q\";a:1:{s:1:\"g\";a:1:{s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10891;}}}}}}}s:1:\"g\";a:1:{s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8822;}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8818;}}}}}}}s:1:\"f\";a:3:{s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10620;}}}}}s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8970;}}}}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120105;}}}s:1:\"g\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8822;}s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10897;}}}s:1:\"h\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8637;}}s:1:\"u\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8636;}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10602;}}}}}s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9604;}}}}}s:1:\"j\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1113;}}}}s:1:\"l\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8810;}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8647;}}}}s:1:\"c\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8990;}}}}}}}s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10603;}}}}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9722;}}}}}s:1:\"m\";a:2:{s:1:\"i\";a:1:{s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:320;}}}}}s:1:\"o\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9136;}s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"h\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9136;}}}}}}}}}}s:1:\"n\";a:4:{s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8808;}}s:1:\"a\";a:1:{s:1:\"p\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10889;}s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"x\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10889;}}}}}}}s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10887;}s:1:\"q\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10887;}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8808;}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8934;}}}}}s:1:\"o\";a:8:{s:1:\"a\";a:2:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10220;}}}s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8701;}}}}s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10214;}}}}s:1:\"n\";a:1:{s:1:\"g\";a:3:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10229;}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10231;}}}}}}}}}}}}}}}s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10236;}}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10230;}}}}}}}}}}}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:2:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8619;}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8620;}}}}}}}}}}}}}s:1:\"p\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10629;}}}s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120157;}}s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10797;}}}}}s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10804;}}}}}}s:1:\"w\";a:2:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8727;}}}}s:1:\"b\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:95;}}}}}s:1:\"z\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9674;}s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9674;}}}}}s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10731;}}}}s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:40;}s:1:\"l\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10643;}}}}}}s:1:\"r\";a:5:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8646;}}}}s:1:\"c\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8991;}}}}}}}s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8651;}s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10605;}}}}}s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8206;}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8895;}}}}}s:1:\"s\";a:6:{s:1:\"a\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"o\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8249;}}}}}s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120001;}}}s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8624;}}s:1:\"i\";a:1:{s:1:\"m\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8818;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10893;}}s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10895;}}}}s:1:\"q\";a:2:{s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:91;}}s:1:\"u\";a:1:{s:1:\"o\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8216;}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8218;}}}}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:322;}}}}}}s:1:\"t\";a:9:{s:1:\";\";a:1:{s:9:\"codepoint\";i:60;}s:9:\"codepoint\";i:60;s:1:\"c\";a:2:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10918;}}s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10873;}}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8918;}}}}s:1:\"h\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8907;}}}}}s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8905;}}}}}s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10614;}}}}}s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10875;}}}}}}s:1:\"r\";a:2:{s:1:\"P\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10646;}}}}s:1:\"i\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9667;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8884;}}s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9666;}}}}}s:1:\"u\";a:1:{s:1:\"r\";a:2:{s:1:\"d\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10570;}}}}}}s:1:\"u\";a:1:{s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10598;}}}}}}}}s:1:\"m\";a:14:{s:1:\"D\";a:1:{s:1:\"D\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8762;}}}}}s:1:\"a\";a:4:{s:1:\"c\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:175;}s:9:\"codepoint\";i:175;}}s:1:\"l\";a:2:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9794;}}s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10016;}s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10016;}}}}}}s:1:\"p\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8614;}s:1:\"s\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8614;}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8615;}}}}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8612;}}}}}s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8613;}}}}}}}s:1:\"r\";a:1:{s:1:\"k\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9646;}}}}}}s:1:\"c\";a:2:{s:1:\"o\";a:1:{s:1:\"m\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10793;}}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1084;}}}s:1:\"d\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8212;}}}}}s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"u\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8737;}}}}}}}}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120106;}}}s:1:\"h\";a:1:{s:1:\"o\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8487;}}}s:1:\"i\";a:3:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:181;}s:9:\"codepoint\";i:181;}}}s:1:\"d\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8739;}s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:42;}}}}s:1:\"c\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10992;}}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:183;}s:9:\"codepoint\";i:183;}}}}s:1:\"n\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8722;}s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8863;}}s:1:\"d\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8760;}s:1:\"u\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10794;}}}}}}}s:1:\"l\";a:2:{s:1:\"c\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10971;}}}s:1:\"d\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8230;}}}}s:1:\"n\";a:1:{s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8723;}}}}}}s:1:\"o\";a:2:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\"l\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8871;}}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120158;}}}}s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8723;}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120002;}}}s:1:\"t\";a:1:{s:1:\"p\";a:1:{s:1:\"o\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8766;}}}}}}s:1:\"u\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:956;}s:1:\"l\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8888;}}}}}}}s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8888;}}}}}}s:1:\"n\";a:23:{s:1:\"L\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8653;}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8654;}}}}}}}}}}}}}}}s:1:\"R\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8655;}}}}}}}}}}}s:1:\"V\";a:2:{s:1:\"D\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8879;}}}}}s:1:\"d\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8878;}}}}}}s:1:\"a\";a:4:{s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8711;}}}}s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:324;}}}}}s:1:\"p\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8777;}s:1:\"o\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:329;}}}s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"x\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8777;}}}}}}s:1:\"t\";a:1:{s:1:\"u\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9838;}s:1:\"a\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9838;}s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8469;}}}}}}}}s:1:\"b\";a:1:{s:1:\"s\";a:1:{s:1:\"p\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:160;}s:9:\"codepoint\";i:160;}}}s:1:\"c\";a:5:{s:1:\"a\";a:2:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10819;}}s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:328;}}}}}s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:326;}}}}}s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8775;}}}}s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10818;}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1085;}}}s:1:\"d\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8211;}}}}}s:1:\"e\";a:6:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8800;}s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8663;}}}}s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\"h\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10532;}}}s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8599;}s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8599;}}}}}}s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"i\";a:1:{s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8802;}}}}}s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10536;}}}}}s:1:\"x\";a:1:{s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8708;}s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8708;}}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120107;}}}s:1:\"g\";a:3:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8817;}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8817;}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8821;}}}}s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8815;}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8815;}}}}s:1:\"h\";a:3:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8654;}}}}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8622;}}}}s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10994;}}}}}s:1:\"i\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8715;}s:1:\"s\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8956;}s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8954;}}}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8715;}}}s:1:\"j\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1114;}}}}s:1:\"l\";a:6:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8653;}}}}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8602;}}}}s:1:\"d\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8229;}}}s:1:\"e\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8816;}s:1:\"f\";a:1:{s:1:\"t\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8602;}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8622;}}}}}}}}}}}}}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8816;}}s:1:\"s\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8814;}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8820;}}}}s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8814;}s:1:\"r\";a:1:{s:1:\"i\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8938;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8940;}}}}}}s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8740;}}}}s:1:\"o\";a:2:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120159;}}}s:1:\"t\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:172;}s:9:\"codepoint\";i:172;s:1:\"i\";a:1:{s:1:\"n\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8713;}s:1:\"v\";a:3:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8713;}}s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8951;}}s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8950;}}}}}s:1:\"n\";a:1:{s:1:\"i\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8716;}s:1:\"v\";a:3:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8716;}}s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8958;}}s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8957;}}}}}}}s:1:\"p\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8742;}s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8742;}}}}}}}}s:1:\"o\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10772;}}}}}}s:1:\"r\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8832;}s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8928;}}}}s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8832;}}}}}s:1:\"r\";a:4:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8655;}}}}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8603;}}}}s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8603;}}}}}}}}}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8939;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8941;}}}}}}s:1:\"s\";a:7:{s:1:\"c\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8833;}s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8929;}}}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120003;}}}s:1:\"h\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:2:{s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8740;}}}}s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8742;}}}}}}}}}}}}}s:1:\"i\";a:1:{s:1:\"m\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8769;}s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8772;}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8772;}}}}}s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8740;}}}}s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8742;}}}}s:1:\"q\";a:1:{s:1:\"s\";a:1:{s:1:\"u\";a:2:{s:1:\"b\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8930;}}}s:1:\"p\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8931;}}}}}}s:1:\"u\";a:3:{s:1:\"b\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8836;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8840;}}s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8840;}}}}}}}s:1:\"c\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8833;}}}s:1:\"p\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8837;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8841;}}s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8841;}}}}}}}}}s:1:\"t\";a:4:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8825;}}}s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:241;}s:9:\"codepoint\";i:241;}}}}s:1:\"l\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8824;}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:2:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8938;}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8940;}}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8939;}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8941;}}}}}}}}}}}}}}}}s:1:\"u\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:957;}s:1:\"m\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:35;}s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8470;}}}}s:1:\"s\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8199;}}}}}s:1:\"v\";a:6:{s:1:\"D\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8877;}}}}}s:1:\"H\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10500;}}}}}s:1:\"d\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8876;}}}}}s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"f\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10718;}}}}}}s:1:\"l\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10498;}}}}}s:1:\"r\";a:1:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10499;}}}}}}s:1:\"w\";a:3:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8662;}}}}s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\"h\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10531;}}}s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8598;}s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8598;}}}}}}s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10535;}}}}}}}s:1:\"o\";a:18:{s:1:\"S\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9416;}}s:1:\"a\";a:2:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:243;}s:9:\"codepoint\";i:243;}}}}s:1:\"s\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8859;}}}}s:1:\"c\";a:2:{s:1:\"i\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8858;}s:1:\"c\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:244;}s:9:\"codepoint\";i:244;}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1086;}}}s:1:\"d\";a:5:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8861;}}}}s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:337;}}}}}s:1:\"i\";a:1:{s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10808;}}}s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8857;}}}s:1:\"s\";a:1:{s:1:\"o\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10684;}}}}}}s:1:\"e\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:339;}}}}}s:1:\"f\";a:2:{s:1:\"c\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10687;}}}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120108;}}}s:1:\"g\";a:3:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:731;}}}s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:242;}s:9:\"codepoint\";i:242;}}}}s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10689;}}}s:1:\"h\";a:2:{s:1:\"b\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10677;}}}}s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8486;}}}s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8750;}}}}s:1:\"l\";a:4:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8634;}}}}s:1:\"c\";a:2:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10686;}}}s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"s\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10683;}}}}}}s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8254;}}}}s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10688;}}}s:1:\"m\";a:3:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:333;}}}}s:1:\"e\";a:1:{s:1:\"g\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:969;}}}}s:1:\"i\";a:3:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:959;}}}}}s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10678;}}s:1:\"n\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8854;}}}}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120160;}}}}s:1:\"p\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10679;}}}s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10681;}}}}s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8853;}}}}}s:1:\"r\";a:7:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8744;}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8635;}}}}s:1:\"d\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10845;}s:1:\"e\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8500;}s:1:\"o\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8500;}}}}}s:1:\"f\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:170;}s:9:\"codepoint\";i:170;}s:1:\"m\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:186;}s:9:\"codepoint\";i:186;}}s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"o\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8886;}}}}}s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10838;}}}s:1:\"s\";a:1:{s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10839;}}}}}}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10843;}}}s:1:\"s\";a:3:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8500;}}}s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:248;}s:9:\"codepoint\";i:248;}}}}s:1:\"o\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8856;}}}}s:1:\"t\";a:1:{s:1:\"i\";a:2:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:245;}s:9:\"codepoint\";i:245;}}}s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8855;}s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10806;}}}}}}}}s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:246;}s:9:\"codepoint\";i:246;}}}s:1:\"v\";a:1:{s:1:\"b\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9021;}}}}}}s:1:\"p\";a:12:{s:1:\"a\";a:1:{s:1:\"r\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8741;}s:1:\"a\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:182;}s:9:\"codepoint\";i:182;s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8741;}}}}}}s:1:\"s\";a:2:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10995;}}}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:11005;}}}s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8706;}}}}s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1087;}}}s:1:\"e\";a:1:{s:1:\"r\";a:5:{s:1:\"c\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:37;}}}}s:1:\"i\";a:1:{s:1:\"o\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:46;}}}}s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8240;}}}}s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8869;}}s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\"n\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8241;}}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120109;}}}s:1:\"h\";a:3:{s:1:\"i\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:966;}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:966;}}}s:1:\"m\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8499;}}}}}s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9742;}}}}}s:1:\"i\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:960;}s:1:\"t\";a:1:{s:1:\"c\";a:1:{s:1:\"h\";a:1:{s:1:\"f\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8916;}}}}}}}}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:982;}}}s:1:\"l\";a:2:{s:1:\"a\";a:1:{s:1:\"n\";a:2:{s:1:\"c\";a:1:{s:1:\"k\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8463;}s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8462;}}}}s:1:\"k\";a:1:{s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8463;}}}}}s:1:\"u\";a:1:{s:1:\"s\";a:9:{s:1:\";\";a:1:{s:9:\"codepoint\";i:43;}s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10787;}}}}}s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8862;}}s:1:\"c\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10786;}}}}s:1:\"d\";a:2:{s:1:\"o\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8724;}}s:1:\"u\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10789;}}}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10866;}}s:1:\"m\";a:1:{s:1:\"n\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:177;}s:9:\"codepoint\";i:177;}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10790;}}}}s:1:\"t\";a:1:{s:1:\"w\";a:1:{s:1:\"o\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10791;}}}}}}}s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:177;}}s:1:\"o\";a:3:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10773;}}}}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120161;}}}s:1:\"u\";a:1:{s:1:\"n\";a:1:{s:1:\"d\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:163;}s:9:\"codepoint\";i:163;}}}}s:1:\"r\";a:10:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8826;}s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10931;}}s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10935;}}}s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8828;}}}}s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10927;}s:1:\"c\";a:6:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8826;}s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"x\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10935;}}}}}}}s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"r\";a:1:{s:1:\"l\";a:1:{s:1:\"y\";a:1:{s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8828;}}}}}}}}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10927;}}}s:1:\"n\";a:3:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"x\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10937;}}}}}}}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10933;}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8936;}}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8830;}}}}}}s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8242;}s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8473;}}}}}s:1:\"n\";a:3:{s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10933;}}s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10937;}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8936;}}}}}s:1:\"o\";a:3:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8719;}}s:1:\"f\";a:3:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9006;}}}}}s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8978;}}}}}s:1:\"s\";a:1:{s:1:\"u\";a:1:{s:1:\"r\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8979;}}}}}}s:1:\"p\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8733;}s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8733;}}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8830;}}}}s:1:\"u\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8880;}}}}}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120005;}}}s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:968;}}}s:1:\"u\";a:1:{s:1:\"n\";a:1:{s:1:\"c\";a:1:{s:1:\"s\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8200;}}}}}}}s:1:\"q\";a:6:{s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120110;}}}s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10764;}}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120162;}}}}s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8279;}}}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120006;}}}}s:1:\"u\";a:3:{s:1:\"a\";a:1:{s:1:\"t\";a:2:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"n\";a:1:{s:1:\"i\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8461;}}}}}}}}s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10774;}}}}}}s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:63;}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8799;}}}}}}s:1:\"o\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:34;}s:9:\"codepoint\";i:34;}}}}s:1:\"r\";a:21:{s:1:\"A\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8667;}}}}s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8658;}}}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10524;}}}}}}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10511;}}}}}s:1:\"H\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10596;}}}}s:1:\"a\";a:7:{s:1:\"c\";a:2:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10714;}}s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:341;}}}}}s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8730;}}}}s:1:\"e\";a:1:{s:1:\"m\";a:1:{s:1:\"p\";a:1:{s:1:\"t\";a:1:{s:1:\"y\";a:1:{s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10675;}}}}}}}s:1:\"n\";a:1:{s:1:\"g\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10217;}s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10642;}}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10661;}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10217;}}}}}s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"o\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:187;}s:9:\"codepoint\";i:187;}}}s:1:\"r\";a:1:{s:1:\"r\";a:11:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8594;}s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10613;}}}s:1:\"b\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8677;}s:1:\"f\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10528;}}}}s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10547;}}s:1:\"f\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10526;}}}s:1:\"h\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8618;}}}s:1:\"l\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8620;}}}s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10565;}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10612;}}}}s:1:\"t\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8611;}}}s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8605;}}}}s:1:\"t\";a:2:{s:1:\"a\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10522;}}}}s:1:\"i\";a:1:{s:1:\"o\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8758;}s:1:\"n\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8474;}}}}}}}}}s:1:\"b\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10509;}}}}s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10099;}}}}s:1:\"r\";a:2:{s:1:\"a\";a:1:{s:1:\"c\";a:2:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:125;}}s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:93;}}}}s:1:\"k\";a:2:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10636;}}s:1:\"s\";a:1:{s:1:\"l\";a:2:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10638;}}s:1:\"u\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10640;}}}}}}}s:1:\"c\";a:4:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:345;}}}}}s:1:\"e\";a:2:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:343;}}}}s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8969;}}}}s:1:\"u\";a:1:{s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:125;}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1088;}}}s:1:\"d\";a:4:{s:1:\"c\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10551;}}}s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10601;}}}}}}s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"o\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8221;}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8221;}}}}}s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8627;}}}}s:1:\"e\";a:3:{s:1:\"a\";a:1:{s:1:\"l\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8476;}s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8475;}}}}s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8476;}}}}}s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8477;}}}}s:1:\"c\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9645;}}}s:1:\"g\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:174;}s:9:\"codepoint\";i:174;}}s:1:\"f\";a:3:{s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10621;}}}}}s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8971;}}}}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120111;}}}s:1:\"h\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8641;}}s:1:\"u\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8640;}s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10604;}}}}}s:1:\"o\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:961;}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1009;}}}}s:1:\"i\";a:3:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:6:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8594;}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8611;}}}}}}}}}}s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"p\";a:1:{s:1:\"o\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:2:{s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8641;}}}}}s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8640;}}}}}}}}}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8644;}}}}}}}s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"p\";a:1:{s:1:\"o\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8652;}}}}}}}}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8649;}}}}}}}}}}}}s:1:\"s\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8605;}}}}}}}}}}}s:1:\"t\";a:1:{s:1:\"h\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8908;}}}}}}}}}}}}}}s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:730;}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8787;}}}}}}}}}}}}s:1:\"l\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8644;}}}}s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8652;}}}}s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8207;}}}s:1:\"m\";a:1:{s:1:\"o\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9137;}s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"h\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9137;}}}}}}}}}}s:1:\"n\";a:1:{s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10990;}}}}}s:1:\"o\";a:4:{s:1:\"a\";a:2:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10221;}}}s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8702;}}}}s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10215;}}}}s:1:\"p\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10630;}}}s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120163;}}s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10798;}}}}}s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10805;}}}}}}}s:1:\"p\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:41;}s:1:\"g\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10644;}}}}}s:1:\"p\";a:1:{s:1:\"o\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10770;}}}}}}}}s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8649;}}}}}s:1:\"s\";a:4:{s:1:\"a\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"o\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8250;}}}}}s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120007;}}}s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8625;}}s:1:\"q\";a:2:{s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:93;}}s:1:\"u\";a:1:{s:1:\"o\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8217;}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8217;}}}}}}s:1:\"t\";a:3:{s:1:\"h\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8908;}}}}}s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8906;}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9657;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8885;}}s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9656;}}s:1:\"l\";a:1:{s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10702;}}}}}}}}s:1:\"u\";a:1:{s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10600;}}}}}}}s:1:\"x\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8478;}}}s:1:\"s\";a:19:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:347;}}}}}}s:1:\"b\";a:1:{s:1:\"q\";a:1:{s:1:\"u\";a:1:{s:1:\"o\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8218;}}}}}s:1:\"c\";a:10:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8827;}s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10932;}}s:1:\"a\";a:2:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10936;}}s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:353;}}}}}s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8829;}}}}s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10928;}s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:351;}}}}}s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:349;}}}}s:1:\"n\";a:3:{s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10934;}}s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10938;}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8937;}}}}}s:1:\"p\";a:1:{s:1:\"o\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10771;}}}}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8831;}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1089;}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8901;}s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8865;}}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10854;}}}}}s:1:\"e\";a:7:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8664;}}}}s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\"h\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10533;}}}s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8600;}s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8600;}}}}}}s:1:\"c\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:167;}s:9:\"codepoint\";i:167;}}s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:59;}}}s:1:\"s\";a:1:{s:1:\"w\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10537;}}}}}s:1:\"t\";a:1:{s:1:\"m\";a:2:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8726;}}}}}s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8726;}}}}s:1:\"x\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10038;}}}}s:1:\"f\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120112;}s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8994;}}}}}}s:1:\"h\";a:4:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9839;}}}}s:1:\"c\";a:2:{s:1:\"h\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1097;}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1096;}}}s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:2:{s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8739;}}}}s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8741;}}}}}}}}}}}}s:1:\"y\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:173;}s:9:\"codepoint\";i:173;}}s:1:\"i\";a:2:{s:1:\"g\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:963;}s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:962;}}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:962;}}}}}s:1:\"m\";a:8:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8764;}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10858;}}}}s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8771;}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8771;}}}s:1:\"g\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10910;}s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10912;}}}s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10909;}s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10911;}}}s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8774;}}}s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10788;}}}}}s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10610;}}}}}}}s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8592;}}}}}s:1:\"m\";a:4:{s:1:\"a\";a:2:{s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8726;}}}}}}}}}}}s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10803;}}}}}s:1:\"e\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"s\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10724;}}}}}}}s:1:\"i\";a:2:{s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8739;}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8995;}}}}s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10922;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10924;}}}}s:1:\"o\";a:3:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1100;}}}}}s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:47;}s:1:\"b\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10692;}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9023;}}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120164;}}}}s:1:\"p\";a:1:{s:1:\"a\";a:2:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9824;}s:1:\"u\";a:1:{s:1:\"i\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9824;}}}}}}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8741;}}}}s:1:\"q\";a:3:{s:1:\"c\";a:2:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8851;}}}s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8852;}}}}s:1:\"s\";a:1:{s:1:\"u\";a:2:{s:1:\"b\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8847;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8849;}}s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8847;}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8849;}}}}}}}s:1:\"p\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8848;}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8850;}}s:1:\"s\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8848;}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8850;}}}}}}}}}s:1:\"u\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9633;}s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9633;}}s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9642;}}}}s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9642;}}}}s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8594;}}}}}s:1:\"s\";a:4:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120008;}}}s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\"m\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8726;}}}}}s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8995;}}}}}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8902;}}}}}}s:1:\"t\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9734;}s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9733;}}}}s:1:\"r\";a:2:{s:1:\"a\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:2:{s:1:\"e\";a:1:{s:1:\"p\";a:1:{s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1013;}}}}}}}}s:1:\"p\";a:1:{s:1:\"h\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:981;}}}}}}}}}s:1:\"n\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:175;}}}}}s:1:\"u\";a:5:{s:1:\"b\";a:9:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8834;}s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10949;}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10941;}}}}s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8838;}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10947;}}}}}s:1:\"m\";a:1:{s:1:\"u\";a:1:{s:1:\"l\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10945;}}}}}s:1:\"n\";a:2:{s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10955;}}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8842;}}}s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10943;}}}}}s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10617;}}}}}s:1:\"s\";a:3:{s:1:\"e\";a:1:{s:1:\"t\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8834;}s:1:\"e\";a:1:{s:1:\"q\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8838;}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10949;}}}}s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\"q\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8842;}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10955;}}}}}}}s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10951;}}}s:1:\"u\";a:2:{s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10965;}}s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10963;}}}}}s:1:\"c\";a:1:{s:1:\"c\";a:6:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8827;}s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"x\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10936;}}}}}}}s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"r\";a:1:{s:1:\"l\";a:1:{s:1:\"y\";a:1:{s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8829;}}}}}}}}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10928;}}}s:1:\"n\";a:3:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"x\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10938;}}}}}}}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10934;}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8937;}}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8831;}}}}}}s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8721;}}s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9834;}}}s:1:\"p\";a:13:{i:1;a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:185;}s:9:\"codepoint\";i:185;}i:2;a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:178;}s:9:\"codepoint\";i:178;}i:3;a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:179;}s:9:\"codepoint\";i:179;}s:1:\";\";a:1:{s:9:\"codepoint\";i:8835;}s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10950;}}s:1:\"d\";a:2:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10942;}}}s:1:\"s\";a:1:{s:1:\"u\";a:1:{s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10968;}}}}}s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8839;}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10948;}}}}}s:1:\"h\";a:1:{s:1:\"s\";a:1:{s:1:\"u\";a:1:{s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10967;}}}}}s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10619;}}}}}s:1:\"m\";a:1:{s:1:\"u\";a:1:{s:1:\"l\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10946;}}}}}s:1:\"n\";a:2:{s:1:\"E\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10956;}}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8843;}}}s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10944;}}}}}s:1:\"s\";a:3:{s:1:\"e\";a:1:{s:1:\"t\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8835;}s:1:\"e\";a:1:{s:1:\"q\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8839;}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10950;}}}}s:1:\"n\";a:1:{s:1:\"e\";a:1:{s:1:\"q\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8843;}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10956;}}}}}}}s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10952;}}}s:1:\"u\";a:2:{s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10964;}}s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10966;}}}}}}s:1:\"w\";a:3:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8665;}}}}s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\"h\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10534;}}}s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8601;}s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8601;}}}}}}s:1:\"n\";a:1:{s:1:\"w\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10538;}}}}}}s:1:\"z\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:223;}s:9:\"codepoint\";i:223;}}}}}s:1:\"t\";a:13:{s:1:\"a\";a:2:{s:1:\"r\";a:1:{s:1:\"g\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8982;}}}}}s:1:\"u\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:964;}}}s:1:\"b\";a:1:{s:1:\"r\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9140;}}}}s:1:\"c\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:357;}}}}}s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:355;}}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1090;}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8411;}}}}s:1:\"e\";a:1:{s:1:\"l\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8981;}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120113;}}}s:1:\"h\";a:4:{s:1:\"e\";a:2:{s:1:\"r\";a:1:{s:1:\"e\";a:2:{i:4;a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8756;}}s:1:\"f\";a:1:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8756;}}}}}}}s:1:\"t\";a:1:{s:1:\"a\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:952;}s:1:\"s\";a:1:{s:1:\"y\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:977;}}}}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:977;}}}}}s:1:\"i\";a:2:{s:1:\"c\";a:1:{s:1:\"k\";a:2:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"x\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8776;}}}}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8764;}}}}}}s:1:\"n\";a:1:{s:1:\"s\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8201;}}}}}s:1:\"k\";a:2:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8776;}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8764;}}}}}s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"n\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:254;}s:9:\"codepoint\";i:254;}}}}s:1:\"i\";a:3:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:732;}}}}s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\"s\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:215;}s:9:\"codepoint\";i:215;s:1:\"b\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8864;}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10801;}}}}s:1:\"d\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10800;}}}}}s:1:\"n\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8749;}}}}s:1:\"o\";a:3:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10536;}}}s:1:\"p\";a:4:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8868;}s:1:\"b\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9014;}}}}s:1:\"c\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10993;}}}}s:1:\"f\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120165;}s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10970;}}}}}}s:1:\"s\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10537;}}}}s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8244;}}}}}}s:1:\"r\";a:3:{s:1:\"a\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8482;}}}}s:1:\"i\";a:7:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:5:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9653;}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9663;}}}}}s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9667;}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8884;}}}}}}}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8796;}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9657;}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8885;}}}}}}}}}}}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9708;}}}}s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8796;}}s:1:\"m\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10810;}}}}}}s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10809;}}}}}s:1:\"s\";a:1:{s:1:\"b\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10701;}}}s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10811;}}}}}}s:1:\"p\";a:1:{s:1:\"e\";a:1:{s:1:\"z\";a:1:{s:1:\"i\";a:1:{s:1:\"u\";a:1:{s:1:\"m\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9186;}}}}}}}}s:1:\"s\";a:3:{s:1:\"c\";a:2:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120009;}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1094;}}}s:1:\"h\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1115;}}}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:359;}}}}}}s:1:\"w\";a:2:{s:1:\"i\";a:1:{s:1:\"x\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8812;}}}}s:1:\"o\";a:1:{s:1:\"h\";a:1:{s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"d\";a:2:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8606;}}}}}}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8608;}}}}}}}}}}}}}}}}}}s:1:\"u\";a:18:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8657;}}}}s:1:\"H\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10595;}}}}s:1:\"a\";a:2:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:250;}s:9:\"codepoint\";i:250;}}}}s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8593;}}}}s:1:\"b\";a:1:{s:1:\"r\";a:2:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1118;}}}s:1:\"e\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:365;}}}}}}s:1:\"c\";a:2:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:251;}s:9:\"codepoint\";i:251;}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1091;}}}s:1:\"d\";a:3:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8645;}}}}s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:369;}}}}}s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10606;}}}}}s:1:\"f\";a:2:{s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10622;}}}}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120114;}}}s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"v\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:249;}s:9:\"codepoint\";i:249;}}}}}s:1:\"h\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\"l\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8639;}}s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8638;}}}}s:1:\"b\";a:1:{s:1:\"l\";a:1:{s:1:\"k\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9600;}}}}}s:1:\"l\";a:2:{s:1:\"c\";a:2:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"n\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8988;}s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8988;}}}}}}s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8975;}}}}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9720;}}}}}s:1:\"m\";a:2:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:363;}}}}s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:168;}s:9:\"codepoint\";i:168;}}s:1:\"o\";a:2:{s:1:\"g\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:371;}}}}s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120166;}}}}s:1:\"p\";a:6:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8593;}}}}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"n\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8597;}}}}}}}}}}s:1:\"h\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"p\";a:1:{s:1:\"o\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:2:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8639;}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8638;}}}}}}}}}}}}}s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8846;}}}}s:1:\"s\";a:1:{s:1:\"i\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:965;}s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:978;}}s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:965;}}}}}}s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"w\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8648;}}}}}}}}}}s:1:\"r\";a:3:{s:1:\"c\";a:2:{s:1:\"o\";a:1:{s:1:\"r\";a:1:{s:1:\"n\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8989;}s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8989;}}}}}}s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8974;}}}}}s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:367;}}}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9721;}}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120010;}}}}s:1:\"t\";a:3:{s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8944;}}}}s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"d\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:361;}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9653;}s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9652;}}}}}s:1:\"u\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8648;}}}}s:1:\"m\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:252;}s:9:\"codepoint\";i:252;}}}s:1:\"w\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10663;}}}}}}}}s:1:\"v\";a:14:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8661;}}}}s:1:\"B\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10984;}s:1:\"v\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10985;}}}}}s:1:\"D\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8872;}}}}}s:1:\"a\";a:2:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10652;}}}}}s:1:\"r\";a:7:{s:1:\"e\";a:1:{s:1:\"p\";a:1:{s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"l\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:949;}}}}}}}}s:1:\"k\";a:1:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\"p\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1008;}}}}}}s:1:\"n\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\"h\";a:1:{s:1:\"i\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8709;}}}}}}}}s:1:\"p\";a:3:{s:1:\"h\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:966;}}}s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:982;}}s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"t\";a:1:{s:1:\"o\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8733;}}}}}}}s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8597;}s:1:\"h\";a:1:{s:1:\"o\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1009;}}}}s:1:\"s\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:962;}}}}}}s:1:\"t\";a:2:{s:1:\"h\";a:1:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:977;}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"a\";a:1:{s:1:\"n\";a:1:{s:1:\"g\";a:1:{s:1:\"l\";a:1:{s:1:\"e\";a:2:{s:1:\"l\";a:1:{s:1:\"e\";a:1:{s:1:\"f\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8882;}}}}}s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"h\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8883;}}}}}}}}}}}}}}}}s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1074;}}}s:1:\"d\";a:1:{s:1:\"a\";a:1:{s:1:\"s\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8866;}}}}}s:1:\"e\";a:3:{s:1:\"e\";a:3:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8744;}s:1:\"b\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8891;}}}}s:1:\"e\";a:1:{s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8794;}}}}s:1:\"l\";a:1:{s:1:\"l\";a:1:{s:1:\"i\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8942;}}}}}s:1:\"r\";a:2:{s:1:\"b\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:124;}}}}s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:124;}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120115;}}}s:1:\"l\";a:1:{s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8882;}}}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120167;}}}}s:1:\"p\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8733;}}}}}s:1:\"r\";a:1:{s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8883;}}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120011;}}}}s:1:\"z\";a:1:{s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"z\";a:1:{s:1:\"a\";a:1:{s:1:\"g\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10650;}}}}}}}}s:1:\"w\";a:7:{s:1:\"c\";a:1:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:373;}}}}}s:1:\"e\";a:2:{s:1:\"d\";a:2:{s:1:\"b\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10847;}}}}s:1:\"g\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8743;}s:1:\"q\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8793;}}}}}s:1:\"i\";a:1:{s:1:\"e\";a:1:{s:1:\"r\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8472;}}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120116;}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120168;}}}}s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8472;}}s:1:\"r\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8768;}s:1:\"e\";a:1:{s:1:\"a\";a:1:{s:1:\"t\";a:1:{s:1:\"h\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8768;}}}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120012;}}}}}s:1:\"x\";a:14:{s:1:\"c\";a:3:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8898;}}}s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9711;}}}}s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8899;}}}}s:1:\"d\";a:1:{s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9661;}}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120117;}}}s:1:\"h\";a:2:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10234;}}}}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10231;}}}}}s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:958;}}s:1:\"l\";a:2:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10232;}}}}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10229;}}}}}s:1:\"m\";a:1:{s:1:\"a\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10236;}}}}s:1:\"n\";a:1:{s:1:\"i\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8955;}}}}s:1:\"o\";a:3:{s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10752;}}}}s:1:\"p\";a:2:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120169;}}s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10753;}}}}}s:1:\"t\";a:1:{s:1:\"i\";a:1:{s:1:\"m\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10754;}}}}}}s:1:\"r\";a:2:{s:1:\"A\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10233;}}}}s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10230;}}}}}s:1:\"s\";a:2:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120013;}}}s:1:\"q\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"p\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10758;}}}}}}s:1:\"u\";a:2:{s:1:\"p\";a:1:{s:1:\"l\";a:1:{s:1:\"u\";a:1:{s:1:\"s\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:10756;}}}}}s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"i\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:9651;}}}}}s:1:\"v\";a:1:{s:1:\"e\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8897;}}}}s:1:\"w\";a:1:{s:1:\"e\";a:1:{s:1:\"d\";a:1:{s:1:\"g\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8896;}}}}}}}s:1:\"y\";a:8:{s:1:\"a\";a:1:{s:1:\"c\";a:2:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:253;}s:9:\"codepoint\";i:253;}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1103;}}}}s:1:\"c\";a:2:{s:1:\"i\";a:1:{s:1:\"r\";a:1:{s:1:\"c\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:375;}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1099;}}}s:1:\"e\";a:1:{s:1:\"n\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:165;}s:9:\"codepoint\";i:165;}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120118;}}}s:1:\"i\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1111;}}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120170;}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120014;}}}}s:1:\"u\";a:2:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1102;}}}s:1:\"m\";a:1:{s:1:\"l\";a:2:{s:1:\";\";a:1:{s:9:\"codepoint\";i:255;}s:9:\"codepoint\";i:255;}}}}s:1:\"z\";a:10:{s:1:\"a\";a:1:{s:1:\"c\";a:1:{s:1:\"u\";a:1:{s:1:\"t\";a:1:{s:1:\"e\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:378;}}}}}}s:1:\"c\";a:2:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"o\";a:1:{s:1:\"n\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:382;}}}}}s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1079;}}}s:1:\"d\";a:1:{s:1:\"o\";a:1:{s:1:\"t\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:380;}}}}s:1:\"e\";a:2:{s:1:\"e\";a:1:{s:1:\"t\";a:1:{s:1:\"r\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8488;}}}}}s:1:\"t\";a:1:{s:1:\"a\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:950;}}}}s:1:\"f\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120119;}}}s:1:\"h\";a:1:{s:1:\"c\";a:1:{s:1:\"y\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:1078;}}}}s:1:\"i\";a:1:{s:1:\"g\";a:1:{s:1:\"r\";a:1:{s:1:\"a\";a:1:{s:1:\"r\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8669;}}}}}}}s:1:\"o\";a:1:{s:1:\"p\";a:1:{s:1:\"f\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120171;}}}}s:1:\"s\";a:1:{s:1:\"c\";a:1:{s:1:\"r\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:120015;}}}}s:1:\"w\";a:2:{s:1:\"j\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8205;}}s:1:\"n\";a:1:{s:1:\"j\";a:1:{s:1:\";\";a:1:{s:9:\"codepoint\";i:8204;}}}}}}"
  },
  {
    "path": "libraries/humble-http-agent/CookieJar.php",
    "content": "<?php\n/**\n * Cookie Jar\n * \n * PHP class for handling cookies, as defined by the Netscape spec: \n * <http://curl.haxx.se/rfc/cookie_spec.html>\n *\n * This class should be used to handle cookies (storing cookies from HTTP response messages, and\n * sending out cookies in HTTP request messages). This has been adapted for FiveFilters.org \n * from the original version used in HTTP Navigator. See http://www.keyvan.net/code/http-navigator/\n * \n * This class is mainly based on Cookies.pm <http://search.cpan.org/author/GAAS/libwww-perl-5.65/\n * lib/HTTP/Cookies.pm> from the libwww-perl collection <http://www.linpro.no/lwp/>.\n * Unlike Cookies.pm, this class only supports the Netscape cookie spec, not RFC 2965.\n * \n * @version 0.5\n * @date 2011-03-15\n * @see http://php.net/HttpRequestPool\n * @author Keyvan Minoukadeh\n * @copyright 2011 Keyvan Minoukadeh\n * @license http://www.gnu.org/licenses/agpl-3.0.html AGPL v3\n */\n\nclass CookieJar\n{\n    /**\n    * Cookies - array containing all cookies.\n    *\n    * <pre>\n    * Cookies are stored like this:\n    *   [domain][path][name] = array\n    * where array is:\n    *   0 => value, 1 => secure, 2 => expires\n    * </pre>\n    * @var array\n    * @access private\n    */\n    public $cookies = array();\n\tpublic $debug = false;\n\n    /**\n    * Constructor\n    */\n    function __construct() {\n    }\n\n\tprotected function debug($msg, $file=null, $line=null) {\n\t\tif ($this->debug) {\n\t\t\t$mem = round(memory_get_usage()/1024, 2);\n\t\t\t$memPeak = round(memory_get_peak_usage()/1024, 2);\n\t\t\techo '* ',$msg;\n\t\t\tif (isset($file, $line)) echo \" ($file line $line)\";\n\t\t\techo ' - mem used: ',$mem,\" (peak: $memPeak)\\n\";\t\n\t\t\tob_flush();\n\t\t\tflush();\n\t\t}\n\t}\t\n\t\n    /**\n    * Get matching cookies\n    *\n    * Only use this method if you cannot use add_cookie_header(), for example, if you want to use\n    * this cookie jar class without using the request class.\n    *\n    * @param array $param associative array containing 'domain', 'path', 'secure' keys\n    * @return string\n    * @see add_cookie_header()\n    */\n    public function getMatchingCookies($url)\n    {\n\t\tif (($parts = @parse_url($url)) && isset($parts['scheme'], $parts['host'], $parts['path'])) {\n\t\t\t$param['domain'] = $parts['host'];\n\t\t\t$param['path'] = $parts['path'];\n\t\t\t$param['secure'] = (strtolower($parts['scheme']) == 'https');\n\t\t\tunset($parts);\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n        // RFC 2965 notes:\n        //  If multiple cookies satisfy the criteria above, they are ordered in\n        //  the Cookie header such that those with more specific Path attributes\n        //  precede those with less specific.  Ordering with respect to other\n        //  attributes (e.g., Domain) is unspecified.\n        $domain = $param['domain'];\n        if (strpos($domain, '.') === false) $domain .= '.local';\n        $request_path = $param['path'];\n        if ($request_path == '') $request_path = '/';\n        $request_secure = $param['secure'];\n        $now = time();\n        $matched_cookies = array();\n        // domain - find matching domains\n        $this->debug('Finding matching domains for '.$domain, __FILE__, __LINE__);\n        while (strpos($domain, '.') !== false) {\n            if (isset($this->cookies[$domain])) {\n                $this->debug(' domain match found: '.$domain);\n                $cookies =& $this->cookies[$domain];\n            } else {\n                $domain = $this->_reduce_domain($domain);\n                continue;\n            }\n            // paths - find matching paths starting from most specific\n            $this->debug('  - Finding matching paths for '.$request_path);\n            $paths = array_keys($cookies);\n            usort($paths, array($this, '_cmp_length'));\n            foreach ($paths as $path) {\n                // continue to next cookie if request path does not path-match cookie path\n                if (!$this->_path_match($request_path, $path)) continue;\n                // loop through cookie names\n                $this->debug('     path match found: '.$path);\n                foreach ($cookies[$path] as $name => $values) {\n                    // if this cookie is secure but request isn't, continue to next cookie\n                    if ($values[1] && !$request_secure) continue;\n                    // if cookie is not a session cookie and has expired, continue to next cookie\n                    if (is_int($values[2]) && ($values[2] < $now)) continue;\n                    // cookie matches request\n                    $this->debug('      cookie match: '.$name.'='.$values[0]);\n                    $matched_cookies[] = $name.'='.$values[0];\n                }\n            }\n            $domain = $this->_reduce_domain($domain);\n        }\n        // return cookies\n        return implode('; ', $matched_cookies);\n    }\n\n    /**\n    * Parse Set-Cookie values.\n    *\n    * Only use this method if you cannot use extract_cookies(), for example, if you want to use\n    * this cookie jar class without using the response class.\n    *\n    * @param array $set_cookies array holding 1 or more \"Set-Cookie\" header values\n    * @param array $param associative array containing 'host', 'path' keys\n    * @return void\n    * @see extract_cookies()\n    */\n    public function storeCookies($url, $set_cookies)\n    {\n        if (count($set_cookies) == 0) return;\n\t\t$param = @parse_url($url);\n\t\tif (!is_array($param) || !isset($param['host'])) return;\n        $request_host = $param['host'];\n        if (strpos($request_host, '.') === false) $request_host .= '.local';\n        $request_path = @$param['path'];\n        if ($request_path == '') $request_path = '/';\n        //\n        // loop through set-cookie headers\n        //\n        foreach ($set_cookies as $set_cookie) {\n            $this->debug('Parsing: '.$set_cookie);\n            // temporary cookie store (before adding to jar)\n            $tmp_cookie = array();\n            $param = explode(';', $set_cookie);\n            // loop through params\n            for ($x=0; $x<count($param); $x++) {\n                $key_val = explode('=', $param[$x], 2);\n                if (count($key_val) != 2) {\n                    // if the first param isn't a name=value pair, continue to the next set-cookie\n                    // header\n                    if ($x == 0) continue 2;\n                    // check for secure flag\n                    if (strtolower(trim($key_val[0])) == 'secure') $tmp_cookie['secure'] = true;\n                    // continue to next param\n                    continue;\n                }\n                list($key, $val) = array_map('trim', $key_val);\n                // first name=value pair is the cookie name and value\n                // the name and value are stored under 'name' and 'value' to avoid conflicts\n                // with later parameters.\n                if ($x == 0) {\n                    $tmp_cookie = array('name'=>$key, 'value'=>$val);\n                    continue;\n                }\n                $key = strtolower($key);\n                if (in_array($key, array('expires', 'path', 'domain', 'secure'))) {\n                    $tmp_cookie[$key] = $val;\n                }\n            }\n            //\n            // set cookie\n            //\n            // check domain\n            if (isset($tmp_cookie['domain']) && ($tmp_cookie['domain'] != $request_host) &&\n                    ($tmp_cookie['domain'] != \".$request_host\")) {\n                $domain = $tmp_cookie['domain'];\n                if ((strpos($domain, '.') === false) && ($domain != 'local')) {\n                    $this->debug(' - domain \"'.$domain.'\" has no dot and is not a local domain');\n                    continue;\n                }\n                if (preg_match('/\\.[0-9]+$/', $domain)) {\n                    $this->debug(' - domain \"'.$domain.'\" appears to be an ip address');\n                    continue;\n                }\n                if (substr($domain, 0, 1) != '.') $domain = \".$domain\";\n                if (!$this->_domain_match($request_host, $domain)) {\n                    $this->debug(' - request host \"'.$request_host.'\" does not domain-match \"'.$domain.'\"');\n                    continue;\n                }\n            } else {\n                // if domain is not specified in the set-cookie header, domain will default to\n                // the request host\n                $domain = $request_host;\n            }\n            // check path\n            if (isset($tmp_cookie['path']) && ($tmp_cookie['path'] != '')) {\n                $path = urldecode($tmp_cookie['path']);\n                if (!$this->_path_match($request_path, $path)) {\n                    $this->debug(' - request path \"'.$request_path.'\" does not path-match \"'.$path.'\"');\n                    continue;\n                }\n            } else {\n                $path = $request_path;\n                $path = substr($path, 0, strrpos($path, '/'));\n                if ($path == '') $path = '/';\n            }\n            // check if secure\n            $secure = (isset($tmp_cookie['secure'])) ? true : false;\n            // check expiry\n            if (isset($tmp_cookie['expires'])) {\n                if (($expires = strtotime($tmp_cookie['expires'])) < 0) {\n                    $expires = null;\n                }\n            } else {\n                $expires = null;\n            }\n            // set cookie\n            $this->set_cookie($domain, $path, $tmp_cookie['name'], $tmp_cookie['value'], $secure, $expires);\n        }\n    }\n\t\n\t// return array of set-cookie values extracted from HTTP response headers (string $h)\n\tpublic function extractCookies($h) {\n        $x = 0;\n        $lines = 0;\n        $headers = array();\n        $last_match = false;\n\t\t$h = explode(\"\\n\", $h);\n        foreach ($h as $line) {\n\t\t\t$line = rtrim($line);\n            $lines++;\n\n            $trimmed_line = trim($line);\n            if (isset($line_last)) {\n                // check if we have \\r\\n\\r\\n (indicating the end of headers)\n                // some servers will not use CRLF (\\r\\n), so we make CR (\\r) optional.\n                // if (preg_match('/\\015?\\012\\015?\\012/', $line_last.$line)) {\n                //     break;\n                // }\n                // As an alternative, we can check if the current trimmed line is empty\n                if ($trimmed_line == '') {\n                    break;\n                }\n\n                // check for continuation line...\n                // RFC 2616 Section 2.2 \"Basic Rules\":\n                // HTTP/1.1 header field values can be folded onto multiple lines if the\n                // continuation line begins with a space or horizontal tab. All linear\n                // white space, including folding, has the same semantics as SP. A\n                // recipient MAY replace any linear white space with a single SP before\n                // interpreting the field value or forwarding the message downstream.\n                if ($last_match && preg_match('/^\\s+(.*)/', $line, $match)) {\n                    // append to previous header value\n                    $headers[$x-1] .= ' '.rtrim($match[1]);\n                    continue;\n                }\n            }\n            $line_last = $line;\n\n            // split header name and value\n            if (preg_match('/^Set-Cookie\\s*:\\s*(.*)/i', $line, $match)) {\n                $headers[$x++] = rtrim($match[1]);\n                $last_match = true;\n            } else {\n                $last_match = false;\n            }\n        }\n        return $headers;\n\t}\n\n    /**\n    * Set Cookie\n    * @param string $domain\n    * @param string $path\n    * @param string $name cookie name\n    * @param string $value cookie value\n    * @param bool $secure\n    * @param int $expires expiry time (null if session cookie, <= 0 will delete cookie)\n    * @return void\n    */\n    function set_cookie($domain, $path, $name, $value, $secure=false, $expires=null)\n    {\n        if ($domain == '') return;\n        if ($path == '') return;\n        if ($name == '') return;\n        // check if cookie needs to go\n        if (isset($expires) && ($expires <= 0)) {\n            if (isset($this->cookies[$domain][$path][$name])) unset($this->cookies[$domain][$path][$name]);\n            return;\n        }\n        if ($value == '') return;\n        $this->cookies[$domain][$path][$name] = array($value, $secure, $expires);\n        return;\n    }\n\n    /**\n    * Clear cookies - [domain [,path [,name]]] - call method with no arguments to clear all cookies.\n    * @param string $domain\n    * @param string $path\n    * @param string $name\n    * @return void\n    */\n    function clear($domain=null, $path=null, $name=null)\n    {\n        if (!isset($domain)) {\n            $this->cookies = array();\n        } elseif (!isset($path)) {\n            if (isset($this->cookies[$domain])) unset($this->cookies[$domain]);\n        } elseif (!isset($name)) {\n            if (isset($this->cookies[$domain][$path])) unset($this->cookies[$domain][$path]);\n        } elseif (isset($name)) {\n            if (isset($this->cookies[$domain][$path][$name])) unset($this->cookies[$domain][$path][$name]);\n        }\n    }\n\n    /**\n    * Compare string length - used for sorting\n    * @access private\n    * @return int\n    */\n    function _cmp_length($a, $b)\n    {\n        $la = strlen($a); $lb = strlen($b);\n        if ($la == $lb) return 0;\n        return ($la > $lb) ? -1 : 1;\n    }\n\n    /**\n    * Reduce domain\n    * @param string $domain\n    * @return string\n    * @access private\n    */\n    function _reduce_domain($domain)\n    {\n        if ($domain == '') return '';\n        if (substr($domain, 0, 1) == '.') return substr($domain, 1);\n        return substr($domain, strpos($domain, '.'));\n    }\n\n    /**\n    * Path match - check if path1 path-matches path2\n    *\n    * From RFC 2965: \n    *   <i>For two strings that represent paths, P1 and P2, P1 path-matches P2\n    *   if P2 is a prefix of P1 (including the case where P1 and P2 string-\n    *   compare equal).  Thus, the string /tec/waldo path-matches /tec.</i>\n    * @param string $path1\n    * @param string $path2\n    * @return bool\n    * @access private\n    */\n    function _path_match($path1, $path2)\n    {\n        return (substr($path1, 0, strlen($path2)) == $path2);\n    }\n\n    /**\n    * Domain match - check if domain1 domain-matches domain2\n    *\n    * A few extracts from RFC 2965: \n    *  -  A Set-Cookie2 from request-host y.x.foo.com for Domain=.foo.com\n    *     would be rejected, because H is y.x and contains a dot.\n    *\n    *  -  A Set-Cookie2 from request-host x.foo.com for Domain=.foo.com\n    *     would be accepted.\n    *\n    *  -  A Set-Cookie2 with Domain=.com or Domain=.com., will always be\n    *     rejected, because there is no embedded dot.\n    *\n    *  -  A Set-Cookie2 from request-host example for Domain=.local will\n    *     be accepted, because the effective host name for the request-\n    *     host is example.local, and example.local domain-matches .local.\n    *\n    * I'm ignoring the first point for now (must check to see how other browsers handle\n    * this rule for Set-Cookie headers)\n    *\n    * @param string $domain1\n    * @param string $domain2\n    * @return bool\n    * @access private\n    */\n    function _domain_match($domain1, $domain2)\n    {\n        $domain1 = strtolower($domain1);\n        $domain2 = strtolower($domain2);\n        while (strpos($domain1, '.') !== false) {\n            if ($domain1 == $domain2) return true;\n            $domain1 = $this->_reduce_domain($domain1);\n            continue;\n        }\n        return false;\n    }\n}\n?>"
  },
  {
    "path": "libraries/humble-http-agent/HumbleHttpAgent.php",
    "content": "<?php\n/**\n * Humble HTTP Agent\n * \n * This class is designed to take advantage of parallel HTTP requests\n * offered by PHP's PECL HTTP extension or the curl_multi_* functions. \n * For environments which do not have these options, it reverts to standard sequential \n * requests (using file_get_contents())\n * \n * @version 1.4\n * @date 2013-05-10\n * @see http://php.net/HttpRequestPool\n * @author Keyvan Minoukadeh\n * @copyright 2011-2013 Keyvan Minoukadeh\n * @license http://www.gnu.org/licenses/agpl-3.0.html AGPL v3\n */\n\nclass HumbleHttpAgent\n{\n\tconst METHOD_REQUEST_POOL = 1;\n\tconst METHOD_CURL_MULTI = 2;\n\tconst METHOD_FILE_GET_CONTENTS = 4;\n\t//const UA_BROWSER = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1';\n\tconst UA_BROWSER = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.92 Safari/535.2';\n\tconst UA_PHP = 'PHP/5.4';\n\tconst REF_GOOGLE = 'http://www.google.co.uk/url?sa=t&source=web&cd=1';\n\t\n\tprotected $requests = array();\n\tprotected $redirectQueue = array();\n\tprotected $requestOptions;\n\tprotected $maxParallelRequests = 5;\n\tprotected $cache = null;\n\tprotected $httpContext;\n\tprotected $minimiseMemoryUse = false; //TODO\n\tprotected $cookieJar;\n\tpublic $method;\n\tpublic $debug = false;\n\tpublic $debugVerbose = false;\n\tpublic $rewriteHashbangFragment = true; // see http://code.google.com/web/ajaxcrawling/docs/specification.html\n\tpublic $maxRedirects = 5;\n\tpublic $userAgentMap = array();\n\tpublic $rewriteUrls = array();\n\tpublic $userAgentDefault;\n\tpublic $referer;\n\t//public $userAgent = 'Mozilla/5.0';\n\t\n\t// Prevent certain file/mime types\n\t// HTTP responses which match these content types will\n\t// be returned without body.\n\tpublic $headerOnlyTypes = array();\n\t// URLs ending with one of these extensions will\n\t// prompt Humble HTTP Agent to send a HEAD request first\n\t// to see if returned content type matches $headerOnlyTypes.\n\tpublic $headerOnlyClues = array('pdf','mp3','zip','exe','gif','gzip','gz','jpeg','jpg','mpg','mpeg','png','ppt','mov');\n\t// AJAX triggers to search for.\n\t// for AJAX sites, e.g. Blogger with its dynamic views templates.\n\tpublic $ajaxTriggers = array(\"<meta name='fragment' content='!'\",'<meta name=\"fragment\" content=\"!\"',\"<meta content='!' name='fragment'\",'<meta content=\"!\" name=\"fragment\"');\n\t\n\t//TODO: set max file size\n\t//TODO: normalise headers\n\t\n\tfunction __construct($requestOptions=null, $method=null) {\n\t\t$this->userAgentDefault = self::UA_BROWSER;\n\t\t$this->referer = self::REF_GOOGLE;\n\t\t// set the request method\n\t\tif (in_array($method, array(1,2,4))) {\n\t\t\t$this->method = $method;\n\t\t} else {\n\t\t\tif (class_exists('HttpRequestPool')) {\n\t\t\t\t$this->method = self::METHOD_REQUEST_POOL;\n\t\t\t} elseif (function_exists('curl_multi_init')) {\n\t\t\t\t$this->method = self::METHOD_CURL_MULTI;\n\t\t\t} else {\n\t\t\t\t$this->method = self::METHOD_FILE_GET_CONTENTS;\n\t\t\t}\n\t\t}\n\t\tif ($this->method == self::METHOD_CURL_MULTI) {\n\t\t\trequire_once(dirname(__FILE__).'/RollingCurl.php');\n\t\t}\n\t\t// create cookie jar\n\t\t$this->cookieJar = new CookieJar();\n\t\t// set request options (redirect must be 0)\n\t\t$this->requestOptions = array(\n\t\t\t'timeout' => 15,\n\t\t\t'connecttimeout' => 15,\n\t\t\t'dns_cache_timeout' => 300,\n\t\t\t'redirect' => 0 // we handle redirects manually so we can rewrite the new hashbang URLs that are creeping up over the web\n\t\t\t// TODO: test onprogress?\n\t\t);\n\t\tif (is_array($requestOptions)) {\n\t\t\t$this->requestOptions = array_merge($this->requestOptions, $requestOptions);\n\t\t}\n\t\t$this->httpContext = array(\n\t\t\t'http' => array(\n\t\t\t\t'ignore_errors' => true,\n\t\t\t\t'timeout' => $this->requestOptions['timeout'],\n\t\t\t\t'max_redirects' => $this->requestOptions['redirect'],\n\t\t\t\t'header' => \"Accept: */*\\r\\n\"\n\t\t\t\t)\n\t\t\t);\n\t}\n\n\tpublic function initCache($dir, $level = 0, $cleanup = 100, $life = 3600) {\n\t\t$this->debug('HTTP cache TTL is set to '.$life.' sec.');\n\t\t$frontendOptions = array(\n\t\t\t'lifetime' => $life, // cache lifetime\n\t\t\t'automatic_serialization' => false,\n\t\t\t'write_control' => false,\n\t\t\t'automatic_cleaning_factor' => $cleanup,\n\t\t\t'ignore_user_abort' => false\n\t\t);\n\t\t$backendOptions = array(\n\t\t\t'cache_dir' => $dir.'/urls/', // directory where to put the cache files\n\t\t\t'file_locking' => false,\n\t\t\t'read_control' => true,\n\t\t\t'read_control_type' => 'strlen',\n\t\t\t'hashed_directory_level' => $level,\n\t\t\t'hashed_directory_perm' => 0777,\n\t\t\t'cache_file_perm' => 0664,\n\t\t\t'file_name_prefix' => 'ff'\n\t\t);\n\t\t// getting a Zend_Cache_Core object\n\t\t$this->cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);\n\t}\n\n\tprivate function isCached($url) {\n\t\tif (!$this->cache || !$url) return false;\n\t\treturn ($this->cache->test('request'.md5($url)) !== false);\n\t}\n\n\tprivate function setCached($url, $data) {\n\t\tif (!$this->cache || !$url || !$data) return;\n\t\t$this->cache->save(serialize($data), 'request'.md5($url));\n\t}\n\t\n\tprivate function getCached($url) {\n\t\tif (!$this->cache || !$url) return null;\n\t\treturn unserialize($this->cache->load('request'.md5($url)));\n\t}\n\n\tprotected function debug($msg) {\n\t\tif ($this->debug) {\n\t\t\t$mem = round(memory_get_usage()/1024, 2);\n\t\t\t$memPeak = round(memory_get_peak_usage()/1024, 2);\n\t\t\techo '* ',$msg,\"<br />\";\n\t\t\tif ($this->debugVerbose) echo ' - mem used: ',$mem,\" (peak: $memPeak)\";\n\t\t\techo \"\\n\";\n\t\t\tob_flush();\n\t\t\tflush();\n\t\t}\n\t}\n\t\n\tprotected function getUserAgent($url, $asArray=false) {\n\t\t$host = @parse_url($url, PHP_URL_HOST);\n\t\tif (strtolower(substr($host, 0, 4)) == 'www.') {\n\t\t\t$host = substr($host, 4);\n\t\t}\n\t\tif ($host) {\n\t\t\t$try = array($host);\n\t\t\t$split = explode('.', $host);\n\t\t\tif (count($split) > 1) {\n\t\t\t\tarray_shift($split);\n\t\t\t\t$try[] = '.'.implode('.', $split);\n\t\t\t}\n\t\t\tforeach ($try as $h) {\n\t\t\t\tif (isset($this->userAgentMap[$h])) {\n\t\t\t\t\t$ua = $this->userAgentMap[$h];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!isset($ua)) $ua = $this->userAgentDefault;\n\t\tif ($asArray) {\n\t\t\treturn array('User-Agent' => $ua);\n\t\t} else {\n\t\t\treturn 'User-Agent: '.$ua;\n\t\t}\n\t}\n\t\n\tpublic function rewriteHashbangFragment($url) {\n\t\t// return $url if there's no '#!'\n\t\tif (strpos($url, '#!') === false) return $url;\n\t\t// split $url and rewrite\n\t\t// TODO: is SimplePie_IRI included?\n\t\t$iri = new SimplePie_IRI($url);\n\t\t$fragment = substr($iri->fragment, 1); // strip '!'\n\t\t$iri->fragment = null;\n\t\tif (isset($iri->query)) {\n\t\t\tparse_str($iri->query, $query);\n\t\t} else {\n\t\t\t$query = array();\n\t\t}\n\t\t$query['_escaped_fragment_'] = (string)$fragment;\n\t\t$iri->query = str_replace('%2F', '/', http_build_query($query)); // needed for some sites\n\t\treturn $iri->get_iri();\n\t}\n\t\n\tpublic function getRedirectURLfromHTML($url, $html) {\n\t\t$redirect_url = $this->getMetaRefreshURL($url, $html);\n\t\tif (!$redirect_url) {\n\t\t\t$redirect_url = $this->getUglyURL($url, $html);\n\t\t}\n\t\treturn $redirect_url;\n\t}\n\t\n\tpublic function getMetaRefreshURL($url, $html) {\n\t\tif ($html == '') return false;\n\t\t// <meta HTTP-EQUIV=\"REFRESH\" content=\"0; url=http://www.bernama.com/bernama/v6/newsindex.php?id=943513\">\n\t\tif (!preg_match('!<meta http-equiv=[\"\\']?refresh[\"\\']? content=[\"\\']?[0-9];\\s*url=[\"\\']?([^\"\\'>]+)[\"\\']*>!i', $html, $match)) {\n\t\t\treturn false;\n\t\t}\n\t\t$redirect_url = $match[1];\n\t\tif (preg_match('!^https?://!i', $redirect_url)) {\n\t\t\t// already absolute\n\t\t\t$this->debug('Meta refresh redirect found (http-equiv=\"refresh\"), new URL: '.$redirect_url);\n\t\t\treturn $redirect_url;\n\t\t}\n\t\t// absolutize redirect URL\n\t\t$base = new SimplePie_IRI($url);\n\t\t// remove '//' in URL path (causes URLs not to resolve properly)\n\t\tif (isset($base->path)) $base->path = preg_replace('!//+!', '/', $base->path);\n\t\tif ($absolute = SimplePie_IRI::absolutize($base, $redirect_url)) {\n\t\t\t$this->debug('Meta refresh redirect found (http-equiv=\"refresh\"), new URL: '.$absolute);\n\t\t\treturn $absolute;\n\t\t}\n\t\treturn false;\n\t}\t\n\t\n\tpublic function getUglyURL($url, $html) {\n\t\tif ($html == '') return false;\n\t\t$found = false;\n\t\tforeach ($this->ajaxTriggers as $string) {\n\t\t\tif (stripos($html, $string)) {\n\t\t\t\t$found = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!$found) return false;\n\t\t$iri = new SimplePie_IRI($url);\n\t\tif (isset($iri->query)) {\n\t\t\tparse_str($iri->query, $query);\n\t\t} else {\n\t\t\t$query = array();\n\t\t}\n\t\t$query['_escaped_fragment_'] = '';\n\t\t$iri->query = str_replace('%2F', '/', http_build_query($query)); // needed for some sites\n\t\t$ugly_url = $iri->get_iri();\n\t\t$this->debug('AJAX trigger (meta name=\"fragment\" content=\"!\") found, new URL: '.$ugly_url);\n\t\treturn $ugly_url;\n\t}\n\t\n\tpublic function removeFragment($url) {\n\t\t$pos = strpos($url, '#');\n\t\tif ($pos === false) {\n\t\t\treturn $url;\n\t\t} else {\n\t\t\treturn substr($url, 0, $pos);\n\t\t}\n\t}\n\t\n\tpublic function rewriteUrls($url) {\n\t\tforeach ($this->rewriteUrls as $find => $action) {\n\t\t\tif (strpos($url, $find) !== false) {\n\t\t\t\tif (is_array($action)) {\n\t\t\t\t\treturn strtr($url, $action);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn $url;\n\t}\n\t\n\tpublic function enableDebug($bool=true) {\n\t\t$this->debug = (bool)$bool;\n\t}\n\t\n\tpublic function minimiseMemoryUse($bool = true) {\n\t\t$this->minimiseMemoryUse = $bool;\n\t}\n\t\n\tpublic function setMaxParallelRequests($max) {\n\t\t$this->maxParallelRequests = $max;\n\t}\n\n\tpublic function validateUrl($url) {\n\t\t$url = filter_var($url, FILTER_SANITIZE_URL);\n\t\t$test = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED);\n\t\t// deal with bug http://bugs.php.net/51192 (present in PHP 5.2.13 and PHP 5.3.2)\n\t\tif ($test === false) {\n\t\t\t$test = filter_var(strtr($url, '-', '_'), FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED);\n\t\t}\n\t\tif ($test !== false && $test !== null && preg_match('!^https?://!', $url)) {\n\t\t\treturn $url;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\tpublic function fetchAll(array $urls) {\n\t\t$this->fetchAllOnce($urls, $isRedirect=false);\n\t\t$redirects = 0;\n\t\twhile (!empty($this->redirectQueue) && ++$redirects <= $this->maxRedirects) {\n\t\t\t$this->debug(\"Following redirects #$redirects...\");\n\t\t\t$this->fetchAllOnce($this->redirectQueue, $isRedirect=true);\n\t\t}\n\t}\n\t\n\t// fetch all URLs without following redirects\n\tpublic function fetchAllOnce(array $urls, $isRedirect=false) {\n\t\tif (!$isRedirect) $urls = array_unique($urls);\n\t\tif (empty($urls)) return;\n\t\t\n\t\t//////////////////////////////////////////////////////\n\t\t// parallel (HttpRequestPool)\n\t\tif ($this->method == self::METHOD_REQUEST_POOL) {\n\t\t\t$this->debug('Starting parallel fetch (HttpRequestPool)');\n\t\t\ttry {\n\t\t\t\twhile (count($urls) > 0) {\n\t\t\t\t\t$this->debug('Processing set of '.min($this->maxParallelRequests, count($urls)));\n\t\t\t\t\t$subset = array_splice($urls, 0, $this->maxParallelRequests);\n\t\t\t\t\t$pool = new HttpRequestPool();\n\t\t\t\t\tforeach ($subset as $orig => $url) {\n\t\t\t\t\t\tif (!$isRedirect) $orig = $url;\n\t\t\t\t\t\tunset($this->redirectQueue[$orig]);\n\t\t\t\t\t\t$this->debug(\"...$url\");\n\t\t\t\t\t\tif (!$isRedirect && isset($this->requests[$url])) {\n\t\t\t\t\t\t\t$this->debug(\"......in memory\");\n\t\t\t\t\t\t} elseif ($this->isCached($url)) {\n\t\t\t\t\t\t\t$this->debug(\"......is cached\");\n\t\t\t\t\t\t\tif (!$this->minimiseMemoryUse) {\n\t\t\t\t\t\t\t\t$this->requests[$url] = $this->getCached($url);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$this->debug(\"......adding to pool\");\n\t\t\t\t\t\t\t$req_url = $this->rewriteUrls($url);\n\t\t\t\t\t\t\t$req_url = ($this->rewriteHashbangFragment) ? $this->rewriteHashbangFragment($req_url) : $req_url;\n\t\t\t\t\t\t\t$req_url = $this->removeFragment($req_url);\n\t\t\t\t\t\t\tif (!empty($this->headerOnlyTypes) && !isset($this->requests[$orig]['wrongGuess']) && $this->possibleUnsupportedType($req_url)) {\n\t\t\t\t\t\t\t\t$_meth = HttpRequest::METH_HEAD;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t$_meth = HttpRequest::METH_GET;\n\t\t\t\t\t\t\t\tunset($this->requests[$orig]['wrongGuess']);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$httpRequest = new HttpRequest($req_url, $_meth, $this->requestOptions);\n\t\t\t\t\t\t\t// send cookies, if we have any\n\t\t\t\t\t\t\tif ($cookies = $this->cookieJar->getMatchingCookies($req_url)) {\n\t\t\t\t\t\t\t\t$this->debug(\"......sending cookies: $cookies\");\n\t\t\t\t\t\t\t\t$httpRequest->addHeaders(array('Cookie' => $cookies));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t//$httpRequest->addHeaders(array('User-Agent' => $this->userAgent));\n\t\t\t\t\t\t\t$httpRequest->addHeaders($this->getUserAgent($req_url, true));\n\t\t\t\t\t\t\t// add referer for picky sites\n\t\t\t\t\t\t\t$httpRequest->addheaders(array('Referer' => $this->referer));\n\t\t\t\t\t\t\t$this->requests[$orig] = array('headers'=>null, 'body'=>null, 'httpRequest'=>$httpRequest);\n\t\t\t\t\t\t\t$this->requests[$orig]['original_url'] = $orig;\n\t\t\t\t\t\t\t$pool->attach($httpRequest);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// did we get anything into the pool?\n\t\t\t\t\tif (count($pool) > 0) {\n\t\t\t\t\t\t$this->debug('Sending request...');\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t$pool->send();\n\t\t\t\t\t\t} catch (HttpRequestPoolException $e) {\n\t\t\t\t\t\t\t// do nothing\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$this->debug('Received responses');\n\t\t\t\t\t\tforeach($subset as $orig => $url) {\n\t\t\t\t\t\t\tif (!$isRedirect) $orig = $url;\n\t\t\t\t\t\t\t$request = $this->requests[$orig]['httpRequest'];\n\t\t\t\t\t\t\t//$this->requests[$orig]['headers'] = $this->headersToString($request->getResponseHeader());\n\t\t\t\t\t\t\t// getResponseHeader() doesn't return status line, so, for consistency...\n\t\t\t\t\t\t\t$this->requests[$orig]['headers'] = substr($request->getRawResponseMessage(), 0, $request->getResponseInfo('header_size'));\n\t\t\t\t\t\t\t// check content type\n\t\t\t\t\t\t\t// TODO: use getResponseHeader('content-type') or getResponseInfo()\n\t\t\t\t\t\t\tif ($this->headerOnlyType($this->requests[$orig]['headers'])) {\n\t\t\t\t\t\t\t\t$this->requests[$orig]['body'] = '';\n\t\t\t\t\t\t\t\t$_header_only_type = true;\n\t\t\t\t\t\t\t\t$this->debug('Header only type returned');\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t$this->requests[$orig]['body'] = $request->getResponseBody();\n\t\t\t\t\t\t\t\t$_header_only_type = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$this->requests[$orig]['effective_url'] = $request->getResponseInfo('effective_url');\n\t\t\t\t\t\t\t$this->requests[$orig]['status_code'] = $status_code = $request->getResponseCode();\n\t\t\t\t\t\t\t// is redirect?\n\t\t\t\t\t\t\tif ((in_array($status_code, array(300, 301, 302, 303, 307)) || $status_code > 307 && $status_code < 400) && $request->getResponseHeader('location')) {\n\t\t\t\t\t\t\t\t$redirectURL = $request->getResponseHeader('location');\n\t\t\t\t\t\t\t\tif (!preg_match('!^https?://!i', $redirectURL)) {\n\t\t\t\t\t\t\t\t\t$redirectURL = SimplePie_Misc::absolutize_url($redirectURL, $url);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ($this->validateURL($redirectURL)) {\n\t\t\t\t\t\t\t\t\t$this->debug('Redirect detected. Valid URL: '.$redirectURL);\n\t\t\t\t\t\t\t\t\t// store any cookies\n\t\t\t\t\t\t\t\t\t$cookies = $request->getResponseHeader('set-cookie');\n\t\t\t\t\t\t\t\t\tif ($cookies && !is_array($cookies)) $cookies = array($cookies);\n\t\t\t\t\t\t\t\t\tif ($cookies) $this->cookieJar->storeCookies($url, $cookies);\n\t\t\t\t\t\t\t\t\t$this->redirectQueue[$orig] = $redirectURL;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t$this->debug('Redirect detected. Invalid URL: '.$redirectURL);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} elseif (!$_header_only_type && $request->getMethod() === HttpRequest::METH_HEAD) {\n\t\t\t\t\t\t\t\t// the response content-type did not match our 'header only' types, \n\t\t\t\t\t\t\t\t// but we'd issues a HEAD request because we assumed it would. So\n\t\t\t\t\t\t\t\t// let's queue a proper GET request for this item...\n\t\t\t\t\t\t\t\t$this->debug('Wrong guess at content-type, queing GET request');\n\t\t\t\t\t\t\t\t$this->requests[$orig]['wrongGuess'] = true;\n\t\t\t\t\t\t\t\t$this->redirectQueue[$orig] = $this->requests[$orig]['effective_url'];\n\t\t\t\t\t\t\t} elseif (strpos($this->requests[$orig]['effective_url'], '_escaped_fragment_') === false) {\n\t\t\t\t\t\t\t\t// check for <meta name='fragment' content='!'/>\n\t\t\t\t\t\t\t\t// for AJAX sites, e.g. Blogger with its dynamic views templates.\n\t\t\t\t\t\t\t\t// Based on Google's spec: https://developers.google.com/webmasters/ajax-crawling/docs/specification\n\t\t\t\t\t\t\t\tif (isset($this->requests[$orig]['body'])) {\n\t\t\t\t\t\t\t\t\t$redirectURL = $this->getRedirectURLfromHTML($this->requests[$orig]['effective_url'], substr($this->requests[$orig]['body'], 0, 4000));\n\t\t\t\t\t\t\t\t\tif ($redirectURL) {\n\t\t\t\t\t\t\t\t\t\t$this->redirectQueue[$orig] = $redirectURL;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t//die($url.' -multi- '.$request->getResponseInfo('effective_url'));\n\n\t\t\t\t\t\t\tif (isset($this->cache) && isset($this->requests[$orig]['body'])) {\n\t\t\t\t\t\t\t\t $this->setCached($orig, $this->requests[$orig]);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t$pool->detach($request);\n\t\t\t\t\t\t\tunset($this->requests[$orig]['httpRequest'], $request);\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\tif ($this->minimiseMemoryUse) {\n\t\t\t\t\t\t\t\tif ($this->cache($url)) {\n\t\t\t\t\t\t\t\t\tunset($this->requests[$url]);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (HttpException $e) {\n\t\t\t\t$this->debug($e);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\t\n\t\t//////////////////////////////////////////////////////////\n\t\t// parallel (curl_multi_*)\n\t\telseif ($this->method == self::METHOD_CURL_MULTI) {\n\t\t\t$this->debug('Starting parallel fetch (curl_multi_*)');\n\t\t\twhile (count($urls) > 0) {\n\t\t\t\t$this->debug('Processing set of '.min($this->maxParallelRequests, count($urls)));\n\t\t\t\t$subset = array_splice($urls, 0, $this->maxParallelRequests);\n\t\t\t\t$pool = new RollingCurl(array($this, 'handleCurlResponse'));\n\t\t\t\t$pool->window_size = count($subset);\t\t\n\t\t\t\t\n\t\t\t\tforeach ($subset as $orig => $url) {\n\t\t\t\t\tif (!$isRedirect) $orig = $url;\n\t\t\t\t\tunset($this->redirectQueue[$orig]);\n\t\t\t\t\t$this->debug(\"...$url\");\n\t\t\t\t\tif (!$isRedirect && isset($this->requests[$url])) {\n\t\t\t\t\t\t$this->debug(\"......in memory\");\n\t\t\t\t\t} elseif ($this->isCached($url)) {\n\t\t\t\t\t\t$this->debug(\"......is cached\");\n\t\t\t\t\t\tif (!$this->minimiseMemoryUse) {\n\t\t\t\t\t\t\t$this->requests[$url] = $this->getCached($url);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this->debug(\"......adding to pool\");\n\t\t\t\t\t\t$req_url = $this->rewriteUrls($url);\n\t\t\t\t\t\t$req_url = ($this->rewriteHashbangFragment) ? $this->rewriteHashbangFragment($req_url) : $req_url;\n\t\t\t\t\t\t$req_url = $this->removeFragment($req_url);\n\t\t\t\t\t\tif (!empty($this->headerOnlyTypes) && !isset($this->requests[$orig]['wrongGuess']) && $this->possibleUnsupportedType($req_url)) {\n\t\t\t\t\t\t\t$_meth = 'HEAD';\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$_meth = 'GET';\n\t\t\t\t\t\t\tunset($this->requests[$orig]['wrongGuess']);\n\t\t\t\t\t\t}\t\t\t\t\t\t\n\t\t\t\t\t\t$headers = array();\n\t\t\t\t\t\t//$headers[] = 'User-Agent: '.$this->userAgent;\n\t\t\t\t\t\t$headers[] = $this->getUserAgent($req_url);\n\t\t\t\t\t\t// add referer for picky sites\n\t\t\t\t\t\t$headers[] = 'Referer: '.$this->referer;\n\t\t\t\t\t\t// send cookies, if we have any\n\t\t\t\t\t\tif ($cookies = $this->cookieJar->getMatchingCookies($req_url)) {\n\t\t\t\t\t\t\t$this->debug(\"......sending cookies: $cookies\");\n\t\t\t\t\t\t\t$headers[] = 'Cookie: '.$cookies;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$httpRequest = new RollingCurlRequest($req_url, $_meth, null, $headers, array(\n\t\t\t\t\t\t\tCURLOPT_CONNECTTIMEOUT => $this->requestOptions['timeout'],\n\t\t\t\t\t\t\tCURLOPT_TIMEOUT => $this->requestOptions['timeout']\n\t\t\t\t\t\t\t));\n\t\t\t\t\t\t$httpRequest->set_original_url($orig);\n\t\t\t\t\t\t$this->requests[$orig] = array('headers'=>null, 'body'=>null, 'httpRequest'=>$httpRequest);\n\t\t\t\t\t\t$this->requests[$orig]['original_url'] = $orig; // TODO: is this needed anymore?\n\t\t\t\t\t\t$pool->add($httpRequest);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// did we get anything into the pool?\n\t\t\t\tif (count($pool) > 0) {\n\t\t\t\t\t$this->debug('Sending request...');\n\t\t\t\t\t$pool->execute(); // this will call handleCurlResponse() and populate $this->requests[$orig]\n\t\t\t\t\t$this->debug('Received responses');\n\t\t\t\t\tforeach($subset as $orig => $url) {\n\t\t\t\t\t\tif (!$isRedirect) $orig = $url;\n\t\t\t\t\t\t// $this->requests[$orig]['headers']\n\t\t\t\t\t\t// $this->requests[$orig]['body']\n\t\t\t\t\t\t// $this->requests[$orig]['effective_url']\n\t\t\t\t\t\t// check content type\n\t\t\t\t\t\tif ($this->headerOnlyType($this->requests[$orig]['headers'])) {\n\t\t\t\t\t\t\t$this->requests[$orig]['body'] = '';\n\t\t\t\t\t\t\t$_header_only_type = true;\n\t\t\t\t\t\t\t$this->debug('Header only type returned');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$_header_only_type = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$status_code = $this->requests[$orig]['status_code'];\n\t\t\t\t\t\tif ((in_array($status_code, array(300, 301, 302, 303, 307)) || $status_code > 307 && $status_code < 400) && isset($this->requests[$orig]['location'])) {\n\t\t\t\t\t\t\t$redirectURL = $this->requests[$orig]['location'];\n\t\t\t\t\t\t\tif (!preg_match('!^https?://!i', $redirectURL)) {\n\t\t\t\t\t\t\t\t$redirectURL = SimplePie_Misc::absolutize_url($redirectURL, $url);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ($this->validateURL($redirectURL)) {\n\t\t\t\t\t\t\t\t$this->debug('Redirect detected. Valid URL: '.$redirectURL);\n\t\t\t\t\t\t\t\t// store any cookies\n\t\t\t\t\t\t\t\t$cookies = $this->cookieJar->extractCookies($this->requests[$orig]['headers']);\n\t\t\t\t\t\t\t\tif (!empty($cookies)) $this->cookieJar->storeCookies($url, $cookies);\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t$this->redirectQueue[$orig] = $redirectURL;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t$this->debug('Redirect detected. Invalid URL: '.$redirectURL);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} elseif (!$_header_only_type && $this->requests[$orig]['method'] == 'HEAD') {\n\t\t\t\t\t\t\t// the response content-type did not match our 'header only' types, \n\t\t\t\t\t\t\t// but we'd issues a HEAD request because we assumed it would. So\n\t\t\t\t\t\t\t// let's queue a proper GET request for this item...\n\t\t\t\t\t\t\t$this->debug('Wrong guess at content-type, queing GET request');\n\t\t\t\t\t\t\t$this->requests[$orig]['wrongGuess'] = true;\n\t\t\t\t\t\t\t$this->redirectQueue[$orig] = $this->requests[$orig]['effective_url'];\n\t\t\t\t\t\t} elseif (strpos($this->requests[$orig]['effective_url'], '_escaped_fragment_') === false) {\n\t\t\t\t\t\t\t// check for <meta name='fragment' content='!'/>\n\t\t\t\t\t\t\t// for AJAX sites, e.g. Blogger with its dynamic views templates.\n\t\t\t\t\t\t\t// Based on Google's spec: https://developers.google.com/webmasters/ajax-crawling/docs/specification\n\t\t\t\t\t\t\tif (isset($this->requests[$orig]['body'])) {\n\t\t\t\t\t\t\t\t$redirectURL = $this->getRedirectURLfromHTML($this->requests[$orig]['effective_url'], substr($this->requests[$orig]['body'], 0, 4000));\n\t\t\t\t\t\t\t\tif ($redirectURL) {\n\t\t\t\t\t\t\t\t\t$this->redirectQueue[$orig] = $redirectURL;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isset($this->cache) && isset($this->requests[$orig]['body'])) {\n\t\t\t\t\t\t\t$this->setCached($orig, $this->requests[$orig]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// die($url.' -multi- '.$request->getResponseInfo('effective_url'));\n\t\t\t\t\t\tunset($this->requests[$orig]['httpRequest'], $this->requests[$orig]['method']);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//////////////////////////////////////////////////////\n\t\t// sequential (file_get_contents)\n\t\telse {\n\t\t\t$this->debug('Starting sequential fetch (file_get_contents)');\n\t\t\t$this->debug('Processing set of '.count($urls));\n\t\t\tforeach ($urls as $orig => $url) {\n\t\t\t\tif (!$isRedirect) $orig = $url;\n\t\t\t\tunset($this->redirectQueue[$orig]);\n\t\t\t\t$this->debug(\"...$url\");\n\t\t\t\tif (!$isRedirect && isset($this->requests[$url])) {\n\t\t\t\t\t$this->debug(\"......in memory\");\n\t\t\t\t/*\n\t\t\t\t} elseif ($this->isCached($url)) {\n\t\t\t\t\t$this->debug(\"......is cached\");\n\t\t\t\t\tif (!$this->minimiseMemoryUse) {\n\t\t\t\t\t\t$this->requests[$url] = $this->getCached($url);\n\t\t\t\t\t}\n\t\t\t\t*/\n\t\t\t\t} else {\n\t\t\t\t\t$this->debug(\"Sending request for $url\");\n\t\t\t\t\t$this->requests[$orig]['original_url'] = $orig;\n\t\t\t\t\t$req_url = $this->rewriteUrls($url);\n\t\t\t\t\t$req_url = ($this->rewriteHashbangFragment) ? $this->rewriteHashbangFragment($req_url) : $req_url;\n\t\t\t\t\t$req_url = $this->removeFragment($req_url);\n\t\t\t\t\t// send cookies, if we have any\n\t\t\t\t\t$httpContext = $this->httpContext;\n\t\t\t\t\t$httpContext['http']['header'] .= $this->getUserAgent($req_url).\"\\r\\n\";\n\t\t\t\t\t// add referer for picky sites\n\t\t\t\t\t$httpContext['http']['header'] .= 'Referer: '.$this->referer.\"\\r\\n\";\n\t\t\t\t\tif ($cookies = $this->cookieJar->getMatchingCookies($req_url)) {\n\t\t\t\t\t\t$this->debug(\"......sending cookies: $cookies\");\n\t\t\t\t\t\t$httpContext['http']['header'] .= 'Cookie: '.$cookies.\"\\r\\n\";\n\t\t\t\t\t}\n\t\t\t\t\tif (false !== ($html = @file_get_contents($req_url, false, stream_context_create($httpContext)))) {\n\t\t\t\t\t\t$this->debug('Received response');\n\t\t\t\t\t\t// get status code\n\t\t\t\t\t\tif (!isset($http_response_header[0]) || !preg_match('!^HTTP/\\d+\\.\\d+\\s+(\\d+)!', trim($http_response_header[0]), $match)) {\n\t\t\t\t\t\t\t$this->debug('Error: no status code found');\n\t\t\t\t\t\t\t// TODO: handle error - no status code\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$this->requests[$orig]['headers'] = $this->headersToString($http_response_header, false);\n\t\t\t\t\t\t\t// check content type\n\t\t\t\t\t\t\tif ($this->headerOnlyType($this->requests[$orig]['headers'])) {\n\t\t\t\t\t\t\t\t$this->requests[$orig]['body'] = '';\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t$this->requests[$orig]['body'] = $html;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$this->requests[$orig]['effective_url'] = $req_url;\n\t\t\t\t\t\t\t$this->requests[$orig]['status_code'] = $status_code = (int)$match[1];\n\t\t\t\t\t\t\tunset($match);\n\t\t\t\t\t\t\t// handle redirect\n\t\t\t\t\t\t\tif (preg_match('/^Location:(.*?)$/mi', $this->requests[$orig]['headers'], $match)) {\n\t\t\t\t\t\t\t\t$this->requests[$orig]['location'] =  trim($match[1]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ((in_array($status_code, array(300, 301, 302, 303, 307)) || $status_code > 307 && $status_code < 400) && isset($this->requests[$orig]['location'])) {\n\t\t\t\t\t\t\t\t$redirectURL = $this->requests[$orig]['location'];\n\t\t\t\t\t\t\t\tif (!preg_match('!^https?://!i', $redirectURL)) {\n\t\t\t\t\t\t\t\t\t$redirectURL = SimplePie_Misc::absolutize_url($redirectURL, $url);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ($this->validateURL($redirectURL)) {\n\t\t\t\t\t\t\t\t\t$this->debug('Redirect detected. Valid URL: '.$redirectURL);\n\t\t\t\t\t\t\t\t\t// store any cookies\n\t\t\t\t\t\t\t\t\t$cookies = $this->cookieJar->extractCookies($this->requests[$orig]['headers']);\n\t\t\t\t\t\t\t\t\tif (!empty($cookies)) $this->cookieJar->storeCookies($url, $cookies);\n\t\t\t\t\t\t\t\t\t$this->redirectQueue[$orig] = $redirectURL;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t$this->debug('Redirect detected. Invalid URL: '.$redirectURL);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} elseif (strpos($this->requests[$orig]['effective_url'], '_escaped_fragment_') === false) {\n\t\t\t\t\t\t\t\t// check for <meta name='fragment' content='!'/>\n\t\t\t\t\t\t\t\t// for AJAX sites, e.g. Blogger with its dynamic views templates.\n\t\t\t\t\t\t\t\t// Based on Google's spec: https://developers.google.com/webmasters/ajax-crawling/docs/specification\n\t\t\t\t\t\t\t\tif (isset($this->requests[$orig]['body'])) {\n\t\t\t\t\t\t\t\t\t$redirectURL = $this->getRedirectURLfromHTML($this->requests[$orig]['effective_url'], substr($this->requests[$orig]['body'], 0, 4000));\n\t\t\t\t\t\t\t\t\tif ($redirectURL) {\n\t\t\t\t\t\t\t\t\t\t$this->redirectQueue[$orig] = $redirectURL;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$this->debug('Error retrieving URL');\n\t\t\t\t\t\t//print_r($req_url);\n\t\t\t\t\t\t//print_r($http_response_header);\n\t\t\t\t\t\t//print_r($html);\n\t\t\t\t\t\t\n\t\t\t\t\t\t// TODO: handle error - failed to retrieve URL\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic function handleCurlResponse($response, $info, $request) {\n\t\t$orig = $request->url_original;\n\t\t$this->requests[$orig]['headers'] = substr($response, 0, $info['header_size']);\n\t\t$this->requests[$orig]['body'] = substr($response, $info['header_size']);\n\t\t$this->requests[$orig]['method'] = $request->method;\n\t\t$this->requests[$orig]['effective_url'] = $info['url'];\n\t\t$this->requests[$orig]['status_code'] = (int)$info['http_code'];\n\t\tif (preg_match('/^Location:(.*?)$/mi', $this->requests[$orig]['headers'], $match)) {\n\t\t\t$this->requests[$orig]['location'] =  trim($match[1]);\n\t\t}\n\t}\n\t\n\tprotected function headersToString(array $headers, $associative=true) {\n\t\tif (!$associative) {\n\t\t\treturn implode(\"\\n\", $headers);\n\t\t} else {\n\t\t\t$str = '';\n\t\t\tforeach ($headers as $key => $val) {\n\t\t\t\tif (is_array($val)) {\n\t\t\t\t\tforeach ($val as $v) $str .= \"$key: $v\\n\";\n\t\t\t\t} else {\n\t\t\t\t\t$str .= \"$key: $val\\n\";\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn rtrim($str);\n\t\t}\n\t}\n\t\n\tpublic function get($url, $remove=false, $gzdecode=true) {\n\t\t$url = \"$url\";\n\t\tif (isset($this->requests[$url]) && isset($this->requests[$url]['body'])) {\n\t\t\t$this->debug(\"URL already fetched - in memory ($url, effective: {$this->requests[$url]['effective_url']})\");\n\t\t\t$response = $this->requests[$url];\n\t\t/*\n\t\t} elseif ($this->isCached($url)) {\n\t\t\t$this->debug(\"URL already fetched - in disk cache ($url)\");\n\t\t\t$response = $this->getCached($url);\n\t\t\t$this->requests[$url] = $response;\n\t\t*/\n\t\t} else {\n\t\t\t$this->debug(\"Fetching URL ($url)\");\n\t\t\t$this->fetchAll(array($url));\n\t\t\tif (isset($this->requests[$url]) && isset($this->requests[$url]['body'])) {\n\t\t\t\t$response = $this->requests[$url];\n\t\t\t} else {\n\t\t\t\t$this->debug(\"Request failed\");\n\t\t\t\t$response = false;\n\t\t\t}\n\t\t}\n\t\t/*\n\t\tif ($this->minimiseMemoryUse && $response) {\n\t\t\t$this->cache($url);\n\t\t\tunset($this->requests[$url]);\n\t\t}\n\t\t*/\n\t\tif ($remove && $response) unset($this->requests[$url]);\n\t\tif ($gzdecode && stripos($response['headers'], 'Content-Encoding: gzip')) {\n\t\t\tif ($html = gzdecode($response['body'])) {\n\t\t\t\t$response['body'] = $html;\n\t\t\t}\n\t\t}\n\t\treturn $response;\n\t}\n\t\n\tpublic function parallelSupport() {\n\t\treturn class_exists('HttpRequestPool') || function_exists('curl_multi_init');\n\t}\n\t\n\tprivate function headerOnlyType($headers) {\n\t\tif (preg_match('!^Content-Type:\\s*(([a-z-]+)/([^;\\r\\n ]+))!im', $headers, $match)) {\n\t\t\t// look for full mime type (e.g. image/jpeg) or just type (e.g. image)\n\t\t\t$match[1] = strtolower(trim($match[1]));\n\t\t\t$match[2] = strtolower(trim($match[2]));\n\t\t\tforeach (array($match[1], $match[2]) as $mime) {\n\t\t\t\tif (in_array($mime, $this->headerOnlyTypes)) return true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\t\n\tprivate function possibleUnsupportedType($url) {\n\t\t$path = @parse_url($url, PHP_URL_PATH);\n\t\tif ($path && strpos($path, '.') !== false) {\n\t\t\t$ext = strtolower(trim(pathinfo($path, PATHINFO_EXTENSION)));\n\t\t\treturn in_array($ext, $this->headerOnlyClues);\n\t\t}\n\t\treturn false;\n\t}\n}\n\n// gzdecode from http://www.php.net/manual/en/function.gzdecode.php#82930\nif (!function_exists('gzdecode')) {\n\tfunction gzdecode($data,&$filename='',&$error='',$maxlength=null) \n\t{\n\t\t$len = strlen($data);\n\t\tif ($len < 18 || strcmp(substr($data,0,2),\"\\x1f\\x8b\")) {\n\t\t\t$error = \"Not in GZIP format.\";\n\t\t\treturn null;  // Not GZIP format (See RFC 1952)\n\t\t}\n\t\t$method = ord(substr($data,2,1));  // Compression method\n\t\t$flags  = ord(substr($data,3,1));  // Flags\n\t\tif ($flags & 31 != $flags) {\n\t\t\t$error = \"Reserved bits not allowed.\";\n\t\t\treturn null;\n\t\t}\n\t\t// NOTE: $mtime may be negative (PHP integer limitations)\n\t\t$mtime = unpack(\"V\", substr($data,4,4));\n\t\t$mtime = $mtime[1];\n\t\t$xfl   = substr($data,8,1);\n\t\t$os    = substr($data,8,1);\n\t\t$headerlen = 10;\n\t\t$extralen  = 0;\n\t\t$extra     = \"\";\n\t\tif ($flags & 4) {\n\t\t\t// 2-byte length prefixed EXTRA data in header\n\t\t\tif ($len - $headerlen - 2 < 8) {\n\t\t\t\treturn false;  // invalid\n\t\t\t}\n\t\t\t$extralen = unpack(\"v\",substr($data,8,2));\n\t\t\t$extralen = $extralen[1];\n\t\t\tif ($len - $headerlen - 2 - $extralen < 8) {\n\t\t\t\treturn false;  // invalid\n\t\t\t}\n\t\t\t$extra = substr($data,10,$extralen);\n\t\t\t$headerlen += 2 + $extralen;\n\t\t}\n\t\t$filenamelen = 0;\n\t\t$filename = \"\";\n\t\tif ($flags & 8) {\n\t\t\t// C-style string\n\t\t\tif ($len - $headerlen - 1 < 8) {\n\t\t\t\treturn false; // invalid\n\t\t\t}\n\t\t\t$filenamelen = strpos(substr($data,$headerlen),chr(0));\n\t\t\tif ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) {\n\t\t\t\treturn false; // invalid\n\t\t\t}\n\t\t\t$filename = substr($data,$headerlen,$filenamelen);\n\t\t\t$headerlen += $filenamelen + 1;\n\t\t}\n\t\t$commentlen = 0;\n\t\t$comment = \"\";\n\t\tif ($flags & 16) {\n\t\t\t// C-style string COMMENT data in header\n\t\t\tif ($len - $headerlen - 1 < 8) {\n\t\t\t\treturn false; // invalid\n\t\t\t}\n\t\t\t$commentlen = strpos(substr($data,$headerlen),chr(0));\n\t\t\tif ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) {\n\t\t\t\treturn false; // Invalid header format\n\t\t\t}\n\t\t\t$comment = substr($data,$headerlen,$commentlen);\n\t\t\t$headerlen += $commentlen + 1;\n\t\t}\n\t\t$headercrc = \"\";\n\t\tif ($flags & 2) {\n\t\t\t// 2-bytes (lowest order) of CRC32 on header present\n\t\t\tif ($len - $headerlen - 2 < 8) {\n\t\t\t\treturn false; // invalid\n\t\t\t}\n\t\t\t$calccrc = crc32(substr($data,0,$headerlen)) & 0xffff;\n\t\t\t$headercrc = unpack(\"v\", substr($data,$headerlen,2));\n\t\t\t$headercrc = $headercrc[1];\n\t\t\tif ($headercrc != $calccrc) {\n\t\t\t\t$error = \"Header checksum failed.\";\n\t\t\t\treturn false; // Bad header CRC\n\t\t\t}\n\t\t\t$headerlen += 2;\n\t\t}\n\t\t// GZIP FOOTER\n\t\t$datacrc = unpack(\"V\",substr($data,-8,4));\n\t\t$datacrc = sprintf('%u',$datacrc[1] & 0xFFFFFFFF);\n\t\t$isize = unpack(\"V\",substr($data,-4));\n\t\t$isize = $isize[1];\n\t\t// decompression:\n\t\t$bodylen = $len-$headerlen-8;\n\t\tif ($bodylen < 1) {\n\t\t\t// IMPLEMENTATION BUG!\n\t\t\treturn null;\n\t\t}\n\t\t$body = substr($data,$headerlen,$bodylen);\n\t\t$data = \"\";\n\t\tif ($bodylen > 0) {\n\t\t\tswitch ($method) {\n\t\t\tcase 8:\n\t\t\t\t// Currently the only supported compression method:\n\t\t\t\t$data = gzinflate($body,$maxlength);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t$error = \"Unknown compression method.\";\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}  // zero-byte body content is allowed\n\t\t// Verifiy CRC32\n\t\t$crc   = sprintf(\"%u\",crc32($data));\n\t\t$crcOK = $crc == $datacrc;\n\t\t$lenOK = $isize == strlen($data);\n\t\tif (!$lenOK || !$crcOK) {\n\t\t\t$error = ( $lenOK ? '' : 'Length check FAILED. ') . ( $crcOK ? '' : 'Checksum FAILED.');\n\t\t\treturn false;\n\t\t}\n\t\treturn $data;\n\t}\n}\n?>"
  },
  {
    "path": "libraries/humble-http-agent/RollingCurl.php",
    "content": "<?php\n/*\nAuthored by Josh Fraser (www.joshfraser.com)\nReleased under Apache License 2.0\n\nMaintained by Alexander Makarov, http://rmcreative.ru/\n\nModified by Keyvan Minoukadeh for the Five Filters project: http://fivefilters.org\n*/\n\n/**\n * Class that represent a single curl request\n */\nclass RollingCurlRequest {\n    public $url = false;\n\tpublic $url_original = false; // used for tracking redirects\n    public $method = 'GET';\n    public $post_data = null;\n    public $headers = null;\n    public $options = null;\n\n    /**\n     * @param string $url\n     * @param string $method\n     * @param  $post_data\n     * @param  $headers\n     * @param  $options\n     * @return void\n     */\n    function __construct($url, $method = \"GET\", $post_data = null, $headers = null, $options = null) {\n        $this->url = $url;\n\t\t$this->url_original = $url;\n        $this->method = $method;\n        $this->post_data = $post_data;\n        $this->headers = $headers;\n        $this->options = $options;\n    }\n\t\n    /**\n     * @param string $url\n     * @return void\n     */\n    public function set_original_url($url) {\n\t\t$this->url_original = $url;\n\t}\n    /**\n     * @return void\n     */\n    public function __destruct() {\n        unset($this->url, $this->url_original, $this->method, $this->post_data, $this->headers, $this->options);\n    }\n}\n\n/**\n * RollingCurl custom exception\n */\nclass RollingCurlException extends Exception {\n}\n\n/**\n * Class that holds a rolling queue of curl requests.\n *\n * @throws RollingCurlException\n */\nclass RollingCurl implements Countable {\n    /**\n     * @var int\n     *\n     * Window size is the max number of simultaneous connections allowed.\n     *\n     * REMEMBER TO RESPECT THE SERVERS:\n     * Sending too many requests at one time can easily be perceived\n     * as a DOS attack. Increase this window_size if you are making requests\n     * to multiple servers or have permission from the receving server admins.\n     */\n    private $window_size = 5;\n\n    /**\n     * @var float\n     *\n     * Timeout is the timeout used for curl_multi_select.\n     */\n    private $timeout = 10;\n\n    /**\n     * @var string|array\n     *\n     * Callback function to be applied to each result.\n     */\n    private $callback;\n\n    /**\n     * @var array\n     *\n     * Set your base options that you want to be used with EVERY request.\n     */\n    protected $options = array(\n        CURLOPT_SSL_VERIFYPEER => 0,\n        CURLOPT_RETURNTRANSFER => 1,\n        CURLOPT_CONNECTTIMEOUT => 30,\n        CURLOPT_TIMEOUT => 30\n    );\n\n    /**\n     * @var array\n     */\n    private $headers = array();\n\n    /**\n     * @var Request[]\n     *\n     * The request queue\n     */\n    private $requests = array();\n\n    /**\n     * @var RequestMap[]\n     *\n     * Maps handles to request indexes\n     */\n    private $requestMap = array();\n\n    /**\n     * @param  $callback\n     * Callback function to be applied to each result.\n     *\n     * Can be specified as 'my_callback_function'\n     * or array($object, 'my_callback_method').\n     *\n     * Function should take three parameters: $response, $info, $request.\n     * $response is response body, $info is additional curl info.\n     * $request is the original request\n     *\n     * @return void\n     */\n    function __construct($callback = null) {\n        $this->callback = $callback;\n    }\n\n    /**\n     * @param string $name\n     * @return mixed\n     */\n    public function __get($name) {\n        return (isset($this->{$name})) ? $this->{$name} : null;\n    }\n\n    /**\n     * @param string $name\n     * @param mixed $value\n     * @return bool\n     */\n    public function __set($name, $value) {\n        // append the base options & headers\n        if ($name == \"options\" || $name == \"headers\") {\n            $this->{$name} = $value + $this->{$name};\n        } else {\n            $this->{$name} = $value;\n        }\n        return true;\n    }\n\n    /**\n     * Count number of requests added (Countable interface)\n     *\n     * @return int\n     */\n    public function count() {\n        return count($this->requests);\n    }\t\n\t\n    /**\n     * Add a request to the request queue\n     *\n     * @param Request $request\n     * @return bool\n     */\n    public function add($request) {\n        $this->requests[] = $request;\n        return true;\n    }\n\n    /**\n     * Create new Request and add it to the request queue\n     *\n     * @param string $url\n     * @param string $method\n     * @param  $post_data\n     * @param  $headers\n     * @param  $options\n     * @return bool\n     */\n    public function request($url, $method = \"GET\", $post_data = null, $headers = null, $options = null) {\n        $this->requests[] = new RollingCurlRequest($url, $method, $post_data, $headers, $options);\n        return true;\n    }\n\n    /**\n     * Perform GET request\n     *\n     * @param string $url\n     * @param  $headers\n     * @param  $options\n     * @return bool\n     */\n    public function get($url, $headers = null, $options = null) {\n        return $this->request($url, \"GET\", null, $headers, $options);\n    }\n\n    /**\n     * Perform POST request\n     *\n     * @param string $url\n     * @param  $post_data\n     * @param  $headers\n     * @param  $options\n     * @return bool\n     */\n    public function post($url, $post_data = null, $headers = null, $options = null) {\n        return $this->request($url, \"POST\", $post_data, $headers, $options);\n    }\n\n    /**\n     * Execute processing\n     *\n     * @param int $window_size Max number of simultaneous connections\n     * @return string|bool\n     */\n    public function execute($window_size = null) {\n        // rolling curl window must always be greater than 1\n        if (sizeof($this->requests) == 1) {\n            return $this->single_curl();\n        } else {\n            // start the rolling curl. window_size is the max number of simultaneous connections\n            return $this->rolling_curl($window_size);\n        }\n    }\n\n    /**\n     * Performs a single curl request\n     *\n     * @access private\n     * @return string\n     */\n    private function single_curl() {\n        $ch = curl_init();\n        $request = array_shift($this->requests);\n        $options = $this->get_options($request);\n        curl_setopt_array($ch, $options);\n        $output = curl_exec($ch);\n        $info = curl_getinfo($ch);\n\n        // it's not neccesary to set a callback for one-off requests\n        if ($this->callback) {\n            $callback = $this->callback;\n            if (is_callable($this->callback)) {\n                call_user_func($callback, $output, $info, $request);\n            }\n        }\n        else\n            return $output;\n        return true;\n    }\n\n    /**\n     * Performs multiple curl requests\n     *\n     * @access private\n     * @throws RollingCurlException\n     * @param int $window_size Max number of simultaneous connections\n     * @return bool\n     */\n    private function rolling_curl($window_size = null) {\n        if ($window_size)\n            $this->window_size = $window_size;\n\n        // make sure the rolling window isn't greater than the # of urls\n        if (sizeof($this->requests) < $this->window_size)\n            $this->window_size = sizeof($this->requests);\n\n        if ($this->window_size < 2) {\n            throw new RollingCurlException(\"Window size must be greater than 1\");\n        }\n\n        $master = curl_multi_init();\n\n        // start the first batch of requests\n        for ($i = 0; $i < $this->window_size; $i++) {\n            $ch = curl_init();\n\n            $options = $this->get_options($this->requests[$i]);\n\n            curl_setopt_array($ch, $options);\n            curl_multi_add_handle($master, $ch);\n\n            // Add to our request Maps\n            $key = (string) $ch;\n            $this->requestMap[$key] = $i;\n        }\n\n        do {\n            while (($execrun = curl_multi_exec($master, $running)) == CURLM_CALL_MULTI_PERFORM) ;\n            if ($execrun != CURLM_OK)\n                break;\n            // a request was just completed -- find out which one\n            while ($done = curl_multi_info_read($master)) {\n\n                // get the info and content returned on the request\n                $info = curl_getinfo($done['handle']);\n                $output = curl_multi_getcontent($done['handle']);\n\n                // send the return values to the callback function.\n                $callback = $this->callback;\n                if (is_callable($callback)) {\n                    $key = (string) $done['handle'];\n                    $request = $this->requests[$this->requestMap[$key]];\n                    unset($this->requestMap[$key]);\n                    call_user_func($callback, $output, $info, $request);\n                }\n\n                // start a new request (it's important to do this before removing the old one)\n                if ($i < sizeof($this->requests) && isset($this->requests[$i]) && $i < count($this->requests)) {\n                    $ch = curl_init();\n                    $options = $this->get_options($this->requests[$i]);\n                    curl_setopt_array($ch, $options);\n                    curl_multi_add_handle($master, $ch);\n\n                    // Add to our request Maps\n                    $key = (string) $ch;\n                    $this->requestMap[$key] = $i;\n                    $i++;\n                }\n\n                // remove the curl handle that just completed\n                curl_multi_remove_handle($master, $done['handle']);\n\n            }\n\n            // Block for data in / output; error handling is done by curl_multi_exec\n            //if ($running) curl_multi_select($master, $this->timeout);\n\t\t\t// removing timeout as it causes problems on Windows with PHP 5.3.5 and Curl 7.20.0\n\t\t\tif ($running) curl_multi_select($master);\n\n        } while ($running);\n        curl_multi_close($master);\n        return true;\n    }\n\n\n    /**\n     * Helper function to set up a new request by setting the appropriate options\n     *\n     * @access private\n     * @param Request $request\n     * @return array\n     */\n    private function get_options($request) {\n        // options for this entire curl object\n        $options = $this->__get('options');\n\t\t// We're managing reirects in PHP - allows us to intervene and rewrite/block URLs\n\t\t// before the next request goes out.\n\t\t$options[CURLOPT_FOLLOWLOCATION] = 0;\n        $options[CURLOPT_MAXREDIRS] = 0;\n        //if (ini_get('safe_mode') == 'Off' || !ini_get('safe_mode')) {\n        //    $options[CURLOPT_FOLLOWLOCATION] = 1;\n        //    $options[CURLOPT_MAXREDIRS] = 5;\n        //}\n        $headers = $this->__get('headers');\n\t\t// append custom headers for this specific request\n\t\tif ($request->headers) {\n\t\t\t$headers = $headers + $request->headers;\n\t\t}\n\n        // append custom options for this specific request\n        if ($request->options) {\n            $options = $request->options + $options;\n        }\n\n        // set the request URL\n        $options[CURLOPT_URL] = $request->url;\n\n        if ($headers) {\n            $options[CURLOPT_HTTPHEADER] = $headers;\n        }\n\t\t// return response headers\n\t\t$options[CURLOPT_HEADER] = 1;\n\t\t\n\t\t// send HEAD request?\n\t\tif ($request->method == 'HEAD') {\n\t\t\t$options[CURLOPT_NOBODY] = 1;\n\t\t}\n\n        return $options;\n    }\n\n    /**\n     * @return void\n     */\n    public function __destruct() {\n        unset($this->window_size, $this->callback, $this->options, $this->headers, $this->requests);\n    }\n}"
  },
  {
    "path": "libraries/humble-http-agent/SimplePie_HumbleHttpAgent.php",
    "content": "<?php\n/**\n * Humble HTTP Agent extension for SimplePie_File\n * \n * This class is designed to extend and override SimplePie_File\n * in order to prevent duplicate HTTP requests being sent out.\n * The idea is to initialise an instance of Humble HTTP Agent\n * and attach it, to a static class variable, of this class.\n * SimplePie will then automatically initialise this class\n * \n * @date 2011-02-28\n */\n\nclass SimplePie_HumbleHttpAgent extends SimplePie_File\n{\n\tprotected static $agent;\n\tvar $url;\n\tvar $useragent;\n\tvar $success = true;\n\tvar $headers = array();\n\tvar $body;\n\tvar $status_code;\n\tvar $redirects = 0;\n\tvar $error;\n\tvar $method = SIMPLEPIE_FILE_SOURCE_NONE;\n\n\tpublic static function set_agent(HumbleHttpAgent $agent) {\n\t\tself::$agent = $agent;\n\t}\n\t\n\tpublic function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false) {\n\t\tif (class_exists('idna_convert'))\n\t\t{\n\t\t\t$idn = new idna_convert();\n\t\t\t$parsed = SimplePie_Misc::parse_url($url);\n\t\t\t$url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);\n\t\t}\n\t\t$this->url = $url;\n\t\t$this->useragent = $useragent;\n\t\tif (preg_match('/^http(s)?:\\/\\//i', $url))\n\t\t{\n\t\t\tif (!is_array($headers))\n\t\t\t{\n\t\t\t\t$headers = array();\n\t\t\t}\n\t\t\t$this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;\n\t\t\t$headers2 = array();\n\t\t\tforeach ($headers as $key => $value) {\n\t\t\t\t$headers2[] = \"$key: $value\";\n\t\t\t}\n\t\t\t//TODO: allow for HTTP headers\n\t\t\t// curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);\n\n\t\t\t$response = self::$agent->get($url);\n\t\t\t\n\t\t\tif ($response === false || !isset($response['status_code'])) {\n\t\t\t\t$this->error = 'failed to fetch URL';\n\t\t\t\t$this->success = false;\n\t\t\t} else {\n\t\t\t\t// The extra lines at the end are there to satisfy SimplePie's HTTP parser.\n\t\t\t\t// The class expects a full HTTP message, whereas we're giving it only\n\t\t\t\t// headers - the new lines indicate the start of the body.\n\t\t\t\t$parser = new SimplePie_HTTP_Parser($response['headers'].\"\\r\\n\\r\\n\");\n\t\t\t\tif ($parser->parse()) {\n\t\t\t\t\t$this->headers = $parser->headers;\n\t\t\t\t\t//$this->body = $parser->body;\n\t\t\t\t\t$this->body = $response['body'];\n\t\t\t\t\t$this->status_code = $parser->status_code;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->error = 'invalid URL';\n\t\t\t$this->success = false;\n\t\t}\n\t}\n}\n?>"
  },
  {
    "path": "libraries/language-detect/LanguageDetect/Exception.php",
    "content": "<?php\nclass Text_LanguageDetect_Exception extends Exception\n{\n    /**\n     * Database file could not be found\n     */\n    const DB_NOT_FOUND = 10;\n\n    /**\n     * Database file found, but not readable\n     */\n    const DB_NOT_READABLE = 11;\n\n    /**\n     * Database file is empty\n     */\n    const DB_EMPTY = 12;\n\n    /**\n     * Database contents is not a PHP array\n     */\n    const DB_NOT_ARRAY = 13;\n\n    /**\n     * Magic quotes are activated\n     */\n    const MAGIC_QUOTES = 14;\n\n\n    /**\n     * Parameter of invalid type passed to method\n     */\n    const PARAM_TYPE = 20;\n\n    /**\n     * Character in parameter is invalid\n     */\n    const INVALID_CHAR = 21;\n\n\n    /**\n     * Language is not in the database\n     */\n    const UNKNOWN_LANGUAGE = 30;\n\n\n    /**\n     * Error during block detection\n     */\n    const BLOCK_DETECTION = 40;\n\n\n    /**\n     * Error while clustering languages\n     */\n    const NO_HIGHEST_KEY = 50;\n}\n"
  },
  {
    "path": "libraries/language-detect/LanguageDetect/ISO639.php",
    "content": "<?php\n/**\n * Part of Text_LanguageDetect\n *\n * PHP version 5\n *\n * @category  Text\n * @package   Text_LanguageDetect\n * @author    Christian Weiske <cweiske@php.net>\n * @copyright 2011 Christian Weiske <cweiske@php.net>\n * @license   http://www.debian.org/misc/bsd.license BSD\n * @version   SVN: $Id$\n * @link      http://pear.php.net/package/Text_LanguageDetect/\n */\n\n/**\n * Provides a mapping between the languages from lang.dat and the\n * ISO 639-1 and ISO-639-2 codes.\n *\n * Note that this class contains only languages that exist in lang.dat.\n *\n * @category  Text\n * @package   Text_LanguageDetect\n * @author    Christian Weiske <cweiske@php.net>\n * @copyright 2011 Christian Weiske <cweiske@php.net>\n * @license   http://www.debian.org/misc/bsd.license BSD\n * @link      http://www.loc.gov/standards/iso639-2/php/code_list.php\n */\nclass Text_LanguageDetect_ISO639\n{\n    /**\n     * Maps all language names from the language database to the\n     * ISO 639-1 2-letter language code.\n     *\n     * NULL indicates that there is no 2-letter code.\n     *\n     * @var array\n     */\n    public static $nameToCode2 = array(\n        'albanian'   => 'sq',\n        'arabic'     => 'ar',\n        'azeri'      => 'az',\n        'bengali'    => 'bn',\n        'bulgarian'  => 'bg',\n        'cebuano'    => null,\n        'croatian'   => 'hr',\n        'czech'      => 'cs',\n        'danish'     => 'da',\n        'dutch'      => 'nl',\n        'english'    => 'en',\n        'estonian'   => 'et',\n        'farsi'      => 'fa',\n        'finnish'    => 'fi',\n        'french'     => 'fr',\n        'german'     => 'de',\n        'hausa'      => 'ha',\n        'hawaiian'   => null,\n        'hindi'      => 'hi',\n        'hungarian'  => 'hu',\n        'icelandic'  => 'is',\n        'indonesian' => 'id',\n        'italian'    => 'it',\n        'kazakh'     => 'kk',\n        'kyrgyz'     => 'ky',\n        'latin'      => 'la',\n        'latvian'    => 'lv',\n        'lithuanian' => 'lt',\n        'macedonian' => 'mk',\n        'mongolian'  => 'mn',\n        'nepali'     => 'ne',\n        'norwegian'  => 'no',\n        'pashto'     => 'ps',\n        'pidgin'     => null,\n        'polish'     => 'pl',\n        'portuguese' => 'pt',\n        'romanian'   => 'ro',\n        'russian'    => 'ru',\n        'serbian'    => 'sr',\n        'slovak'     => 'sk',\n        'slovene'    => 'sl',\n        'somali'     => 'so',\n        'spanish'    => 'es',\n        'swahili'    => 'sw',\n        'swedish'    => 'sv',\n        'tagalog'    => 'tl',\n        'turkish'    => 'tr',\n        'ukrainian'  => 'uk',\n        'urdu'       => 'ur',\n        'uzbek'      => 'uz',\n        'vietnamese' => 'vi',\n        'welsh'      => 'cy',\n    );\n\n    /**\n     * Maps all language names from the language database to the\n     * ISO 639-2 3-letter language code.\n     *\n     * @var array\n     */\n    public static $nameToCode3 = array(\n        'albanian'   => 'sqi',\n        'arabic'     => 'ara',\n        'azeri'      => 'aze',\n        'bengali'    => 'ben',\n        'bulgarian'  => 'bul',\n        'cebuano'    => 'ceb',\n        'croatian'   => 'hrv',\n        'czech'      => 'ces',\n        'danish'     => 'dan',\n        'dutch'      => 'nld',\n        'english'    => 'eng',\n        'estonian'   => 'est',\n        'farsi'      => 'fas',\n        'finnish'    => 'fin',\n        'french'     => 'fra',\n        'german'     => 'deu',\n        'hausa'      => 'hau',\n        'hawaiian'   => 'haw',\n        'hindi'      => 'hin',\n        'hungarian'  => 'hun',\n        'icelandic'  => 'isl',\n        'indonesian' => 'ind',\n        'italian'    => 'ita',\n        'kazakh'     => 'kaz',\n        'kyrgyz'     => 'kir',\n        'latin'      => 'lat',\n        'latvian'    => 'lav',\n        'lithuanian' => 'lit',\n        'macedonian' => 'mkd',\n        'mongolian'  => 'mon',\n        'nepali'     => 'nep',\n        'norwegian'  => 'nor',\n        'pashto'     => 'pus',\n        'pidgin'     => 'crp',\n        'polish'     => 'pol',\n        'portuguese' => 'por',\n        'romanian'   => 'ron',\n        'russian'    => 'rus',\n        'serbian'    => 'srp',\n        'slovak'     => 'slk',\n        'slovene'    => 'slv',\n        'somali'     => 'som',\n        'spanish'    => 'spa',\n        'swahili'    => 'swa',\n        'swedish'    => 'swe',\n        'tagalog'    => 'tgl',\n        'turkish'    => 'tur',\n        'ukrainian'  => 'ukr',\n        'urdu'       => 'urd',\n        'uzbek'      => 'uzb',\n        'vietnamese' => 'vie',\n        'welsh'      => 'cym',\n    );\n\n    /**\n     * Maps ISO 639-1 2-letter language codes to the language names\n     * in the language database\n     *\n     * Not all languages have a 2 letter code, so some are missing\n     *\n     * @var array\n     */\n    public static $code2ToName = array(\n        'ar' => 'arabic',\n        'az' => 'azeri',\n        'bg' => 'bulgarian',\n        'bn' => 'bengali',\n        'cs' => 'czech',\n        'cy' => 'welsh',\n        'da' => 'danish',\n        'de' => 'german',\n        'en' => 'english',\n        'es' => 'spanish',\n        'et' => 'estonian',\n        'fa' => 'farsi',\n        'fi' => 'finnish',\n        'fr' => 'french',\n        'ha' => 'hausa',\n        'hi' => 'hindi',\n        'hr' => 'croatian',\n        'hu' => 'hungarian',\n        'id' => 'indonesian',\n        'is' => 'icelandic',\n        'it' => 'italian',\n        'kk' => 'kazakh',\n        'ky' => 'kyrgyz',\n        'la' => 'latin',\n        'lt' => 'lithuanian',\n        'lv' => 'latvian',\n        'mk' => 'macedonian',\n        'mn' => 'mongolian',\n        'ne' => 'nepali',\n        'nl' => 'dutch',\n        'no' => 'norwegian',\n        'pl' => 'polish',\n        'ps' => 'pashto',\n        'pt' => 'portuguese',\n        'ro' => 'romanian',\n        'ru' => 'russian',\n        'sk' => 'slovak',\n        'sl' => 'slovene',\n        'so' => 'somali',\n        'sq' => 'albanian',\n        'sr' => 'serbian',\n        'sv' => 'swedish',\n        'sw' => 'swahili',\n        'tl' => 'tagalog',\n        'tr' => 'turkish',\n        'uk' => 'ukrainian',\n        'ur' => 'urdu',\n        'uz' => 'uzbek',\n        'vi' => 'vietnamese',\n    );\n\n    /**\n     * Maps ISO 639-2 3-letter language codes to the language names\n     * in the language database.\n     *\n     * @var array\n     */\n    public static $code3ToName = array(\n        'ara' => 'arabic',\n        'aze' => 'azeri',\n        'ben' => 'bengali',\n        'bul' => 'bulgarian',\n        'ceb' => 'cebuano',\n        'ces' => 'czech',\n        'crp' => 'pidgin',\n        'cym' => 'welsh',\n        'dan' => 'danish',\n        'deu' => 'german',\n        'eng' => 'english',\n        'est' => 'estonian',\n        'fas' => 'farsi',\n        'fin' => 'finnish',\n        'fra' => 'french',\n        'hau' => 'hausa',\n        'haw' => 'hawaiian',\n        'hin' => 'hindi',\n        'hrv' => 'croatian',\n        'hun' => 'hungarian',\n        'ind' => 'indonesian',\n        'isl' => 'icelandic',\n        'ita' => 'italian',\n        'kaz' => 'kazakh',\n        'kir' => 'kyrgyz',\n        'lat' => 'latin',\n        'lav' => 'latvian',\n        'lit' => 'lithuanian',\n        'mkd' => 'macedonian',\n        'mon' => 'mongolian',\n        'nep' => 'nepali',\n        'nld' => 'dutch',\n        'nor' => 'norwegian',\n        'pol' => 'polish',\n        'por' => 'portuguese',\n        'pus' => 'pashto',\n        'rom' => 'romanian',\n        'rus' => 'russian',\n        'slk' => 'slovak',\n        'slv' => 'slovene',\n        'som' => 'somali',\n        'spa' => 'spanish',\n        'sqi' => 'albanian',\n        'srp' => 'serbian',\n        'swa' => 'swahili',\n        'swe' => 'swedish',\n        'tgl' => 'tagalog',\n        'tur' => 'turkish',\n        'ukr' => 'ukrainian',\n        'urd' => 'urdu',\n        'uzb' => 'uzbek',\n        'vie' => 'vietnamese',\n    );\n\n    /**\n     * Returns the 2-letter ISO 639-1 code for the given language name.\n     *\n     * @param string $lang English language name like \"swedish\"\n     *\n     * @return string Two-letter language code (e.g. \"sv\") or NULL if not found\n     */\n    public static function nameToCode2($lang)\n    {\n        $lang = strtolower($lang);\n        if (!isset(self::$nameToCode2[$lang])) {\n            return null;\n        }\n        return self::$nameToCode2[$lang];\n    }\n\n    /**\n     * Returns the 3-letter ISO 639-2 code for the given language name.\n     *\n     * @param string $lang English language name like \"swedish\"\n     *\n     * @return string Three-letter language code (e.g. \"swe\") or NULL if not found\n     */\n    public static function nameToCode3($lang)\n    {\n        $lang = strtolower($lang);\n        if (!isset(self::$nameToCode3[$lang])) {\n            return null;\n        }\n        return self::$nameToCode3[$lang];\n    }\n\n    /**\n     * Returns the language name for the given 2-letter ISO 639-1 code.\n     *\n     * @param string $code Two-letter language code (e.g. \"sv\")\n     *\n     * @return string English language name like \"swedish\"\n     */\n    public static function code2ToName($code)\n    {\n        $lang = strtolower($code);\n        if (!isset(self::$code2ToName[$code])) {\n            return null;\n        }\n        return self::$code2ToName[$code];\n    }\n\n    /**\n     * Returns the language name for the given 3-letter ISO 639-2 code.\n     *\n     * @param string $code Three-letter language code (e.g. \"swe\")\n     *\n     * @return string English language name like \"swedish\"\n     */\n    public static function code3ToName($code)\n    {\n        $lang = strtolower($code);\n        if (!isset(self::$code3ToName[$code])) {\n            return null;\n        }\n        return self::$code3ToName[$code];\n    }\n}"
  },
  {
    "path": "libraries/language-detect/LanguageDetect/Parser.php",
    "content": "<?php\n\n/**\n * This class represents a text sample to be parsed.\n *\n * @category    Text\n * @package     Text_LanguageDetect\n * @author      Nicholas Pisarro\n * @copyright   2006\n * @license     BSD\n * @version     CVS: $Id: Parser.php 322327 2012-01-15 17:55:59Z cweiske $\n * @link        http://pear.php.net/package/Text_LanguageDetect/\n * @link        http://langdetect.blogspot.com/\n */\n\n/**\n * This class represents a text sample to be parsed.\n *\n * This separates the analysis of a text sample from the primary LanguageDetect\n * class. After a new profile has been built, the data can be retrieved using\n * the accessor functions.\n *\n * This class is intended to be used by the Text_LanguageDetect class, not \n * end-users.\n *\n * @category    Text\n * @package     Text_LanguageDetect\n * @author      Nicholas Pisarro\n * @copyright   2006\n * @license     BSD\n * @version     release: 0.3.0\n */\nclass Text_LanguageDetect_Parser extends Text_LanguageDetect\n{\n    /**\n     * the piece of text being parsed\n     *\n     * @access  private\n     * @var     string\n     */\n    var $_string;\n\n    /**\n     * stores the trigram frequencies of the sample\n     *\n     * @access  private\n     * @var     string\n     */\n    var $_trigrams = array();\n\n    /**\n     * stores the trigram ranks of the sample\n     *\n     * @access  private\n     * @var     array\n     */\n    var $_trigram_ranks = array();\n\n    /**\n     * stores the unicode blocks of the sample\n     *\n     * @access  private\n     * @var     array\n     */\n    var $_unicode_blocks = array();\n    \n    /**\n     * Whether the parser should compile the unicode ranges\n     * \n     * @access  private\n     * @var     bool\n     */\n    var $_compile_unicode = false;\n\n    /**\n     * Whether the parser should compile trigrams\n     *\n     * @access  private\n     * @var     bool\n     */\n    var $_compile_trigram = false;\n\n    /**\n     * Whether the trigram parser should pad the beginning of the string\n     *\n     * @access  private\n     * @var     bool\n     */\n    var $_trigram_pad_start = false;\n\n    /**\n     * Whether the unicode parser should skip non-alphabetical ascii chars\n     *\n     * @access  private\n     * @var     bool\n     */\n    var $_unicode_skip_symbols = true;\n\n    /**\n     * Constructor\n     *\n     * @access  private\n     * @param   string  $string     string to be parsed\n     */\n    function Text_LanguageDetect_Parser($string) {\n        $this->_string = $string;\n    }\n\n    /**\n     * Returns true if a string is suitable for parsing\n     *\n     * @param   string  $str    input string to test\n     * @return  bool            true if acceptable, false if not\n     */\n    public static function validateString($str) {\n        if (!empty($str) && strlen($str) > 3 && preg_match('/\\S/', $str)) {\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * turn on/off trigram counting\n     *\n     * @access  public\n     * @param   bool    $bool true for on, false for off\n     */\n    function prepareTrigram($bool = true)\n    {\n        $this->_compile_trigram = $bool;\n    }\n\n    /**\n     * turn on/off unicode block counting\n     *\n     * @access  public\n     * @param   bool    $bool true for on, false for off\n     */\n    function prepareUnicode($bool = true)\n    {\n        $this->_compile_unicode = $bool;\n    }\n\n    /**\n     * turn on/off padding the beginning of the sample string\n     *\n     * @access  public\n     * @param   bool    $bool true for on, false for off\n     */\n    function setPadStart($bool = true)\n    {\n        $this->_trigram_pad_start = $bool;\n    }\n\n    /**\n     * Should the unicode block counter skip non-alphabetical ascii chars?\n     *\n     * @access  public\n     * @param   bool    $bool true for on, false for off\n     */\n    function setUnicodeSkipSymbols($bool = true)\n    {\n        $this->_unicode_skip_symbols = $bool;\n    }\n\n    /**\n     * Returns the trigram ranks for the text sample\n     *\n     * @access  public\n     * @return  array    trigram ranks in the text sample\n     */\n    function &getTrigramRanks()\n    {\n        return $this->_trigram_ranks;\n    }\n\n    /**\n     * Return the trigram freqency table\n     *\n     * only used in testing to make sure the parser is working\n     *\n     * @access  public\n     * @return  array    trigram freqencies in the text sample\n     */\n    function &getTrigramFreqs()\n    {\n        return $this->_trigram;\n    }\n\n    /**\n     * returns the array of unicode blocks\n     *\n     * @access  public\n     * @return  array   unicode blocks in the text sample\n     */\n    function &getUnicodeBlocks()\n    {\n        return $this->_unicode_blocks;\n    }\n\n    /**\n     * Executes the parsing operation\n     * \n     * Be sure to call the set*() functions to set options and the \n     * prepare*() functions first to tell it what kind of data to compute\n     *\n     * Afterwards the get*() functions can be used to access the compiled\n     * information.\n     *\n     * @access public\n     */\n    function analyze()\n    {\n        $len = strlen($this->_string);\n        $byte_counter = 0;\n\n\n        // unicode startup\n        if ($this->_compile_unicode) {\n            $blocks = $this->_read_unicode_block_db();\n            $block_count = count($blocks);\n\n            $skipped_count = 0;\n            $unicode_chars = array();\n        }\n\n        // trigram startup\n        if ($this->_compile_trigram) {\n            // initialize them as blank so the parser will skip the first two\n            // (since it skips trigrams with more than  2 contiguous spaces)\n            $a = ' ';\n            $b = ' ';\n\n            // kludge\n            // if it finds a valid trigram to start and the start pad option is\n            // off, then set a variable that will be used to reduce this\n            // trigram after parsing has finished\n            if (!$this->_trigram_pad_start) {\n                $a = $this->_next_char($this->_string, $byte_counter, true);\n\n                if ($a != ' ') {\n                    $b = $this->_next_char($this->_string, $byte_counter, true);\n                    $dropone = \" $a$b\";\n                }\n\n                $byte_counter = 0;\n                $a = ' ';\n                $b = ' ';\n            }\n        }\n\n        while ($byte_counter < $len) {\n            $char = $this->_next_char($this->_string, $byte_counter, true);\n\n\n            // language trigram detection\n            if ($this->_compile_trigram) {\n                if (!($b == ' ' && ($a == ' ' || $char == ' '))) {\n                    if (!isset($this->_trigram[$a . $b . $char])) {\n                       $this->_trigram[$a . $b . $char] = 1;\n                    } else {\n                       $this->_trigram[$a . $b . $char]++;\n                    }\n                }\n\n                $a = $b;\n                $b = $char;\n            }\n\n            // unicode block detection\n            if ($this->_compile_unicode) {\n                if ($this->_unicode_skip_symbols\n                        && strlen($char) == 1\n                        && ($char < 'A' || $char > 'z'\n                        || ($char > 'Z' && $char < 'a'))\n                        && $char != \"'\") {  // does not skip the apostrophe\n                                            // since it's included in the language\n                                            // models\n\n                    $skipped_count++;\n                    continue;\n                }\n\n                // build an array of all the characters\n                if (isset($unicode_chars[$char])) {\n                    $unicode_chars[$char]++;\n                } else {\n                    $unicode_chars[$char] = 1;\n                }\n            }\n\n            // todo: add byte detection here\n        }\n\n        // unicode cleanup\n        if ($this->_compile_unicode) {\n            foreach ($unicode_chars as $utf8_char => $count) {\n                $search_result = $this->_unicode_block_name(\n                        $this->_utf8char2unicode($utf8_char), $blocks, $block_count);\n\n                if ($search_result != -1) {\n                    $block_name = $search_result[2];\n                } else {\n                    $block_name = '[Malformatted]';\n                }\n\n                if (isset($this->_unicode_blocks[$block_name])) {\n                    $this->_unicode_blocks[$block_name] += $count;\n                } else {\n                    $this->_unicode_blocks[$block_name] = $count;\n                }\n            }\n        }\n\n\n        // trigram cleanup\n        if ($this->_compile_trigram) {\n            // pad the end\n            if ($b != ' ') {\n                if (!isset($this->_trigram[\"$a$b \"])) {\n                    $this->_trigram[\"$a$b \"] = 1;\n                } else {\n                    $this->_trigram[\"$a$b \"]++;\n                }\n            }\n\n            // perl compatibility; Language::Guess does not pad the beginning\n            // kludge\n            if (isset($dropone)) {\n                if ($this->_trigram[$dropone] == 1) {\n                    unset($this->_trigram[$dropone]);\n                } else {\n                    $this->_trigram[$dropone]--;\n                }\n            }\n\n            if (!empty($this->_trigram)) {\n                $this->_trigram_ranks = $this->_arr_rank($this->_trigram);\n            } else {\n                $this->_trigram_ranks = array();\n            }\n        }\n    }\n}\n\n/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */"
  },
  {
    "path": "libraries/language-detect/LanguageDetect.php",
    "content": "<?php\n\n/**\n * Detects the language of a given piece of text.\n *\n * Attempts to detect the language of a sample of text by correlating ranked\n * 3-gram frequencies to a table of 3-gram frequencies of known languages.\n *\n * Implements a version of a technique originally proposed by Cavnar & Trenkle\n * (1994): \"N-Gram-Based Text Categorization\"\n *\n * PHP version 5\n *\n * @category  Text\n * @package   Text_LanguageDetect\n * @author    Nicholas Pisarro <infinityminusnine+pear@gmail.com>\n * @copyright 2005-2006 Nicholas Pisarro\n * @license   http://www.debian.org/misc/bsd.license BSD\n * @version   SVN: $Id: LanguageDetect.php 322353 2012-01-16 08:41:43Z cweiske $\n * @link      http://pear.php.net/package/Text_LanguageDetect/\n * @link      http://langdetect.blogspot.com/\n */\n\nrequire_once 'LanguageDetect/Exception.php';\nrequire_once 'LanguageDetect/Parser.php';\nrequire_once 'LanguageDetect/ISO639.php';\n\n/**\n * Language detection class\n *\n * Requires the langauge model database (lang.dat) that should have\n * accompanied this class definition in order to be instantiated.\n *\n * Example usage:\n *\n * <code>\n * require_once 'Text/LanguageDetect.php';\n *\n * $l = new Text_LanguageDetect;\n *\n * $stdin = fopen('php://stdin', 'r');\n *\n * echo \"Supported languages:\\n\";\n *\n * try {\n *     $langs = $l->getLanguages();\n * } catch (Text_LanguageDetect_Exception $e) {\n *     die($e->getMessage());\n * }\n *\n * sort($langs);\n * echo join(', ', $langs);\n *\n * while ($line = fgets($stdin)) {\n *     print_r($l->detect($line, 4));\n * }\n * </code>\n *\n * @category  Text\n * @package   Text_LanguageDetect\n * @author    Nicholas Pisarro <infinityminusnine+pear@gmail.com>\n * @copyright 2005 Nicholas Pisarro\n * @license   http://www.debian.org/misc/bsd.license BSD\n * @version   Release: @package_version@\n * @link      http://pear.php.net/package/Text_LanguageDetect/\n * @todo      allow users to generate their own language models\n */\nclass Text_LanguageDetect\n{\n    /**\n     * The filename that stores the trigram data for the detector\n     *\n     * If this value starts with a slash (/) or a dot (.) the value of\n     * $this->_data_dir will be ignored\n     *\n     * @var      string\n     * @access   private\n     */\n    var $_db_filename = 'lang.dat';\n\n    /**\n     * The filename that stores the unicode block definitions\n     *\n     * If this value starts with a slash (/) or a dot (.) the value of\n     * $this->_data_dir will be ignored\n     *\n     * @var string\n     * @access private\n     */\n    var $_unicode_db_filename = 'unicode_blocks.dat';\n\n    /**\n     * The data directory\n     *\n     * Should be set by PEAR installer\n     *\n     * @var      string\n     * @access   private\n     */\n    var $_data_dir = '@data_dir@';\n\n    /**\n     * The trigram data for comparison\n     *\n     * Will be loaded on start from $this->_db_filename\n     *\n     * @var      array\n     * @access   private\n     */\n    var $_lang_db = array();\n\n    /**\n     * stores the map of the trigram data to unicode characters\n     *\n     * @access private\n     * @var array\n     */\n    var $_unicode_map;\n\n    /**\n     * The size of the trigram data arrays\n     *\n     * @var      int\n     * @access   private\n     */\n    var $_threshold = 300;\n\n    /**\n     * the maximum possible score.\n     *\n     * needed for score normalization. Different depending on the\n     * perl compatibility setting\n     *\n     * @access  private\n     * @var     int\n     * @see     setPerlCompatible()\n     */\n    var $_max_score = 0;\n\n    /**\n     * Whether or not to simulate perl's Language::Guess exactly\n     *\n     * @access  private\n     * @var     bool\n     * @see     setPerlCompatible()\n     */\n    var $_perl_compatible = false;\n\n    /**\n     * Whether to use the unicode block detection to speed up processing\n     *\n     * @access private\n     * @var bool\n     */\n    var $_use_unicode_narrowing = true;\n\n    /**\n     * stores the result of the clustering operation\n     *\n     * @access  private\n     * @var     array\n     * @see     clusterLanguages()\n     */\n    var $_clusters;\n\n    /**\n     * Which type of \"language names\" are accepted and returned:\n     *\n     * 0 - language name (\"english\")\n     * 2 - 2-letter ISO 639-1 code (\"en\")\n     * 3 - 3-letter ISO 639-2 code (\"eng\")\n     */\n    var $_name_mode = 0;\n\n    /**\n     * Constructor\n     *\n     * Will attempt to load the language database. If it fails, you will get\n     * an exception.\n     */\n    function __construct()\n    {\n        $data = $this->_readdb($this->_db_filename);\n        $this->_checkTrigram($data['trigram']);\n        $this->_lang_db = $data['trigram'];\n\n        if (isset($data['trigram-unicodemap'])) {\n            $this->_unicode_map = $data['trigram-unicodemap'];\n        }\n\n        // Not yet implemented:\n        if (isset($data['trigram-clusters'])) {\n            $this->_clusters = $data['trigram-clusters'];\n        }\n    }\n\n    /**\n     * Returns the path to the location of the database\n     *\n     * @param string $fname File name to load\n     *\n     * @return string expected path to the language model database\n     * @access private\n     */\n    function _get_data_loc($fname)\n    {\n        return dirname(__FILE__).'/'.$fname;\n    }\n\n    /**\n     * Loads the language trigram database from filename\n     *\n     * Trigram datbase should be a serialize()'d array\n     *\n     * @param string $fname the filename where the data is stored\n     *\n     * @return array the language model data\n     * @throws Text_LanguageDetect_Exception\n     * @access private\n     */\n    function _readdb($fname)\n    {\n        // finds the correct data dir\n        $fname = $this->_get_data_loc($fname);\n\n        // input check\n        if (!file_exists($fname)) {\n            throw new Text_LanguageDetect_Exception(\n                'Language database does not exist: ' . $fname,\n                Text_LanguageDetect_Exception::DB_NOT_FOUND\n            );\n        } elseif (!is_readable($fname)) {\n            throw new Text_LanguageDetect_Exception(\n                'Language database is not readable: ' . $fname,\n                Text_LanguageDetect_Exception::DB_NOT_READABLE\n            );\n        }\n\n        return unserialize(file_get_contents($fname));\n    }\n\n\n    /**\n     * Checks if this object is ready to detect languages\n     *\n     * @param array $trigram Trigram data from database\n     *\n     * @return void\n     * @access private\n     */\n    function _checkTrigram($trigram)\n    {\n        if (!is_array($trigram)) {\n            if (ini_get('magic_quotes_runtime')) {\n                throw new Text_LanguageDetect_Exception(\n                    'Error loading database. Try turning magic_quotes_runtime off.',\n                    Text_LanguageDetect_Exception::MAGIC_QUOTES\n                );\n            }\n            throw new Text_LanguageDetect_Exception(\n                'Language database is not an array.',\n                Text_LanguageDetect_Exception::DB_NOT_ARRAY\n            );\n        } elseif (empty($trigram)) {\n            throw new Text_LanguageDetect_Exception(\n                'Language database has no elements.',\n                Text_LanguageDetect_Exception::DB_EMPTY\n            );\n        }\n    }\n\n    /**\n     * Omits languages\n     *\n     * Pass this function the name of or an array of names of\n     * languages that you don't want considered\n     *\n     * If you're only expecting a limited set of languages, this can greatly\n     * speed up processing\n     *\n     * @param mixed $omit_list    language name or array of names to omit\n     * @param bool  $include_only if true will include (rather than\n     *                            exclude) only those in the list\n     *\n     * @return int number of languages successfully deleted\n     * @throws Text_LanguageDetect_Exception\n     */\n    public function omitLanguages($omit_list, $include_only = false)\n    {\n        $deleted = 0;\n\n        $omit_list = $this->_convertFromNameMode($omit_list);\n\n        if (!$include_only) {\n            // deleting the given languages\n            if (!is_array($omit_list)) {\n                $omit_list = strtolower($omit_list); // case desensitize\n                if (isset($this->_lang_db[$omit_list])) {\n                    unset($this->_lang_db[$omit_list]);\n                    $deleted++;\n                }\n            } else {\n                foreach ($omit_list as $omit_lang) {\n                    if (isset($this->_lang_db[$omit_lang])) {\n                        unset($this->_lang_db[$omit_lang]);\n                        $deleted++;\n                    }\n                }\n            }\n\n        } else {\n            // deleting all except the given languages\n            if (!is_array($omit_list)) {\n                $omit_list = array($omit_list);\n            }\n\n            // case desensitize\n            foreach ($omit_list as $key => $omit_lang) {\n                $omit_list[$key] = strtolower($omit_lang);\n            }\n\n            foreach (array_keys($this->_lang_db) as $lang) {\n                if (!in_array($lang, $omit_list)) {\n                    unset($this->_lang_db[$lang]);\n                    $deleted++;\n                }\n            }\n        }\n\n        // reset the cluster cache if the number of languages changes\n        // this will then have to be recalculated\n        if (isset($this->_clusters) && $deleted > 0) {\n            $this->_clusters = null;\n        }\n\n        return $deleted;\n    }\n\n\n    /**\n     * Returns the number of languages that this object can detect\n     *\n     * @access public\n     * @return int            the number of languages\n     * @throws   Text_LanguageDetect_Exception\n     */\n    function getLanguageCount()\n    {\n        return count($this->_lang_db);\n    }\n\n    /**\n     * Checks if the language with the given name exists in the database\n     *\n     * @param mixed $lang Language name or array of language names\n     *\n     * @return bool true if language model exists\n     */\n    public function languageExists($lang)\n    {\n        $lang = $this->_convertFromNameMode($lang);\n\n        if (is_string($lang)) {\n            return isset($this->_lang_db[strtolower($lang)]);\n\n        } elseif (is_array($lang)) {\n            foreach ($lang as $test_lang) {\n                if (!isset($this->_lang_db[strtolower($test_lang)])) {\n                    return false;\n                }\n            }\n            return true;\n\n        } else {\n            throw new Text_LanguageDetect_Exception(\n                'Unsupported parameter type passed to languageExists()',\n                Text_LanguageDetect_Exception::PARAM_TYPE\n            );\n        }\n    }\n\n    /**\n     * Returns the list of detectable languages\n     *\n     * @access public\n     * @return array        the names of the languages known to this object<<<<<<<\n     * @throws   Text_LanguageDetect_Exception\n     */\n    function getLanguages()\n    {\n        return $this->_convertToNameMode(\n            array_keys($this->_lang_db)\n        );\n    }\n\n    /**\n     * Make this object behave like Language::Guess\n     *\n     * @param bool $setting false to turn off perl compatibility\n     *\n     * @return void\n     */\n    public function setPerlCompatible($setting = true)\n    {\n        if (is_bool($setting)) { // input check\n            $this->_perl_compatible = $setting;\n\n            if ($setting == true) {\n                $this->_max_score = $this->_threshold;\n            } else {\n                $this->_max_score = 0;\n            }\n        }\n\n    }\n\n    /**\n     * Sets the way how language names are accepted and returned.\n     *\n     * @param integer $name_mode One of the following modes:\n     *                           0 - language name (\"english\")\n     *                           2 - 2-letter ISO 639-1 code (\"en\")\n     *                           3 - 3-letter ISO 639-2 code (\"eng\")\n     *\n     * @return void\n     */\n    function setNameMode($name_mode)\n    {\n        $this->_name_mode = $name_mode;\n    }\n\n    /**\n     * Whether to use unicode block ranges in detection\n     *\n     * Should speed up most detections if turned on (detault is on). In some\n     * circumstances it may be slower, such as for large text samples (> 10K)\n     * in languages that use latin scripts. In other cases it should speed up\n     * detection noticeably.\n     *\n     * @param bool $setting false to turn off\n     *\n     * @return void\n     */\n    public function useUnicodeBlocks($setting = true)\n    {\n        if (is_bool($setting)) {\n            $this->_use_unicode_narrowing = $setting;\n        }\n    }\n\n    /**\n     * Converts a piece of text into trigrams\n     *\n     * @param string $text text to convert\n     *\n     * @return     array array of trigram frequencies\n     * @access     private\n     * @deprecated Superceded by the Text_LanguageDetect_Parser class\n     */\n    function _trigram($text)\n    {\n        $s = new Text_LanguageDetect_Parser($text);\n        $s->prepareTrigram();\n        $s->prepareUnicode(false);\n        $s->setPadStart(!$this->_perl_compatible);\n        $s->analyze();\n        return $s->getTrigramFreqs();\n    }\n\n    /**\n     * Converts a set of trigrams from frequencies to ranks\n     *\n     * Thresholds (cuts off) the list at $this->_threshold\n     *\n     * @param array $arr array of trigram\n     *\n     * @return array ranks of trigrams\n     * @access protected\n     */\n    function _arr_rank($arr)\n    {\n\n        // sorts alphabetically first as a standard way of breaking rank ties\n        $this->_bub_sort($arr);\n\n        // below might also work, but seemed to introduce errors in testing\n        //ksort($arr);\n        //asort($arr);\n\n        $rank = array();\n\n        $i = 0;\n        foreach ($arr as $key => $value) {\n            $rank[$key] = $i++;\n\n            // cut off at a standard threshold\n            if ($i >= $this->_threshold) {\n                break;\n            }\n        }\n\n        return $rank;\n    }\n\n    /**\n     * Sorts an array by value breaking ties alphabetically\n     *\n     * @param array &$arr the array to sort\n     *\n     * @return void\n     * @access private\n     */\n    function _bub_sort(&$arr)\n    {\n        // should do the same as this perl statement:\n        // sort { $trigrams{$b} == $trigrams{$a}\n        //   ?  $a cmp $b : $trigrams{$b} <=> $trigrams{$a} }\n\n        // needs to sort by both key and value at once\n        // using the key to break ties for the value\n\n        // converts array into an array of arrays of each key and value\n        // may be a better way of doing this\n        $combined = array();\n\n        foreach ($arr as $key => $value) {\n            $combined[] = array($key, $value);\n        }\n\n        usort($combined, array($this, '_sort_func'));\n\n        $replacement = array();\n        foreach ($combined as $key => $value) {\n            list($new_key, $new_value) = $value;\n            $replacement[$new_key] = $new_value;\n        }\n\n        $arr = $replacement;\n    }\n\n    /**\n     * Sort function used by bubble sort\n     *\n     * Callback function for usort().\n     *\n     * @param array $a first param passed by usort()\n     * @param array $b second param passed by usort()\n     *\n     * @return int 1 if $a is greater, -1 if not\n     * @see    _bub_sort()\n     * @access private\n     */\n    function _sort_func($a, $b)\n    {\n        // each is actually a key/value pair, so that it can compare using both\n        list($a_key, $a_value) = $a;\n        list($b_key, $b_value) = $b;\n\n        if ($a_value == $b_value) {\n            // if the values are the same, break ties using the key\n            return strcmp($a_key, $b_key);\n\n        } else {\n            // if not, just sort normally\n            if ($a_value > $b_value) {\n                return -1;\n            } else {\n                return 1;\n            }\n        }\n\n        // 0 should not be possible because keys must be unique\n    }\n\n    /**\n     * Calculates a linear rank-order distance statistic between two sets of\n     * ranked trigrams\n     *\n     * Sums the differences in rank for each trigram. If the trigram does not\n     * appear in both, consider it a difference of $this->_threshold.\n     *\n     * This distance measure was proposed by Cavnar & Trenkle (1994). Despite\n     * its simplicity it has been shown to be highly accurate for language\n     * identification tasks.\n     *\n     * @param array $arr1 the reference set of trigram ranks\n     * @param array $arr2 the target set of trigram ranks\n     *\n     * @return int the sum of the differences between the ranks of\n     *             the two trigram sets\n     * @access private\n     */\n    function _distance($arr1, $arr2)\n    {\n        $sumdist = 0;\n\n        foreach ($arr2 as $key => $value) {\n            if (isset($arr1[$key])) {\n                $distance = abs($value - $arr1[$key]);\n            } else {\n                // $this->_threshold sets the maximum possible distance value\n                // for any one pair of trigrams\n                $distance = $this->_threshold;\n            }\n            $sumdist += $distance;\n        }\n\n        return $sumdist;\n\n        // todo: there are other distance statistics to try, e.g. relative\n        //       entropy, but they're probably more costly to compute\n    }\n\n    /**\n     * Normalizes the score returned by _distance()\n     *\n     * Different if perl compatible or not\n     *\n     * @param int $score      the score from _distance()\n     * @param int $base_count the number of trigrams being considered\n     *\n     * @return float the normalized score\n     * @see    _distance()\n     * @access private\n     */\n    function _normalize_score($score, $base_count = null)\n    {\n        if ($base_count === null) {\n            $base_count = $this->_threshold;\n        }\n\n        if (!$this->_perl_compatible) {\n            return 1 - ($score / $base_count / $this->_threshold);\n        } else {\n            return floor($score / $base_count);\n        }\n    }\n\n\n    /**\n     * Detects the closeness of a sample of text to the known languages\n     *\n     * Calculates the statistical difference between the text and\n     * the trigrams for each language, normalizes the score then\n     * returns results for all languages in sorted order\n     *\n     * If perl compatible, the score is 300-0, 0 being most similar.\n     * Otherwise, it's 0-1 with 1 being most similar.\n     *\n     * The $sample text should be at least a few sentences in length;\n     * should be ascii-7 or utf8 encoded, if another and the mbstring extension\n     * is present it will try to detect and convert. However, experience has\n     * shown that mb_detect_encoding() *does not work very well* with at least\n     * some types of encoding.\n     *\n     * @param string $sample a sample of text to compare.\n     * @param int    $limit  if specified, return an array of the most likely\n     *                       $limit languages and their scores.\n     *\n     * @return mixed sorted array of language scores, blank array if no\n     *               useable text was found\n     * @see    _distance()\n     * @throws Text_LanguageDetect_Exception\n     */\n    public function detect($sample, $limit = 0)\n    {\n        // input check\n        if (!Text_LanguageDetect_Parser::validateString($sample)) {\n            return array();\n        }\n\n        // check char encoding\n        // (only if mbstring extension is compiled and PHP > 4.0.6)\n        if (function_exists('mb_detect_encoding')\n            && function_exists('mb_convert_encoding')\n        ) {\n            // mb_detect_encoding isn't very reliable, to say the least\n            // detection should still work with a sufficient sample\n            //  of ascii characters\n            $encoding = mb_detect_encoding($sample);\n\n            // mb_detect_encoding() will return FALSE if detection fails\n            // don't attempt conversion if that's the case\n            if ($encoding != 'ASCII' && $encoding != 'UTF-8'\n                && $encoding !== false\n            ) {\n                // verify the encoding exists in mb_list_encodings\n                if (in_array($encoding, mb_list_encodings())) {\n                    $sample = mb_convert_encoding($sample, 'UTF-8', $encoding);\n                }\n            }\n        }\n\n        $sample_obj = new Text_LanguageDetect_Parser($sample);\n        $sample_obj->prepareTrigram();\n        if ($this->_use_unicode_narrowing) {\n            $sample_obj->prepareUnicode();\n        }\n        $sample_obj->setPadStart(!$this->_perl_compatible);\n        $sample_obj->analyze();\n\n        $trigram_freqs =& $sample_obj->getTrigramRanks();\n        $trigram_count = count($trigram_freqs);\n\n        if ($trigram_count == 0) {\n            return array();\n        }\n\n        $scores = array();\n\n        // use unicode block detection to narrow down the possibilities\n        if ($this->_use_unicode_narrowing) {\n            $blocks =& $sample_obj->getUnicodeBlocks();\n\n            if (is_array($blocks)) {\n                $present_blocks = array_keys($blocks);\n            } else {\n                throw new Text_LanguageDetect_Exception(\n                    'Error during block detection',\n                    Text_LanguageDetect_Exception::BLOCK_DETECTION\n                );\n            }\n\n            $possible_langs = array();\n\n            foreach ($present_blocks as $blockname) {\n                if (isset($this->_unicode_map[$blockname])) {\n\n                    $possible_langs = array_merge(\n                        $possible_langs,\n                        array_keys($this->_unicode_map[$blockname])\n                    );\n\n                    // todo: faster way to do this?\n                }\n            }\n\n            // could also try an intersect operation rather than a union\n            // in other words, choose languages whose trigrams contain\n            // ALL of the unicode blocks found in this sample\n            // would improve speed but would be completely thrown off by an\n            // unexpected character, like an umlaut appearing in english text\n\n            $possible_langs = array_intersect(\n                array_keys($this->_lang_db),\n                array_unique($possible_langs)\n            );\n\n            // needs to intersect it with the keys of _lang_db in case\n            // languages have been omitted\n\n        } else {\n            // or just try 'em all\n            $possible_langs = array_keys($this->_lang_db);\n        }\n\n\n        foreach ($possible_langs as $lang) {\n            $scores[$lang] = $this->_normalize_score(\n                $this->_distance($this->_lang_db[$lang], $trigram_freqs),\n                $trigram_count\n            );\n        }\n\n        unset($sample_obj);\n\n        if ($this->_perl_compatible) {\n            asort($scores);\n        } else {\n            arsort($scores);\n        }\n\n        // todo: drop languages with a score of $this->_max_score?\n\n        // limit the number of returned scores\n        if ($limit && is_numeric($limit)) {\n            $limited_scores = array();\n\n            $i = 0;\n            foreach ($scores as $key => $value) {\n                if ($i++ >= $limit) {\n                    break;\n                }\n\n                $limited_scores[$key] = $value;\n            }\n\n            return $this->_convertToNameMode($limited_scores, true);\n        } else {\n            return $this->_convertToNameMode($scores, true);\n        }\n    }\n\n    /**\n     * Returns only the most similar language to the text sample\n     *\n     * Calls $this->detect() and returns only the top result\n     *\n     * @param string $sample text to detect the language of\n     *\n     * @return string the name of the most likely language\n     *                or null if no language is similar\n     * @see    detect()\n     * @throws Text_LanguageDetect_Exception\n     */\n    public function detectSimple($sample)\n    {\n        $scores = $this->detect($sample, 1);\n\n        // if top language has the maximum possible score,\n        // then the top score will have been picked at random\n        if (!is_array($scores) || empty($scores)\n            || current($scores) == $this->_max_score\n        ) {\n            return null;\n        } else {\n            return key($scores);\n        }\n    }\n\n    /**\n     * Returns an array containing the most similar language and a confidence\n     * rating\n     *\n     * Confidence is a simple measure calculated from the similarity score\n     * minus the similarity score from the next most similar language\n     * divided by the highest possible score. Languages that have closely\n     * related cousins (e.g. Norwegian and Danish) should generally have lower\n     * confidence scores.\n     *\n     * The similarity score answers the question \"How likely is the text the\n     * returned language regardless of the other languages considered?\" The\n     * confidence score is one way of answering the question \"how likely is the\n     * text the detected language relative to the rest of the language model\n     * set?\"\n     *\n     * To see how similar languages are a priori, see languageSimilarity()\n     *\n     * @param string $sample text for which language will be detected\n     *\n     * @return array most similar language, score and confidence rating\n     *               or null if no language is similar\n     * @see    detect()\n     * @throws Text_LanguageDetect_Exception\n     */\n    public function detectConfidence($sample)\n    {\n        $scores = $this->detect($sample, 2);\n\n        // if most similar language has the max score, it\n        // will have been picked at random\n        if (!is_array($scores) || empty($scores)\n            || current($scores) == $this->_max_score\n        ) {\n            return null;\n        }\n\n        $arr['language'] = key($scores);\n        $arr['similarity'] = current($scores);\n        if (next($scores) !== false) { // if false then no next element\n            // the goal is to return a higher value if the distance between\n            // the similarity of the first score and the second score is high\n\n            if ($this->_perl_compatible) {\n                $arr['confidence'] = (current($scores) - $arr['similarity'])\n                    / $this->_max_score;\n\n            } else {\n                $arr['confidence'] = $arr['similarity'] - current($scores);\n\n            }\n\n        } else {\n            $arr['confidence'] = null;\n        }\n\n        return $arr;\n    }\n\n    /**\n     * Returns the distribution of unicode blocks in a given utf8 string\n     *\n     * For the block name of a single char, use unicodeBlockName()\n     *\n     * @param string $str          input string. Must be ascii or utf8\n     * @param bool   $skip_symbols if true, skip ascii digits, symbols and\n     *                             non-printing characters. Includes spaces,\n     *                             newlines and common punctutation characters.\n     *\n     * @return array\n     * @throws Text_LanguageDetect_Exception\n     */\n    public function detectUnicodeBlocks($str, $skip_symbols)\n    {\n        $skip_symbols = (bool)$skip_symbols;\n        $str          = (string)$str;\n\n        $sample_obj = new Text_LanguageDetect_Parser($str);\n        $sample_obj->prepareUnicode();\n        $sample_obj->prepareTrigram(false);\n        $sample_obj->setUnicodeSkipSymbols($skip_symbols);\n        $sample_obj->analyze();\n        $blocks = $sample_obj->getUnicodeBlocks();\n        unset($sample_obj);\n        return $blocks;\n    }\n\n    /**\n     * Returns the block name for a given unicode value\n     *\n     * If passed a string, will assume it is being passed a UTF8-formatted\n     * character and will automatically convert. Otherwise it will assume it\n     * is being passed a numeric unicode value.\n     *\n     * Make sure input is of the correct type!\n     *\n     * @param mixed $unicode unicode value or utf8 char\n     *\n     * @return mixed the block name string or false if not found\n     * @throws Text_LanguageDetect_Exception\n     */\n    public function unicodeBlockName($unicode)\n    {\n        if (is_string($unicode)) {\n            // assume it is being passed a utf8 char, so convert it\n            if (self::utf8strlen($unicode) > 1) {\n                throw new Text_LanguageDetect_Exception(\n                    'Pass a single char only to this method',\n                    Text_LanguageDetect_Exception::PARAM_TYPE\n                );\n            }\n            $unicode = $this->_utf8char2unicode($unicode);\n\n        } elseif (!is_int($unicode)) {\n            throw new Text_LanguageDetect_Exception(\n                'Input must be of type string or int.',\n                Text_LanguageDetect_Exception::PARAM_TYPE\n            );\n        }\n\n        $blocks = $this->_read_unicode_block_db();\n\n        $result = $this->_unicode_block_name($unicode, $blocks);\n\n        if ($result == -1) {\n            return false;\n        } else {\n            return $result[2];\n        }\n    }\n\n    /**\n     * Searches the unicode block database\n     *\n     * Returns the block name for a given unicode value. unicodeBlockName() is\n     * the public interface for this function, which does input checks which\n     * this function omits for speed.\n     *\n     * @param int   $unicode     the unicode value\n     * @param array $blocks      the block database\n     * @param int   $block_count the number of defined blocks in the database\n     *\n     * @return mixed Block name, -1 if it failed\n     * @see    unicodeBlockName()\n     * @access protected\n     */\n    function _unicode_block_name($unicode, $blocks, $block_count = -1)\n    {\n        // for a reference, see\n        // http://www.unicode.org/Public/UNIDATA/Blocks.txt\n\n        // assume that ascii characters are the most common\n        // so try it first for efficiency\n        if ($unicode <= $blocks[0][1]) {\n            return $blocks[0];\n        }\n\n        // the optional $block_count param is for efficiency\n        // so we this function doesn't have to run count() every time\n        if ($block_count != -1) {\n            $high = $block_count - 1;\n        } else {\n            $high = count($blocks) - 1;\n        }\n\n        $low = 1; // start with 1 because ascii was 0\n\n        // your average binary search algorithm\n        while ($low <= $high) {\n            $mid = floor(($low + $high) / 2);\n\n            if ($unicode < $blocks[$mid][0]) {\n                // if it's lower than the lower bound\n                $high = $mid - 1;\n\n            } elseif ($unicode > $blocks[$mid][1]) {\n                // if it's higher than the upper bound\n                $low = $mid + 1;\n\n            } else {\n                // found it\n                return $blocks[$mid];\n            }\n        }\n\n        // failed to find the block\n        return -1;\n\n        // todo: differentiate when it's out of range or when it falls\n        //       into an unassigned range?\n    }\n\n    /**\n     * Brings up the unicode block database\n     *\n     * @return array the database of unicode block definitions\n     * @throws Text_LanguageDetect_Exception\n     * @access protected\n     */\n    function _read_unicode_block_db()\n    {\n        // since the unicode definitions are always going to be the same,\n        // might as well share the memory for the db with all other instances\n        // of this class\n        static $data;\n\n        if (!isset($data)) {\n            $data = $this->_readdb($this->_unicode_db_filename);\n        }\n\n        return $data;\n    }\n\n    /**\n     * Calculate the similarities between the language models\n     *\n     * Use this function to see how similar languages are to each other.\n     *\n     * If passed 2 language names, will return just those languages compared.\n     * If passed 1 language name, will return that language compared to\n     * all others.\n     * If passed none, will return an array of every language model compared\n     * to every other one.\n     *\n     * @param string $lang1 the name of the first language to be compared\n     * @param string $lang2 the name of the second language to be compared\n     *\n     * @return array scores of every language compared\n     *               or the score of just the provided languages\n     *               or null if one of the supplied languages does not exist\n     * @throws Text_LanguageDetect_Exception\n     */\n    public function languageSimilarity($lang1 = null, $lang2 = null)\n    {\n        $lang1 = $this->_convertFromNameMode($lang1);\n        $lang2 = $this->_convertFromNameMode($lang2);\n        if ($lang1 != null) {\n            $lang1 = strtolower($lang1);\n\n            // check if language model exists\n            if (!isset($this->_lang_db[$lang1])) {\n                return null;\n            }\n\n            if ($lang2 != null) {\n                if (!isset($this->_lang_db[$lang2])) {\n                    // check if language model exists\n                    return null;\n                }\n\n                $lang2 = strtolower($lang2);\n\n                // compare just these two languages\n                return $this->_normalize_score(\n                    $this->_distance(\n                        $this->_lang_db[$lang1],\n                        $this->_lang_db[$lang2]\n                    )\n                );\n\n            } else {\n                // compare just $lang1 to all languages\n                $return_arr = array();\n                foreach ($this->_lang_db as $key => $value) {\n                    if ($key != $lang1) {\n                        // don't compare a language to itself\n                        $return_arr[$key] = $this->_normalize_score(\n                            $this->_distance($this->_lang_db[$lang1], $value)\n                        );\n                    }\n                }\n                asort($return_arr);\n\n                return $return_arr;\n            }\n\n\n        } else {\n            // compare all languages to each other\n            $return_arr = array();\n            foreach (array_keys($this->_lang_db) as $lang1) {\n                foreach (array_keys($this->_lang_db) as $lang2) {\n                    // skip comparing languages to themselves\n                    if ($lang1 != $lang2) {\n\n                        if (isset($return_arr[$lang2][$lang1])) {\n                            // don't re-calculate what's already been done\n                            $return_arr[$lang1][$lang2]\n                                = $return_arr[$lang2][$lang1];\n\n                        } else {\n                            // calculate\n                            $return_arr[$lang1][$lang2]\n                                = $this->_normalize_score(\n                                    $this->_distance(\n                                        $this->_lang_db[$lang1],\n                                        $this->_lang_db[$lang2]\n                                    )\n                                );\n\n                        }\n                    }\n                }\n            }\n            return $return_arr;\n        }\n    }\n\n    /**\n     * Cluster known languages according to languageSimilarity()\n     *\n     * WARNING: this method is EXPERIMENTAL. It is not recommended for common\n     * use, and it may disappear or its functionality may change in future\n     * releases without notice.\n     *\n     * Uses a nearest neighbor technique to generate the maximum possible\n     * number of dendograms from the similarity data.\n     *\n     * @access      public\n     * @return      array language cluster data\n     * @throws      Text_LanguageDetect_Exception\n     * @see         languageSimilarity()\n     * @deprecated  this function will eventually be removed and placed into\n     *              the model generation class\n     */\n    function clusterLanguages()\n    {\n        // todo: set the maximum number of clusters\n        // return cached result, if any\n        if (isset($this->_clusters)) {\n            return $this->_clusters;\n        }\n\n        $langs = array_keys($this->_lang_db);\n\n        $arr = $this->languageSimilarity();\n\n        sort($langs);\n\n        foreach ($langs as $lang) {\n            if (!isset($this->_lang_db[$lang])) {\n                throw new Text_LanguageDetect_Exception(\n                    \"missing $lang!\",\n                    Text_LanguageDetect_Exception::UNKNOWN_LANGUAGE\n                );\n            }\n        }\n\n        // http://www.psychstat.missouristate.edu/multibook/mlt04m.html\n        foreach ($langs as $old_key => $lang1) {\n            $langs[$lang1] = $lang1;\n            unset($langs[$old_key]);\n        }\n\n        $result_data = $really_map = array();\n\n        $i = 0;\n        while (count($langs) > 2 && $i++ < 200) {\n            $highest_score = -1;\n            $highest_key1 = '';\n            $highest_key2 = '';\n            foreach ($langs as $lang1) {\n                foreach ($langs as $lang2) {\n                    if ($lang1 != $lang2\n                        && $arr[$lang1][$lang2] > $highest_score\n                    ) {\n                        $highest_score = $arr[$lang1][$lang2];\n                        $highest_key1 = $lang1;\n                        $highest_key2 = $lang2;\n                    }\n                }\n            }\n\n            if (!$highest_key1) {\n                // should not ever happen\n                throw new Text_LanguageDetect_Exception(\n                    \"no highest key? (step: $i)\",\n                    Text_LanguageDetect_Exception::NO_HIGHEST_KEY\n                );\n            }\n\n            if ($highest_score == 0) {\n                // languages are perfectly dissimilar\n                break;\n            }\n\n            // $highest_key1 and $highest_key2 are most similar\n            $sum1 = array_sum($arr[$highest_key1]);\n            $sum2 = array_sum($arr[$highest_key2]);\n\n            // use the score for the one that is most similar to the rest of\n            // the field as the score for the group\n            // todo: could try averaging or \"centroid\" method instead\n            // seems like that might make more sense\n            // actually nearest neighbor may be better for binary searching\n\n\n            // for \"Complete Linkage\"/\"furthest neighbor\"\n            // sign should be <\n            // for \"Single Linkage\"/\"nearest neighbor\" method\n            // should should be >\n            // results seem to be pretty much the same with either method\n\n            // figure out which to delete and which to replace\n            if ($sum1 > $sum2) {\n                $replaceme = $highest_key1;\n                $deleteme = $highest_key2;\n            } else {\n                $replaceme = $highest_key2;\n                $deleteme = $highest_key1;\n            }\n\n            $newkey = $replaceme . ':' . $deleteme;\n\n            // $replaceme is most similar to remaining languages\n            // replace $replaceme with '$newkey', deleting $deleteme\n\n            // keep a record of which fork is really which language\n            $really_lang = $replaceme;\n            while (isset($really_map[$really_lang])) {\n                $really_lang = $really_map[$really_lang];\n            }\n            $really_map[$newkey] = $really_lang;\n\n\n            // replace the best fitting key, delete the other\n            foreach ($arr as $key1 => $arr2) {\n                foreach ($arr2 as $key2 => $value2) {\n                    if ($key2 == $replaceme) {\n                        $arr[$key1][$newkey] = $arr[$key1][$key2];\n                        unset($arr[$key1][$key2]);\n                        // replacing $arr[$key1][$key2] with $arr[$key1][$newkey]\n                    }\n\n                    if ($key1 == $replaceme) {\n                        $arr[$newkey][$key2] = $arr[$key1][$key2];\n                        unset($arr[$key1][$key2]);\n                        // replacing $arr[$key1][$key2] with $arr[$newkey][$key2]\n                    }\n\n                    if ($key1 == $deleteme || $key2 == $deleteme) {\n                        // deleting $arr[$key1][$key2]\n                        unset($arr[$key1][$key2]);\n                    }\n                }\n            }\n\n\n            unset($langs[$highest_key1]);\n            unset($langs[$highest_key2]);\n            $langs[$newkey] = $newkey;\n\n\n            // some of these may be overkill\n            $result_data[$newkey] = array(\n                                'newkey' => $newkey,\n                                'count' => $i,\n                                'diff' => abs($sum1 - $sum2),\n                                'score' => $highest_score,\n                                'bestfit' => $replaceme,\n                                'otherfit' => $deleteme,\n                                'really' => $really_lang,\n                            );\n        }\n\n        $return_val = array(\n                'open_forks' => $langs,\n                        // the top level of clusters\n                        // clusters that are mutually exclusive\n                        // or specified by a specific maximum\n\n                'fork_data' => $result_data,\n                        // data for each split\n\n                'name_map' => $really_map,\n                        // which cluster is really which language\n                        // using the nearest neighbor technique, the cluster\n                        // inherits all of the properties of its most-similar member\n                        // this keeps track\n            );\n\n\n        // saves the result in the object\n        $this->_clusters = $return_val;\n\n        return $return_val;\n    }\n\n\n    /**\n     * Perform an intelligent detection based on clusterLanguages()\n     *\n     * WARNING: this method is EXPERIMENTAL. It is not recommended for common\n     * use, and it may disappear or its functionality may change in future\n     * releases without notice.\n     *\n     * This compares the sample text to top the top level of clusters. If the\n     * sample is similar to the cluster it will drop down and compare it to the\n     * languages in the cluster, and so on until it hits a leaf node.\n     *\n     * this should find the language in considerably fewer compares\n     * (the equivalent of a binary search), however clusterLanguages() is costly\n     * and the loss of accuracy from this technique is significant.\n     *\n     * This method may need to be 'fuzzier' in order to become more accurate.\n     *\n     * This function could be more useful if the universe of possible languages\n     * was very large, however in such cases some method of Bayesian inference\n     * might be more helpful.\n     *\n     * @param string $str input string\n     *\n     * @return array language scores (only those compared)\n     * @throws Text_LanguageDetect_Exception\n     * @see    clusterLanguages()\n     */\n    public function clusteredSearch($str)\n    {\n        // input check\n        if (!Text_LanguageDetect_Parser::validateString($str)) {\n            return array();\n        }\n\n        // clusterLanguages() will return a cached result if possible\n        // so it's safe to call it every time\n        $result = $this->clusterLanguages();\n\n        $dendogram_start = $result['open_forks'];\n        $dendogram_data  = $result['fork_data'];\n        $dendogram_alias = $result['name_map'];\n\n        $sample_obj = new Text_LanguageDetect_Parser($str);\n        $sample_obj->prepareTrigram();\n        $sample_obj->setPadStart(!$this->_perl_compatible);\n        $sample_obj->analyze();\n        $sample_result = $sample_obj->getTrigramRanks();\n        $sample_count  = count($sample_result);\n\n        // input check\n        if ($sample_count == 0) {\n            return array();\n        }\n\n        $i = 0; // counts the number of steps\n\n        foreach ($dendogram_start as $lang) {\n            if (isset($dendogram_alias[$lang])) {\n                $lang_key = $dendogram_alias[$lang];\n            } else {\n                $lang_key = $lang;\n            }\n\n            $scores[$lang] = $this->_normalize_score(\n                $this->_distance($this->_lang_db[$lang_key], $sample_result),\n                $sample_count\n            );\n\n            $i++;\n        }\n\n        if ($this->_perl_compatible) {\n            asort($scores);\n        } else {\n            arsort($scores);\n        }\n\n        $top_score = current($scores);\n        $top_key = key($scores);\n\n        // of starting forks, $top_key is the most similar to the sample\n\n        $cur_key = $top_key;\n        while (isset($dendogram_data[$cur_key])) {\n            $lang1 = $dendogram_data[$cur_key]['bestfit'];\n            $lang2 = $dendogram_data[$cur_key]['otherfit'];\n            foreach (array($lang1, $lang2) as $lang) {\n                if (isset($dendogram_alias[$lang])) {\n                    $lang_key = $dendogram_alias[$lang];\n                } else {\n                    $lang_key = $lang;\n                }\n\n                $scores[$lang] = $this->_normalize_score(\n                    $this->_distance($this->_lang_db[$lang_key], $sample_result),\n                    $sample_count\n                );\n\n                //todo: does not need to do same comparison again\n            }\n\n            $i++;\n\n            if ($scores[$lang1] > $scores[$lang2]) {\n                $cur_key = $lang1;\n                $loser_key = $lang2;\n            } else {\n                $cur_key = $lang2;\n                $loser_key = $lang1;\n            }\n\n            $diff = $scores[$cur_key] - $scores[$loser_key];\n\n            // $cur_key ({$dendogram_alias[$cur_key]}) wins\n            // over $loser_key ({$dendogram_alias[$loser_key]})\n            // with a difference of $diff\n        }\n\n        // found result in $i compares\n\n        // rather than sorting the result, preserve it so that you can see\n        // which paths the algorithm decided to take along the tree\n\n        // but sometimes the last item is only the second highest\n        if (($this->_perl_compatible  && (end($scores) > prev($scores)))\n            || (!$this->_perl_compatible && (end($scores) < prev($scores)))\n        ) {\n            $real_last_score = current($scores);\n            $real_last_key = key($scores);\n\n            // swaps the 2nd-to-last item for the last item\n            unset($scores[$real_last_key]);\n            $scores[$real_last_key] = $real_last_score;\n        }\n\n\n        if (!$this->_perl_compatible) {\n            $scores = array_reverse($scores, true);\n            // second param requires php > 4.0.3\n        }\n\n        return $scores;\n    }\n\n    /**\n     * ut8-safe strlen()\n     *\n     * Returns the numbers of characters (not bytes) in a utf8 string\n     *\n     * @param string $str string to get the length of\n     *\n     * @return int number of chars\n     */\n    public static function utf8strlen($str)\n    {\n        // utf8_decode() will convert unknown chars to '?', which is actually\n        // ideal for counting.\n\n        return strlen(utf8_decode($str));\n\n        // idea stolen from dokuwiki\n    }\n\n    /**\n     * Returns the unicode value of a utf8 char\n     *\n     * @param string $char a utf8 (possibly multi-byte) char\n     *\n     * @return int unicode value\n     * @access protected\n     * @link   http://en.wikipedia.org/wiki/UTF-8\n     */\n    function _utf8char2unicode($char)\n    {\n        // strlen() here will actually get the binary length of a single char\n        switch (strlen($char)) {\n        case 1:\n            // normal ASCII-7 byte\n            // 0xxxxxxx -->  0xxxxxxx\n            return ord($char{0});\n\n        case 2:\n            // 2 byte unicode\n            // 110zzzzx 10xxxxxx --> 00000zzz zxxxxxxx\n            $z = (ord($char{0}) & 0x000001F) << 6;\n            $x = (ord($char{1}) & 0x0000003F);\n            return ($z | $x);\n\n        case 3:\n            // 3 byte unicode\n            // 1110zzzz 10zxxxxx 10xxxxxx --> zzzzzxxx xxxxxxxx\n            $z =  (ord($char{0}) & 0x0000000F) << 12;\n            $x1 = (ord($char{1}) & 0x0000003F) << 6;\n            $x2 = (ord($char{2}) & 0x0000003F);\n            return ($z | $x1 | $x2);\n\n        case 4:\n            // 4 byte unicode\n            // 11110zzz 10zzxxxx 10xxxxxx 10xxxxxx -->\n            // 000zzzzz xxxxxxxx xxxxxxxx\n            $z1 = (ord($char{0}) & 0x00000007) << 18;\n            $z2 = (ord($char{1}) & 0x0000003F) << 12;\n            $x1 = (ord($char{2}) & 0x0000003F) << 6;\n            $x2 = (ord($char{3}) & 0x0000003F);\n            return ($z1 | $z2 | $x1 | $x2);\n        }\n    }\n\n    /**\n     * utf8-safe fast character iterator\n     *\n     * Will get the next character starting from $counter, which will then be\n     * incremented. If a multi-byte char the bytes will be concatenated and\n     * $counter will be incremeted by the number of bytes in the char.\n     *\n     * @param string $str             the string being iterated over\n     * @param int    &$counter        the iterator, will increment by reference\n     * @param bool   $special_convert whether to do special conversions\n     *\n     * @return char the next (possibly multi-byte) char from $counter\n     * @access private\n     */\n    static function _next_char($str, &$counter, $special_convert = false)\n    {\n        $char = $str{$counter++};\n        $ord = ord($char);\n\n        // for a description of the utf8 system see\n        // http://www.phpclasses.org/browse/file/5131.html\n\n        // normal ascii one byte char\n        if ($ord <= 127) {\n            // special conversions needed for this package\n            // (that only apply to regular ascii characters)\n            // lower case, and convert all non-alphanumeric characters\n            // other than \"'\" to space\n            if ($special_convert && $char != ' ' && $char != \"'\") {\n                if ($ord >= 65 && $ord <= 90) { // A-Z\n                    $char = chr($ord + 32); // lower case\n                } elseif ($ord < 97 || $ord > 122) { // NOT a-z\n                    $char = ' '; // convert to space\n                }\n            }\n\n            return $char;\n\n        } elseif ($ord >> 5 == 6) { // two-byte char\n            // multi-byte chars\n            $nextchar = $str{$counter++}; // get next byte\n\n            // lower-casing of non-ascii characters is still incomplete\n\n            if ($special_convert) {\n                // lower case latin accented characters\n                if ($ord == 195) {\n                    $nextord = ord($nextchar);\n                    $nextord_adj = $nextord + 64;\n                    // for a reference, see\n                    // http://www.ramsch.org/martin/uni/fmi-hp/iso8859-1.html\n\n                    // &Agrave; - &THORN; but not &times;\n                    if ($nextord_adj >= 192\n                        && $nextord_adj <= 222\n                        && $nextord_adj != 215\n                    ) {\n                        $nextchar = chr($nextord + 32);\n                    }\n\n                } elseif ($ord == 208) {\n                    // lower case cyrillic alphabet\n                    $nextord = ord($nextchar);\n                    // if A - Pe\n                    if ($nextord >= 144 && $nextord <= 159) {\n                        // lower case\n                        $nextchar = chr($nextord + 32);\n\n                    } elseif ($nextord >= 160 && $nextord <= 175) {\n                        // if Er - Ya\n                        // lower case\n                        $char = chr(209); // == $ord++\n                        $nextchar = chr($nextord - 32);\n                    }\n                }\n            }\n\n            // tag on next byte\n            return $char . $nextchar;\n        } elseif ($ord >> 4  == 14) { // three-byte char\n\n            // tag on next 2 bytes\n            return $char . $str{$counter++} . $str{$counter++};\n\n        } elseif ($ord >> 3 == 30) { // four-byte char\n\n            // tag on next 3 bytes\n            return $char . $str{$counter++} . $str{$counter++} . $str{$counter++};\n\n        } else {\n            // error?\n        }\n    }\n\n    /**\n     * Converts an $language input parameter from the configured mode\n     * to the language name that is used internally.\n     *\n     * Works for strings and arrays.\n     *\n     * @param string|array $lang       A language description (\"english\"/\"en\"/\"eng\")\n     * @param boolean      $convertKey If $lang is an array, setting $key\n     *                                 converts the keys to the language name.\n     *\n     * @return string|array Language name\n     */\n    function _convertFromNameMode($lang, $convertKey = false)\n    {\n        if ($this->_name_mode == 0) {\n            return $lang;\n        }\n\n        if ($this->_name_mode == 2) {\n            $method = 'code2ToName';\n        } else {\n            $method = 'code3ToName';\n        }\n\n        if (is_string($lang)) {\n            return (string)Text_LanguageDetect_ISO639::$method($lang);\n        }\n\n        $newlang = array();\n        foreach ($lang as $key => $val) {\n            if ($convertKey) {\n                $newkey = (string)Text_LanguageDetect_ISO639::$method($key);\n                $newlang[$newkey] = $val;\n            } else {\n                $newlang[$key] = (string)Text_LanguageDetect_ISO639::$method($val);\n            }\n        }\n        return $newlang;\n    }\n\n    /**\n     * Converts an $language output parameter from the language name that is\n     * used internally to the configured mode.\n     *\n     * Works for strings and arrays.\n     *\n     * @param string|array $lang       A language description (\"english\"/\"en\"/\"eng\")\n     * @param boolean      $convertKey If $lang is an array, setting $key\n     *                                 converts the keys to the language name.\n     *\n     * @return string|array Language name\n     */\n    function _convertToNameMode($lang, $convertKey = false)\n    {\n        if ($this->_name_mode == 0) {\n            return $lang;\n        }\n\n        if ($this->_name_mode == 2) {\n            $method = 'nameToCode2';\n        } else {\n            $method = 'nameToCode3';\n        }\n\n        if (is_string($lang)) {\n            return Text_LanguageDetect_ISO639::$method($lang);\n        }\n\n        $newlang = array();\n        foreach ($lang as $key => $val) {\n            if ($convertKey) {\n                $newkey = Text_LanguageDetect_ISO639::$method($key);\n                $newlang[$newkey] = $val;\n            } else {\n                $newlang[$key] = Text_LanguageDetect_ISO639::$method($val);\n            }\n        }\n        return $newlang;\n    }\n}\n\n/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */\n?>\n"
  },
  {
    "path": "libraries/readability/ImageCaching.php",
    "content": "<?php\nclass ImageCaching {\n\n\tconst UPPER_LIMIT = 256000;\n\tconst UPPER_MAX = 3145728;\n\tconst LOWER_LIMIT = 512;\n\tconst LOWER_MIN = 48;\n\n\tpublic $lower_limit_setting = null;\n\tpublic $upper_limit_setting = null;\n\n\tprotected $images = array();\n\tprotected $context_get = array();\n\n\tfunction __construct() {\n\t\t$this->lower_limit_setting = self::LOWER_LIMIT;\n\t\t$this->upper_limit_setting = self::UPPER_LIMIT;\n        $opts = array( \n             'http' => array( \n                 'method'=>\"GET\",\n                 'header'=>\"Accept-language: en\\r\\n\" .\n                                    \"Connection: close\\r\\n\" .\n                                    \"User-Agent: Opera/9.80 (Windows NT 6.1; Win64; x64; Edition Next) Presto/2.12.388 Version/12.15\\r\\n\"\n             ) \n         );\n        $this->context_get = stream_context_create($opts);\n\t}\n\n\tpublic function setAllowedSizes($lower, $upper) {\n\t\tif ($lower > $upper) {\n\t\t\t$tmp = $upper; $upper = $lower; $lower = $tmp;\n\t\t}\n\t\tif ($lower && $lower > self::LOWER_MIN && $lower < self::UPPER_MAX) $this->lower_limit_setting = $lower;\n\t\tif ($upper && $upper > self::LOWER_MIN && $upper < self::UPPER_MAX) $this->upper_limit_setting = $upper;\n\t}\n\n\tpublic function cacheFromString(&$html) {\n\t\t$callback = function ($matches) {\n\t\t\t$data_uri = '';\n\t\t\t$url = $matches[1];\n\t\t\tif (!preg_match('!^https?://!i', $url) || strlen($url) < 12) return $matches[0];\n\t\t\t$url = filter_var($url, FILTER_SANITIZE_URL);\n\t\t\tif (!$this->images[$url]){\n\t\t\t\t$data_uri = $this->getImageDataURI($url);\n\t\t\t\tif (strlen($data_uri) > 1)\n\t\t\t\t    $this->images[$url] = $data_uri;\n\t\t\t\telse \n\t\t\t\t\treturn $matches[0];\n\t\t\t} else {\n\t\t\t\t$data_uri = $this->images[$url];\n\t\t\t}\n\t\t\tif (strlen($data_uri) > 1)\n\t\t\t\treturn '<img src=\"' . $data_uri . '\" alt=\"' . $matches[1] . '\"/>';\n\t\t\telse\n\t\t\t\treturn $matches[0];\n\t\t};\n\n\t\t$html = preg_replace_callback('/< *img[^>]+src *= *[\"\\']?([^\"\\'>]*)[^>]*>/i', $callback, $html);\n\t}\n\n\tpublic function cacheFromDocument(&$document) {\n\t\t$imageNodes = $document->getElementsByTagName('img');\n\t\tfor ($node = null, $nodeIndex = 0; ($node = $imageNodes->item($nodeIndex)); $nodeIndex++) {\n\t\t\t$url = $node->getAttribute('src');\n\t\t\t$node->removeAttribute('class');\n\t\t\t$node->removeAttribute('id');\n\t\t\tif (!preg_match('!^https?://!i', $url) || strlen($url) < 12) continue;\n\t\t\t$url = filter_var($url, FILTER_SANITIZE_URL);\n\t\t\t$data_uri = '';\n\t\t\tif (!$this->images[$url]){\n\t\t\t\t$data_uri = $this->getImageDataURI($url);\n\t\t\t\tif (strlen($data_uri) > 1)\n\t\t\t\t    $this->images[$url] = $data_uri;\n\t\t\t\telse \n\t\t\t\t    continue;\n\t\t\t} else {\n\t\t\t\t$data_uri = $this->images[$url];\n\t\t\t}\n\t\t\tif (strlen($data_uri) > 1) {\n\t\t\t\t$node->setAttribute('src', $data_uri);\n\t\t\t\t$node->setAttribute('alt', $url);\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected function getFileSize($image) {\n\t\t$contentLength = 0;\n\t\t$status = 0;\n\t\t$matches = array();\n\n\t\tif (!function_exists('curl_init'))\n\t\t\treturn 0;\n\n\t\t$ch = curl_init($image);\n\t\tcurl_setopt($ch, CURLOPT_NOBODY, true);\n\t\tcurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n\t\tcurl_setopt($ch, CURLOPT_HEADER, true);\n\t\tcurl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);\n        curl_setopt($ch, CURLOPT_USERAGENT, \"Opera/9.80 (Windows NT 6.1; Win64; x64; Edition Next) Presto/2.12.388 Version/12.15\");\n\t\t$data = curl_exec($ch);\n\t\tcurl_close($ch);\n\t\tif ($data === false)\n\t\t\treturn 0;\n\n\t\tif (preg_match('/^HTTP\\/1\\.[01] (\\d\\d\\d)/', $data, $matches))\n\t\t\t$status = (int) $matches[1];\n\t\tif ($status === 200 && preg_match('/Content-Length: (\\d+)/', $data, $matches))\n\t\t\t$contentLength = (int) $matches[1];\n\n\t\treturn $contentLength;\n\t}\n\n\tprotected function getImageDataURI($image, $mime = '') {\n\t\t$image = filter_var($image, FILTER_SANITIZE_URL);\n\t\tif (!preg_match('!^https?://!i', $image))\n\t\t\treturn '';\n\n\t\t$ext = substr(strrchr($image, \".\") , 1, 3);\n\t\tif (strcasecmp($ext, 'jpg') === 0 || strcasecmp($ext, 'png') === 0 || strcasecmp($ext, 'jpe') === 0 || strcasecmp($ext, 'gif') === 0) {\n\t\t\t$size = $this->getFileSize($image);\n\t\t\tif ($size < $this->lower_limit_setting || $size > $this->upper_limit_setting)\n\t\t\t\treturn '';\n\t\t\t$content = @file_get_contents($image, false, $this->context_get);\n\t\t\tif (function_exists('finfo_open')) \n\t\t\t\t$mime = (new finfo(FILEINFO_MIME_TYPE))->buffer($content);\n\t\t\tif (!preg_match('/^image/i', $mime)) return '';\n\t\t\treturn 'data:' . $mime . ';base64,' . base64_encode($content);\n\t\t}\n\t\treturn '';\n\t}\n}\n?>"
  },
  {
    "path": "libraries/readability/JSLikeHTMLElement.php",
    "content": "<?php\n/**\n* JavaScript-like HTML DOM Element\n*\n* This class extends PHP's DOMElement to allow\n* users to get and set the innerHTML property of\n* HTML elements in the same way it's done in \n* JavaScript.\n*\n* Example usage:\n* @code\n* require_once 'JSLikeHTMLElement.php';\n* header('Content-Type: text/plain');\n* $doc = new DOMDocument();\n* $doc->registerNodeClass('DOMElement', 'JSLikeHTMLElement');\n* $doc->loadHTML('<div><p>Para 1</p><p>Para 2</p></div>');\n* $elem = $doc->getElementsByTagName('div')->item(0);\n* \n* // print innerHTML\n* echo $elem->innerHTML; // prints '<p>Para 1</p><p>Para 2</p>'\n* echo \"\\n\\n\";\n* \n* // set innerHTML\n* $elem->innerHTML = '<a href=\"http://fivefilters.org\">FiveFilters.org</a>';\n* echo $elem->innerHTML; // prints '<a href=\"http://fivefilters.org\">FiveFilters.org</a>'\n* echo \"\\n\\n\";\n* \n* // print document (with our changes)\n* echo $doc->saveXML();\n* @endcode\n*\n* @author Keyvan Minoukadeh - http://www.keyvan.net - keyvan@keyvan.net\n* @see http://fivefilters.org (the project this was written for)\n*/\nclass JSLikeHTMLElement extends DOMElement\n{\n\t/**\n\t* Used for setting innerHTML like it's done in JavaScript:\n\t* @code\n\t* $div->innerHTML = '<h2>Chapter 2</h2><p>The story begins...</p>';\n\t* @endcode\n\t*/\n\tpublic function __set($name, $value) {\n\t\tif ($name == 'innerHTML') {\n\t\t\t// first, empty the element\n\t\t\tfor ($x=$this->childNodes->length-1; $x>=0; $x--) {\n\t\t\t\t$this->removeChild($this->childNodes->item($x));\n\t\t\t}\n\t\t\t// $value holds our new inner HTML\n\t\t\tif ($value != '') {\n\t\t\t\t$f = $this->ownerDocument->createDocumentFragment();\n\t\t\t\t// appendXML() expects well-formed markup (XHTML)\n\t\t\t\t$result = @$f->appendXML($value); // @ to suppress PHP warnings\n\t\t\t\tif ($result) {\n\t\t\t\t\tif ($f->hasChildNodes()) $this->appendChild($f);\n\t\t\t\t} else {\n\t\t\t\t\t// $value is probably ill-formed\n\t\t\t\t\t$f = new DOMDocument();\n\t\t\t\t\t$value = mb_convert_encoding($value, 'HTML-ENTITIES', 'UTF-8');\n\t\t\t\t\t// Using <htmlfragment> will generate a warning, but so will bad HTML\n\t\t\t\t\t// (and by this point, bad HTML is what we've got).\n\t\t\t\t\t// We use it (and suppress the warning) because an HTML fragment will \n\t\t\t\t\t// be wrapped around <html><body> tags which we don't really want to keep.\n\t\t\t\t\t// Note: despite the warning, if loadHTML succeeds it will return true.\n\t\t\t\t\t$result = @$f->loadHTML('<htmlfragment>'.$value.'</htmlfragment>');\n\t\t\t\t\tif ($result) {\n\t\t\t\t\t\t$import = $f->getElementsByTagName('htmlfragment')->item(0);\n\t\t\t\t\t\tforeach ($import->childNodes as $child) {\n\t\t\t\t\t\t\t$importedNode = $this->ownerDocument->importNode($child, true);\n\t\t\t\t\t\t\t$this->appendChild($importedNode);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// oh well, we tried, we really did. :(\n\t\t\t\t\t\t// this element is now empty\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t$trace = debug_backtrace();\n\t\t\ttrigger_error('Undefined property via __set(): '.$name.' in '.$trace[0]['file'].' on line '.$trace[0]['line'], E_USER_NOTICE);\n\t\t}\n\t}\n\n\t/**\n\t* Used for getting innerHTML like it's done in JavaScript:\n\t* @code\n\t* $string = $div->innerHTML;\n\t* @endcode\n\t*/\t\n\tpublic function __get($name)\n\t{\n\t\tif ($name == 'innerHTML') {\n\t\t\t$inner = '';\n\t\t\tforeach ($this->childNodes as $child) {\n\t\t\t\t$inner .= $this->ownerDocument->saveXML($child);\n\t\t\t}\n\t\t\treturn $inner;\n\t\t}\n\n\t\t$trace = debug_backtrace();\n\t\ttrigger_error('Undefined property via __get(): '.$name.' in '.$trace[0]['file'].' on line '.$trace[0]['line'], E_USER_NOTICE);\n\t\treturn null;\n\t}\n\n\tpublic function __toString()\n\t{\n\t\treturn '['.$this->tagName.']';\n\t}\n}\n?>"
  },
  {
    "path": "libraries/readability/Readability.php",
    "content": "<?php\n/**\n* Arc90's Readability ported to PHP for FiveFilters.org\n* Based on readability.js version 1.7.1 (without multi-page support)\n* ------------------------------------------------------\n* Original URL: http://lab.arc90.com/experiments/readability/js/readability.js\n* Arc90's project URL: http://lab.arc90.com/experiments/readability/\n* JS Source: http://code.google.com/p/arc90labs-readability\n* Ported by: Keyvan Minoukadeh, http://www.keyvan.net\n* Modded by: Dither, https://dithersky.wordpress.com\n* More information: http://fivefilters.org/content-only/\n* License: Apache License, Version 2.0\n* Requires: PHP version 5.2.0+\n* Date: 2013-08-02\n*\n* Differences between the PHP port and the original\n* ------------------------------------------------------\n* Arc90's Readability is designed to run in the browser. It works on the DOM\n* tree (the parsed HTML) after the page's CSS styles have been applied and\n* Javascript code executed. This PHP port does not run inside a browser.\n* We use PHP's ability to parse HTML to build our DOM tree, but we cannot\n* rely on CSS or Javascript support. As such, the results will not always\n* match Arc90's Readability. (For example, if a web page contains CSS style\n* rules or Javascript code which hide certain HTML elements from display,\n* Arc90's Readability will dismiss those from consideration but our PHP port,\n* unable to understand CSS or Javascript, will not know any better.)\n*\n* Another significant difference is that the aim of Arc90's Readability is\n* to re-present the main content block of a given web page so users can\n* read it more easily in their browsers. Correct identification, clean up,\n* and separation of the content block is only a part of this process.\n* This PHP port is only concerned with this part, it does not include code\n* that relates to presentation in the browser - Arc90 already do\n* that extremely well, and for PDF output there's FiveFilters.org's\n* PDF Newspaper: http://fivefilters.org/pdf-newspaper/.\n*\n* Finally, this class contains methods that might be useful for developers\n* working on HTML document fragments. So without deviating too much from\n* the original code (which I don't want to do because it makes debugging\n* and updating more difficult), I've tried to make it a little more\n* developer friendly. You should be able to use the methods here on\n* existing DOMElement objects without passing an entire HTML document to\n* be parsed.\n*/\n\n// This class allows us to do JavaScript like assignements to innerHTML\nrequire_once(dirname(__FILE__).'/JSLikeHTMLElement.php');\n// This allows image caching functionality\nrequire_once(dirname(__FILE__).'/ImageCaching.php');\n// Placeholder for bayesian text/attributes filter class...\n\n// Alternative usage (for testing only!)\n// uncomment the lines below and call Readability.php in your browser\n// passing it the URL of the page you'd like content from, e.g.:\n// http://www.some.host/Readability.php?link=http://example.com/articles/01/02/2000/what-about-us.html\n\n/** /\nif (function_exists('curl_init') && isset($_GET['link']) && $_GET['link'] !== '') { // other file is using ?url= ...\n\t$url = filter_var($_GET['link'], FILTER_SANITIZE_URL);\n\tif (!preg_match('!^https?://!i', $url)) $url = 'http://'.$url;\n\t$ch = curl_init();\n\tcurl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);\n\tcurl_setopt($ch, CURLOPT_HEADER, false);\n\tcurl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);\n\tcurl_setopt($ch, CURLOPT_URL, $url);\n\tcurl_setopt($ch, CURLOPT_REFERER, $url);\n\tcurl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);\n\t$html = curl_exec($ch);\n\tcurl_close($ch);\n\t$r = new Readability($html, $url);\n\t$r->debug = true;\n\t$r->init();\n\t//$r->preserveImages();\n\tunset($html);\n\techo $r->articleContent->innerHTML;\n}\n/**/\n\nclass Readability\n{\n\tpublic $version = '1.7.2-without-multi-page';\n\tpublic $convertLinksToFootnotes = false;\n\tpublic $revertForcedParagraphElements = true;\n\tpublic $articleTitle;\n\tpublic $articleContent;\n\tpublic $dom;\n\tpublic $url = null; // optional - URL where HTML was retrieved\n\tpublic $lightClean = true; // preserves more content (experimental)\n\tpublic $debug = false;\n\tpublic $tidied = false;\n\tpublic $imageCache = null; // Cache the images from the article\n\tprotected $debugText = ''; // error text for one time output\n\tprotected $domainRegExp = null; // article domain regexp for calibration\n\tprotected $body = null; //\n\tprotected $bodyCache = null; // Cache the body HTML in case we need to re-use it later\n\tprotected $flags = 7; // 1 | 2 | 4;   // Start with all processing flags set.\n\tprotected $success = false; // indicates whether we were able to extract or not\n\n\t/**\n\t* All of the regular expressions in use within readability.\n\t* Defined up here so we don't instantiate them repeatedly in loops.\n\t**/\n\tpublic $regexps = array(\n\t\t'unlikelyCandidates' => '/display\\s*:\\s*none|ignore|\\binfo|annoy|clock|date|time|author|intro|links|hidd?e|about|archive|\\bprint|bookmark|tags|share|search|social|robot|published|combx|comment|mast(?:head)|subscri|community|category|disqus|extra|head(?:er|note)|floor|foot(?:er|note)|menu|tool|function|nav|remark|rss|shoutbox|tool|widget|meta|banner|sponsor|adsense|inner-?ad|ad-|sponsor|\\badv\\b|\\bads\\b|agr?egate?|pager|sidebar|popup|tweet|twitter/i',\n\t\t'okMaybeItsACandidate' => '/article\\b|contain|\\bcontent|column|general|detail|shadow|lightbox|blog|body|entry|main|page/i',\n\t\t'positive' => '/read|full|article|body|\\bcontent|contain|entry|main|markdown|page|attach|pagination|post|text|blog|story/i',\n\t\t'negative' => '/bottom|stat|info|discuss|e[\\-]?mail|comment|reply|log.{2}(n|ed)|sign|single|combx|com-|contact|_nav|link|media|\\bout|promo|\\bad-|related|scroll|shoutbox|sidebar|sponsor|shopping|teaser/i',\n\t\t'divToPElements' => '/<(?:blockquote|code|div|article|footer|aside|img|p|pre|dl|ol|ul)/mi',\n\t\t'killBreaks' => '/(<br\\s*\\/?>([ \\r\\n\\s]|&nbsp;?)*)+/',\n\t\t'media' => '!//(?:[^\\.\\?/]+\\.)?(?:youtu(?:be)?|soundcloud|vimeo|pornhub|xvideos|twitvid|rutube|viddler)\\.(?:com|be|org|net)/!i',\n\t\t'skipFootnoteLink' => '/^\\s*(\\[?[a-z0-9]{1,2}\\]?|^|edit|citation needed)\\s*$/i'\n\t);\n\n\tpublic $tidy_config = array(\n\t\t'tidy-mark' => false,\n\t\t'vertical-space' => false,\n\t\t'doctype' => 'omit',\n\t\t'numeric-entities' => false,\n\t\t'preserve-entities' => true,\n\t\t'break-before-br' => false,\n\t\t'clean' => true,\n\t\t'output-xhtml' => true,\n\t\t'logical-emphasis' => true,\n\t\t'show-body-only' => false,\n\t\t'new-blocklevel-tags' => 'article,aside,audio,details,figcaption,figure,footer,header,hgroup,nav,section,source,summary,temp,track,video',\n\t\t'new-empty-tags' => 'command,embed,keygen,source,track,wbr',\n\t\t'new-inline-tags' => 'audio,canvas,command,datalist,embed,keygen,mark,meter,output,progress,time,video,wbr',\n\t\t'wrap' => 0,\n\t\t'drop-empty-paras' => true,\n\t\t'drop-proprietary-attributes' => false,\n\t\t'enclose-text' => true,\n\t\t'enclose-block-text' => true,\n\t\t'merge-divs' => true,\n\t\t'merge-spans' => true,\n\t\t'input-encoding' => '????',\n\t\t'output-encoding' => 'utf8',\n\t\t'hide-comments' => true\n\t);\n\n\t// raw HTML filters\n\tprotected $pre_filters = array(\n\t\t'!<script[^>]*>(.*?)</script>!is' => '', // remove obvious scripts\n\t\t'!<style[^>]*>(.*?)</style>!is' => '', // remove obvious styles\n\t\t'!</?span[^>]*>!is' => '', // remove spans as we redefine styles and they're probably special-styled\n\t\t'!<font[^>]*>\\s*\\[AD\\]\\s*</font>!is' => '', // HACK: firewall-filtered content\n\t\t'!(<br[^>]*>[ \\r\\n\\s]*){2,}!i' => '</p><p>', // HACK: replace linebreaks plus br's with p's\n\t\t//'!</?noscript>!is' => '', // replace noscripts\n\t\t'!<(/?)font[^>]*>!is' => '<\\\\1span>' // replace fonts to spans\n\t);\n\n\t// output HTML filters\n\tprotected $post_filters = array(\n\t\t'/<br\\s*\\/?>\\s*<p/i' => '<p', // replace excessive br's\n\t\t'!<(?:a|div|p)[^>]+/>!is' => '', // replace empty tags that break layouts\n\t\t//'!<(\\s*/?\\s*(?:blockquote|br|hr|code|div|article|span|footer|aside|p|pre|dl|li|ul|ol)) [^>]+>!is' => \"<\\\\1>\", // remove all attributes on text tags\n\t\t\"/\\n+/\" => \"\\n\", //single newlines cleanup\n\t\t'!<pre[^>]*>\\s*<code!is' => '<pre', // modern web...\n\t\t'!</code>\\s*</pre>!is' => '</pre>',\n\t\t'!<[hb]r>!is' => '<\\\\1 />'\n\t);\n\n\t// flags\n\tconst FLAG_STRIP_UNLIKELYS = 1;\n\tconst FLAG_WEIGHT_ATTRIBUTES = 2;\n\tconst FLAG_CLEAN_CONDITIONALLY = 4;\n\tconst FLAG_DISABLE_PREFILTER = 8;\n\tconst FLAG_DISABLE_POSTFILTER = 16;\n\n\t// constants\n\tconst SCORE_CHARS_IN_PARAGRAPH = 100;\n\tconst SCORE_WORDS_IN_PARAGRAPH = 20;\n\tconst GRANDPARENT_SCORE_DIVISOR = 2.2;\n\tconst MIN_PARAGRAPH_LENGTH = 20;\n\tconst MIN_COMMAS_IN_PARAGRAPH = 6;\n\tconst MIN_ARTICLE_LENGTH = 200;\n\tconst MIN_NODE_LENGTH = 80;\n\tconst MAX_LINK_DENSITY = 0.25;\n\n\t/**\n\t* Create instance of Readability\n\t* @param string UTF-8 encoded string\n\t* @param string (optional) URL associated with HTML (for footnotes)\n\t* @param string (optional) Which parser to use for turning raw HTML into a DOMDocument\n\t* @param boolean (optional) Use tidy\n\t*/\n\tfunction __construct($html, $url=null, $parser='libxml', $use_tidy=true) {\n\t\t$this->url = $url;\n\t\t$this->debugText = 'Parsing URL: '.$url.\"\\n\";\n\t\tif ($url) $this->domainRegExp = '/'.strtr(preg_replace('/www\\d*\\./', '', parse_url($url)['host']), array('.' => '\\.')).'/';\n\n\t\tmb_internal_encoding(\"UTF-8\");\n\t\tmb_http_output(\"UTF-8\");\n\t\tmb_regex_encoding(\"UTF-8\");\n\n\t\t$this->imageCache = new ImageCaching();\n\n\t\t// HACK: dirty cleanup to replace some stuff; shouldn't use regexps with HTML but well...\n\t\tif (!$this->flagIsActive(self::FLAG_DISABLE_PREFILTER)) {\n\t\t\ttry {\n\t\t\t\tforeach ($this->pre_filters as $search => $replace) {\n\t\t\t\t\t$html = preg_replace($search, $replace, $html);\n\t\t\t\t}\n\t\t\t\tunset($search, $replace);\n\t\t\t} catch (Exception $e) {\n\t\t\t\t$this->debugText .= \"Cleaning raw HTML failed. Ignoring: \" . $e->getMessage();\n\t\t\t}\n\t\t}\n\n\t\tif (trim($html) === '') $html = '<html></html>';\n\n\t\t/**\n\t\t * Use tidy (if it exists).\n\t\t * This fixes problems with some sites which would otherwise trouble DOMDocument's HTML parsing.\n\t\t * Although sometimes it makes matters worse, which is why there is an option to disable it.\n\t\t *\n\t\t **/\n\t\tif ($use_tidy && function_exists('tidy_parse_string')) {\n\t\t\t$this->debugText .= 'Tidying document'.\"\\n\";\n\t\t\t$tidy = tidy_parse_string($html, $this->tidy_config, 'UTF8');\n\t\t\tif (tidy_clean_repair($tidy)) {\n\t\t\t\t$original_html = $html;\n\t\t\t\t$this->tidied = true;\n\t\t\t\t$html = $tidy->value;\n\t\t\t\t$html = preg_replace('/<html[^>]+>/i', '<html>', $html);\n\t\t\t\t$html = preg_replace('/[\\r\\n]+/is', \"\\n\", $html);\n\t\t\t}\n\t\t\tunset($tidy);\n\t\t}\n\n\t\t$html = mb_convert_encoding($html, 'HTML-ENTITIES', \"UTF-8\");\n\n\t\tif ($parser=='html5lib' && ($this->dom = HTML5_Parser::parse($html))) {\n\t\t\t// all good\n\t\t} else {\n\t\t\tlibxml_use_internal_errors(true);\n\t\t\t$this->dom = new DOMDocument();\n\t\t\t$this->dom->preserveWhiteSpace = false;\n\t\t\t@$this->dom->loadHTML($html, LIBXML_NOBLANKS | LIBXML_COMPACT | LIBXML_NOERROR);\n\t\t}\n\t\t$this->dom->registerNodeClass('DOMElement', 'JSLikeHTMLElement');\n\t}\n\n\t/**\n\t* Get article title element\n\t* @return DOMElement\n\t*/\n\tpublic function getTitle() {\n\t\treturn $this->articleTitle;\n\t}\n\n\t/**\n\t* Get article content element\n\t* @return DOMElement\n\t*/\n\tpublic function getContent() {\n\t\treturn $this->articleContent;\n\t}\n\n\t/**\n\t* Embed images as data-URI.\n\t**/\n\tpublic function preserveImages() {\n\t\tif ($this->success && $this->articleContent) {\n\t\t\t$this->imageCache->cacheFromDocument($this->articleContent);\n\t\t}\n\t}\n\n\t/**\n\t* Add pre filter for raw input HTML processing\n\t* @param string RegExp for replace\n\t* @param string (optional) Replacer\n\t*/\n\tpublic function addPreFilter($filter, $replacer='') {\n\t\t$this->pre_filters[$filter] = $replacer;\n\t}\n\n\t/**\n\t* Add post filter for raw output HTML processing\n\t* @param string RegExp for replace\n\t* @param string (optional) Replacer\n\t*/\n\tpublic function addPostFilter($filter, $replacer='') {\n\t\t$this->post_filters[$filter] = $replacer;\n\t}\n\n\t/**\n\t* Runs readability.\n\t*\n\t* Workflow:\n\t*  1. Prep the document by removing script tags, css, etc.\n\t*  2. Build readability's DOM tree.\n\t*  3. Grab the article content from the current dom tree.\n\t*  4. Replace the current DOM tree with the new one.\n\t*  5. Read peacefully.\n\t*\n\t* @return boolean true if we found content, false otherwise\n\t**/\n\tpublic function init() {\n\t\tif (!isset($this->dom->documentElement)) return false;\n\t\t$this->removeScripts($this->dom);\n\n\t\t// Assume successful outcome\n\t\t$this->success = true;\n\n\t\t$bodyElems = $this->dom->getElementsByTagName('body');\n\n\t\t// WTF multiple body nodes?\n\t\tif ($this->bodyCache == null) {\n\t\t\t$this->bodyCache = '';\n\t\t\tforeach ($bodyElems as $bodyNode)\n\t\t\t\t$this->bodyCache += $bodyNode->innerHTML;\n\t\t}\n\n\t\tif ($bodyElems->length > 0 && $this->body == null) {\n\t\t\t$this->body = $bodyElems->item(0);\n\t\t}\n\n\t\t$this->prepDocument();\n\n\t\t// Build readability's DOM tree.\n\t\t$overlay = $this->dom->createElement('div');\n\t\t$innerDiv = $this->dom->createElement('div');\n\t\t$articleTitle   = $this->getArticleTitle();\n\t\t$articleContent = $this->grabArticle();\n\n\t\tif (!$articleContent) {\n\t\t\t$this->success = false;\n\t\t\t$articleContent = $this->dom->createElement('div');\n\t\t\t$articleContent->setAttribute('id', 'readability-content');\n\t\t\t$articleContent->innerHTML = '<p>Sorry, Readability was unable to parse this page for content.</p>';\n\t\t}\n\n\t\t$overlay->setAttribute('id', 'readOverlay');\n\t\t$innerDiv->setAttribute('id', 'readInner');\n\n\t\t// Glue the structure of our document together.\n\t\t$innerDiv->appendChild($articleTitle);\n\t\t$innerDiv->appendChild($articleContent);\n\t\t$overlay->appendChild($innerDiv);\n\n\t\t// Clear the old HTML, insert the new content.\n\t\t$this->body->innerHTML = '';\n\t\t$this->body->appendChild($overlay);\n\t\t$this->body->removeAttribute('style');\n\n\t\t$this->postProcessContent($articleContent);\n\n\t\t// Set title and content instance variables.\n\t\t$this->articleTitle = $articleTitle;\n\t\t$this->articleContent = $articleContent;\n\n\t\t$this->dump_dbg();\n\n\t\treturn $this->success;\n\t}\n\n\t/**\n\t* Debug\n\t*/\n\tprotected function dbg($msg) {//, $error=false) {\n\t\tif ($this->debug) $this->debugText .= $msg.\"\\n\";\n\t\t//echo '* ',, \"\\n\";\n\t}\n\n\t/**\n\t* Dump debug info\n\t*/\n\tprotected function dump_dbg() {\n\t\tif ($this->debug) {\n\t\t\tif ($this->debug) openlog(\"Readability PHP \", LOG_PID | LOG_PERROR, 0);\n\t\t\tsyslog(6, $this->debugText); // 1 - error 6 - info\n\t\t}\n\t}\n\n\t/**\n\t* Run any post-process modifications to article content as necessary.\n\t*\n\t* @param DOMElement\n\t* @return void\n\t*/\n\tpublic function postProcessContent($articleContent) {\n\t\tif ($this->convertLinksToFootnotes && !preg_match('/\\bwiki/', @$this->url)) {\n\t\t\t$this->addFootnotes($articleContent);\n\t\t}\n\t}\n\n\t/**\n\t* Get the article title as an H1.\n\t*\n\t* @return DOMElement\n\t*/\n\tprotected function getArticleTitle() {\n\t\t$curTitle = '';\n\t\t$origTitle = '';\n\n\t\ttry {\n\t\t\t$curTitle = $origTitle = $this->getInnerText($this->dom->getElementsByTagName('title')->item(0));\n\t\t} catch(Exception $e) {}\n\n\t\tif (preg_match('/ [\\|\\-] /', $curTitle)) {\n\t\t\t$curTitle = preg_replace('/(.*)[\\|\\-] .*/i', '$1', $origTitle);\n\n\t\t\tif (count(explode(' ', $curTitle)) < 3) {\n\t\t\t\t$curTitle = preg_replace('/[^\\|\\-]*[\\|\\-](.*)/i', '$1', $origTitle);\n\t\t\t}\n\t\t}\n\t\telse if (strpos($curTitle, ': ') !== false) {\n\t\t\t$curTitle = preg_replace('/.*:(.*)/i', '$1', $origTitle);\n\n\t\t\tif (count(explode(' ', $curTitle)) < 3) {\n\t\t\t\t$curTitle = preg_replace('/[^:]*[:](.*)/i','$1', $origTitle);\n\t\t\t}\n\t\t}\n\t\telse if(mb_strlen($curTitle) > 150 || mb_strlen($curTitle) < 15) {\n\t\t\t$hOnes = $this->dom->getElementsByTagName('h1');\n\t\t\tif($hOnes->length == 1) {\n\t\t\t\t$curTitle = $this->getInnerText($hOnes->item(0));\n\t\t\t}\n\t\t}\n\n\t\t$curTitle = trim($curTitle);\n\n\t\tif (count(explode(' ', $curTitle)) <= 4) {\n\t\t\t$curTitle = $origTitle;\n\t\t}\n\n\t\t$articleTitle = $this->dom->createElement('h1');\n\t\t$articleTitle->innerHTML = $curTitle;\n\n\t\treturn $articleTitle;\n\t}\n\n\t/**\n\t* Prepare the HTML document for readability to scrape it.\n\t* This includes things like stripping javascript, CSS, and handling terrible markup.\n\t*\n\t* @return void\n\t**/\n\tprotected function prepDocument() {\n\t\t/**\n\t\t* In some cases a body element can't be found (if the HTML is totally hosed for example)\n\t\t* so we create a new body node and append it to the document.\n\t\t*/\n\t\tif ($this->body == null) {\n\t\t\t$this->body = $this->dom->createElement('body');\n\t\t\t$this->dom->documentElement->appendChild($this->body);\n\t\t}\n\t\t$this->body->setAttribute('id', 'readabilityBody');\n\n\t\t// Remove all style tags in head.\n\t\t$styleTags = $this->dom->getElementsByTagName('style');\n\t\tfor ($i = $styleTags->length-1; $i >= 0; $i--) {\n\t\t\t$styleTags->item($i)->parentNode->removeChild($styleTags->item($i));\n\t\t}\n\t\t$linkTags = $this->dom->getElementsByTagName('link');\n\t\tfor ($i = $linkTags->length-1; $i >= 0; $i--) {\n\t\t\t$linkTags->item($i)->parentNode->removeChild($linkTags->item($i));\n\t\t}\n\t}\n\n\t/**\n\t* For easier reading, convert this document to have footnotes at the bottom rather than inline links.\n\t* @see http://www.roughtype.com/archives/2010/05/experiments_in.php\n\t*\n\t* @return void\n\t**/\n\tpublic function addFootnotes($articleContent) {\n\t\t$footnotesWrapper = $this->dom->createElement('footer');\n\t\t$footnotesWrapper->setAttribute('id', 'readability-footnotes');\n\t\t$footnotesWrapper->innerHTML = '<h3>References</h3>';\n\n\t\t$articleFootnotes = $this->dom->createElement('ol');\n\t\t$articleFootnotes->setAttribute('id', 'readability-footnotes-list');\n\t\t$footnotesWrapper->appendChild($articleFootnotes);\n\n\t\t$articleLinks = $articleContent->getElementsByTagName('a');\n\n\t\t$linkCount = 0;\n\t\tfor ($i = 0; $i < $articleLinks->length; $i++) {\n\t\t\t$articleLink  = $articleLinks->item($i);\n\t\t\t$footnoteLink = $articleLink->cloneNode(true);\n\t\t\t$refLink = $this->dom->createElement('a');\n\t\t\t$footnote = $this->dom->createElement('li');\n\t\t\t$linkDomain   = @parse_url($footnoteLink->getAttribute('href'), PHP_URL_HOST);\n\t\t\tif (!$linkDomain && isset($this->url)) $linkDomain = @parse_url($this->url, PHP_URL_HOST);\n\t\t\t$linkText = $this->getInnerText($articleLink);\n\n\t\t\tif ((strpos($articleLink->getAttribute('class'), 'readability-DoNotFootnote') !== false) || preg_match($this->regexps['skipFootnoteLink'], $linkText)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$linkCount++;\n\n\t\t\t// Add a superscript reference after the article link.\n\t\t\t$refLink->setAttribute('href', '#readabilityFootnoteLink-' . $linkCount);\n\t\t\t$refLink->innerHTML = '<small><sup>[' . $linkCount . ']</sup></small>';\n\t\t\t$refLink->setAttribute('class', 'readability-DoNotFootnote');\n\t\t\t$refLink->setAttribute('style', 'color: inherit;');\n\n\t\t\tif ($articleLink->parentNode->lastChild->isSameNode($articleLink)) {\n\t\t\t\t$articleLink->parentNode->appendChild($refLink);\n\t\t\t} else {\n\t\t\t\t$articleLink->parentNode->insertBefore($refLink, $articleLink->nextSibling);\n\t\t\t}\n\n\t\t\t$articleLink->setAttribute('style', 'color: inherit; text-decoration: none;');\n\t\t\t$articleLink->setAttribute('name', 'readabilityLink-' . $linkCount);\n\n\t\t\t$footnote->innerHTML = '<small><sup><a href=\"#readabilityLink-' . $linkCount . '\" title=\"Jump to Link in Article\">^</a></sup></small> ';\n\n\t\t\t$footnoteLink->innerHTML = ($footnoteLink->getAttribute('title') != '' ? $footnoteLink->getAttribute('title') : $linkText);\n\t\t\t$footnoteLink->setAttribute('name', 'readabilityFootnoteLink-' . $linkCount);\n\n\t\t\t$footnote->appendChild($footnoteLink);\n\t\t\tif ($linkDomain) $footnote->innerHTML = $footnote->innerHTML . '<small> (' . $linkDomain . ')</small>';\n\n\t\t\t$articleFootnotes->appendChild($footnote);\n\t\t}\n\n\t\tif ($linkCount > 0) {\n\t\t\t$articleContent->appendChild($footnotesWrapper);\n\t\t}\n\t}\n\n\t/**\n\t* Prepare the article node for display. Clean out any inline styles,\n\t* iframes, forms, strip extraneous <p> tags, etc.\n\t*\n\t* @param DOMElement\n\t* @return void\n\t*/\n\tfunction prepArticle($articleContent) {\n\n\t\tif ($this->lightClean) {\n\t\t\t$this->dbg('Light clean enabled.');\n\t\t} else {\n\t\t\t$this->dbg('Standard clean enabled.');\n\t\t}\n\n\t\t$this->cleanStyles($articleContent);\n\t\t$this->killBreaks($articleContent);\n\n\t\t$xpath = new DOMXPath($articleContent->ownerDocument);\n\t\tif ($this->revertForcedParagraphElements) {\n\t\t\t/*\n\t\t\t * Reverts P elements with class 'readability-styled' to text nodes:\n\t\t\t * which is what they were before.\n\t\t\t */\n\t\t\t$elems = $xpath->query('.//p[@data-readability-styled]', $articleContent);\n\t\t\tfor ($i = $elems->length-1; $i >= 0; $i--) {\n\t\t\t\t$e = $elems->item($i);\n\t\t\t\t$e->parentNode->replaceChild($articleContent->ownerDocument->createTextNode($e->textContent), $e);\n\t\t\t}\n\t\t}\n\n\t\t// Remove service data-candidate attribute.\n\t\t$elems = $xpath->query('.//*[@data-candidate]', $articleContent);\n\t\tfor ($i = $elems->length-1; $i >= 0; $i--) {\n\t\t\t$elems->item($i)->removeAttribute('data-candidate');\n\t\t}\n\n\t\t// Remove unrelated links and other unneded stuff.\n\t\t// (not(*) and not(text()[normalize-space()])) or // What's wrong here?\n\t\t$elems = $xpath->query('.//a[@rel=\"nofollow\"]', $articleContent);\n\t\tfor ($i = $elems->length-1; $i >= 0; $i--) {\n\t\t\t$elems->item($i)->parentNode->removeChild($elems->item($i));\n\t\t}\n\n\t\t// Clean out junk from the article content.\n\t\t$this->clean($articleContent, 'input');\n\t\t$this->clean($articleContent, 'button');\n\t\t$this->clean($articleContent, 'nav');\n\t\t$this->clean($articleContent, 'object');\n\t\t$this->clean($articleContent, 'iframe');\n\t\t$this->clean($articleContent, 'canvas');\n\t\t$this->clean($articleContent, 'h1');\n\n\t\t/**\n\t\t * If there is only one h2, they are probably using it as a main header, so remove it since we\n\t\t *  already have a header.\n\t\t ***/\n\t\t$h2s = $articleContent->getElementsByTagName('h2');\n\t\tif ($h2s->length == 1 && mb_strlen($this->getInnerText($h2s->item(0), true, true)) < 100) {\n\t\t\t$this->clean($articleContent, 'h2');\n\t\t}\n\n\t\t$this->cleanHeaders($articleContent);\n\n\t\t// Do these last as the previous stuff may have removed junk that will affect these.\n\t\t$this->cleanConditionally($articleContent, 'form');\n\t\t$this->cleanConditionally($articleContent, 'table');\n\t\t$this->cleanConditionally($articleContent, 'ul');\n\t\t//if (!$this->lightClean)\n\t\t$this->cleanConditionally($articleContent, 'div');\n\n\t\t// Remove extra paragraphs.\n\t\t$articleParagraphs = $articleContent->getElementsByTagName('p');\n\t\tfor ($i = $articleParagraphs->length-1; $i >= 0; $i--) {\n\t\t\t$imgCount = $articleParagraphs->item($i)->getElementsByTagName('img')->length;\n\t\t\t$embedCount = $articleParagraphs->item($i)->getElementsByTagName('embed')->length;\n\t\t\t$objectCount = $articleParagraphs->item($i)->getElementsByTagName('object')->length;\n\t\t\t$videoCount = $articleParagraphs->item($i)->getElementsByTagName('video')->length;\n\t\t\t$audioCount = $articleParagraphs->item($i)->getElementsByTagName('audio')->length;\n\n\t\t\tif ($imgCount === 0 && $embedCount === 0 && $objectCount === 0 && $videoCount === 0 && $audioCount === 0 && mb_strlen(preg_replace('/\\s+/is', '', $this->getInnerText($articleParagraphs->item($i), false, false))) === 0) {\n\t\t\t\t$articleParagraphs->item($i)->parentNode->removeChild($articleParagraphs->item($i));\n\t\t\t}\n\t\t}\n\n\t\tif (!$this->flagIsActive(self::FLAG_DISABLE_POSTFILTER)) {\n\t\t\ttry {\n\t\t\t\tforeach ($this->post_filters as $search => $replace) {\n\t\t\t\t\t$articleContent->innerHTML = preg_replace($search, $replace, $articleContent->innerHTML);\n\t\t\t\t}\n\t\t\t\tunset($search, $replace);\n\t\t\t} catch (Exception $e) {\n\t\t\t\t$this->dbg(\"Cleaning output HTML failed. Ignoring: \" . $e->getMessage());\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t* Initialize a node with the readability object. Also checks the\n\t* className/id for special names to add to its score.\n\t*\n\t* @param Element\n\t* @return void\n\t**/\n\tprotected function initializeNode($node) {\n\t\tif (!isset($node->tagName)) return;\n\n\t\t$readability = $this->dom->createAttribute('readability');\n\t\t$readability->value = 0; // this is our contentScore\n\t\t$node->setAttributeNode($readability);\n\n\t\tswitch (strtoupper($node->tagName)) { // using strtoupper just in case\n\t\t\tcase 'ARTICLE':\n\t\t\t\t$readability->value += 15;\n\t\t\tcase 'DIV':\n\t\t\t\t$readability->value += 5;\n\t\t\t\tbreak;\n\t\t\tcase 'PRE':\n\t\t\tcase 'CODE':\n\t\t\tcase 'TD':\n\t\t\tcase 'BLOCKQUOTE':\n\t\t\tcase 'FIGURE':\n\t\t\t\t$readability->value += 3;\n\t\t\t\tbreak;\n/*\t\t\tcase 'SECTION': // often misused\n\t\t\t\t$readability->value += 2;\n\t\t\t\tbreak;\n*/\n\t\t\tcase 'OL':\n\t\t\tcase 'UL':\n\t\t\tcase 'DL':\n\t\t\tcase 'DD':\n\t\t\tcase 'DT':\n\t\t\tcase 'LI':\n\t\t\t\t$readability->value -= 2 * round($this->getLinkDensity($node), 0, PHP_ROUND_HALF_UP);\n\t\t\t\tbreak;\n\t\t\tcase 'ASIDE':\n\t\t\tcase 'FOOTER':\n\t\t\tcase 'HEADER':\n\t\t\tcase 'ADDRESS':\n\t\t\tcase 'FORM':\n\t\t\tcase 'BUTTON':\n\t\t\tcase 'TEXTAREA':\n\t\t\tcase 'INPUT':\n\t\t\tcase 'NAV':\n\t\t\t\t$readability->value -= 3;\n\t\t\t\tbreak;\n\t\t\tcase 'H1':\n\t\t\tcase 'H2':\n\t\t\tcase 'H3':\n\t\t\tcase 'H4':\n\t\t\tcase 'H5':\n\t\t\tcase 'H6':\n\t\t\tcase 'TH':\n\t\t\tcase 'HGROUP':\n\t\t\t\t$readability->value -= 5;\n\t\t\t\tbreak;\n\t\t}\n\t\t$readability->value += $this->getWeight($node);\n\t}\n\n\t/***\n\t* grabArticle - Using a variety of metrics (content score, classname, element types), find the content that is\n\t* most likely to be the stuff a user wants to read. Then return it wrapped up in a div.\n\t*\n\t* @return DOMElement\n\t**/\n\tprotected function grabArticle($page=null) {\n\t\tif (!$page) $page = $this->dom;\n\t\t$xpath = null;\n\t\t$nodesToScore = array();\n\n\t\tif ($page instanceof DOMDocument && isset($page->documentElement)) {\n\t\t\t$xpath = new DOMXPath($page);\n\t\t}\n\n\t\t$allElements = $page->getElementsByTagName('*');\n\t\tfor ($nodeIndex = 0; ($node = $allElements->item($nodeIndex)); $nodeIndex++) {\n\t\t\t$tagName = $node->tagName;\n\n\t\t\t// Some well known site uses sections as paragraphs.\n\t\t\tif (strcasecmp($tagName, 'p') === 0 || strcasecmp($tagName, 'td') === 0 || strcasecmp($tagName, 'section') === 0) {\n\t\t\t\t$nodesToScore[] = $node;\n\t\t\t}\n\n\t\t\t// Turn divs into P tags where they have been used inappropriately\n\t\t\t//  (as in, where they contain no other block level elements).\n\t\t\tif (strcasecmp($tagName, 'div') === 0 || strcasecmp($tagName, 'article') === 0 || strcasecmp($tagName, 'section') === 0) {\n\t\t\t\tif (!preg_match($this->regexps['divToPElements'], $node->innerHTML)) {\n\t\t\t\t\t//$this->dbg('Altering '.$node->getNodePath().' to p');\n\t\t\t\t\t$newNode = $this->dom->createElement('p');\n\t\t\t\t\ttry {\n\t\t\t\t\t\t$newNode->innerHTML = $node->innerHTML;\n\t\t\t\t\t\t// It's easier to debug using original attributes.\n\t\t\t\t\t\t//$newNode->setAttribute('class', $node->getAttribute('class'));\n\t\t\t\t\t\t//$newNode->setAttribute('id', $node->getAttribute('id'));\n\t\t\t\t\t\t$node = $node->parentNode->replaceChild($newNode, $node);\n\t\t\t\t\t\t$nodeIndex--;\n\t\t\t\t\t\t$nodesToScore[] = $newNode;\n\t\t\t\t\t} catch (Exception $e) {\n\t\t\t\t\t\t$this->dbg('Could not alter div/article to p, reverting back to div: ' . $e->getMessage());\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Will change these P elements back to text nodes after processing.\n\t\t\t\t\tfor ($i = 0, $il = $node->childNodes->length; $i < $il; $i++) {\n\t\t\t\t\t\t$childNode = $node->childNodes->item($i);\n\t\t\t\t\t\tif (is_object($childNode) && get_class($childNode) === 'DOMProcessingInstruction') { //executable tags (<?php or <?xml) warning\n\t\t\t\t\t\t\t$childNode->parentNode->removeChild($childNode);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ($childNode->nodeType == 3) { // XML_TEXT_NODE\n\t\t\t\t\t\t\t//$this->dbg('replacing text node with a P tag with the same content.');\n\t\t\t\t\t\t\t$p = $this->dom->createElement('p');\n\t\t\t\t\t\t\t$p->innerHTML = $childNode->nodeValue;\n\n\t\t\t\t\t\t\t$p->setAttribute('data-readability-styled', 'true');\n\t\t\t\t\t\t\t$childNode->parentNode->replaceChild($p, $childNode);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t* Loop through all paragraphs, and assign a score to them based on how content-y they look.\n\t\t* Then add their score to their parent node.\n\t\t*\n\t\t* A score is determined by things like number of commas, class names, etc.\n\t\t* Maybe eventually link density.\n\t\t**/\n\t\tfor ($pt=0, $scored = count($nodesToScore); $pt < $scored; $pt++) {\n\t\t\t$parentNode = $nodesToScore[$pt]->parentNode;\n\t\t\t// No parent node? Move on...\n\t\t\tif (!$parentNode) continue;\n\n\t\t\t$grandParentNode = ($parentNode->parentNode instanceof DOMElement) ? $parentNode->parentNode : null;\n\t\t\t$innerText = $this->getInnerText($nodesToScore[$pt]);\n\n\t\t\t// If this paragraph is less than MIN_PARAGRAPH_LENGTH (default:20) characters, don't even count it.\n\t\t\tif(mb_strlen($innerText) < self::MIN_PARAGRAPH_LENGTH) continue;\n\n\t\t\t// Initialize readability data for the parent.\n\t\t\tif (!$parentNode->hasAttribute('readability')) {\n\t\t\t\t$this->initializeNode($parentNode);\n\t\t\t\t$parentNode->setAttribute('data-candidate','true');\n\t\t\t}\n\n\t\t\t// Initialize readability data for the grandparent.\n\t\t\tif ($grandParentNode && !$grandParentNode->hasAttribute('readability') && isset($grandParentNode->tagName)) {\n\t\t\t\t$this->initializeNode($grandParentNode);\n\t\t\t\t$grandParentNode->setAttribute('data-candidate','true');\n\t\t\t}\n\n\t\t\t// Add a point for the paragraph itself as a base.\n\t\t\t$contentScore = 1;\n\n\t\t\t// Add points for any commas within this paragraph.\n\t\t\t$contentScore += $this->getCommaCount($innerText);\n\n\t\t\t// For every SCORE_CHARS_IN_PARAGRAPH (default:100) characters in this paragraph, add another point. Up to 3 points.\n\t\t\t$contentScore += min(floor(mb_strlen($innerText) / self::SCORE_CHARS_IN_PARAGRAPH), 3);\n\n\t\t\t// For every SCORE_WORDS_IN_PARAGRAPH (default:20) words in this paragraph, add another point. Up to 3 points.\n\t\t\t$contentScore += min(floor($this->getWordCount($innerText)/ self::SCORE_WORDS_IN_PARAGRAPH), 3);\n\n\t\t\t/* TEST: For every positive/negative parent tag, add/substract half point. Up to 3 points. *\\/\n\t\t\t$up = $nodesToScore[$pt];\n\t\t\t$score = 0;\n\t\t\twhile ($up->parentNode instanceof DOMElement) {\n\t\t\t\t$up = $up->parentNode;\n\t\t\t\tif (preg_match($this->regexps['positive'], $up->getAttribute('class') . ' ' . $up->getAttribute('id'))) {\n\t\t\t\t\t$score += 0.5;\n\t\t\t\t} else if (preg_match($this->regexps['negative'], $up->getAttribute('class') . ' ' . $up->getAttribute('id'))) {\n\t\t\t\t\t$score -= 0.5;\n\t\t\t\t}\n\t\t\t}\n\t\t\t$score = floor($score);\n\t\t\t$contentScore += max(min($score, 3), -3);/**/\n\n\t\t\t// Add the score to the parent. The grandparent gets half.\n\t\t\t$parentNode->getAttributeNode('readability')->value += $contentScore;\n\t\t\tif ($grandParentNode) {\n\t\t\t\t$grandParentNode->getAttributeNode('readability')->value += $contentScore / self::GRANDPARENT_SCORE_DIVISOR;\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t  * Node prepping: trash nodes that look cruddy (like ones with the class name \"comment\", etc).\n\t\t  * This is faster to do before scoring but safer after.\n\t\t  */\n\t\tif ($this->flagIsActive(self::FLAG_STRIP_UNLIKELYS) && $xpath) {\n\t\t\t$candidates = $xpath->query('.//*[(self::footer and count(//footer)<2) or (self::aside and count(//aside)<2)]', $page->documentElement);\n\t\t\tfor ($node = null, $c = $candidates->length-1; $c >= 0; $c--) {\n\t\t\t\t$node = $candidates->item($c);\n\t\t\t\t// node should be readable but not inside of an article otherwise it's probably non-readable block\n\t\t\t\tif ($node->hasAttribute('readability') && (int)$node->getAttributeNode('readability')->value < 40 && ($node->parentNode ? strcasecmp($node->parentNode->tagName, 'article') !== 0 : true)) {\n\t\t\t\t\t$this->dbg('Removing unlikely candidate '.$node->getNodePath().' by \"'.$node->tagName.'\" with readability '.($node->hasAttribute('readability') ? (int)$node->getAttributeNode('readability')->value : 0));\n\t\t\t\t\t$node->parentNode->removeChild($node);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$candidates = $xpath->query('.//*[not(self::body) and (@class or @id or @style) and ((number(@readability) < 40) or not(@readability))]', $page->documentElement);\n\t\t\tfor ($node = null, $c = $candidates->length-1; $c >= 0; $c--) {\n\t\t\t\t$node = $candidates->item($c);\n\t\t\t\t$tagName = $node->tagName;\n\t\t\t\t/* Remove unlikely candidates */\n\t\t\t\t$unlikelyMatchString = $node->getAttribute('class').\" \".$node->getAttribute('id').\" \".$node->getAttribute('style');\n\t\t\t\t//$this->dbg('Processing '.$node->getNodePath().' by \"'. $unlikelyMatchString.'\" with readability '.($node->hasAttribute('readability') ? (int)$node->getAttributeNode('readability')->value : 0));\n\n\t\t\t\tif (mb_strlen($unlikelyMatchString) > 3 && // don't process \"empty\" strings\n\t\t\t\t\tpreg_match($this->regexps['unlikelyCandidates'], $unlikelyMatchString) &&\n\t\t\t\t\t!preg_match($this->regexps['okMaybeItsACandidate'], $unlikelyMatchString)\n\t\t\t\t) {\n\t\t\t\t\t$this->dbg('Removing unlikely candidate '.$node->getNodePath().' by \"'. $unlikelyMatchString.'\" with readability '. ($node->hasAttribute('readability') ? (int)$node->getAttributeNode('readability')->value : 0));\n\t\t\t\t\t$node->parentNode->removeChild($node);\n\t\t\t\t\t$nodeIndex--;\n\t\t\t\t}\n\t\t\t}\n\t\t\tunset($candidates);\n\t\t}\n\n\t\t/**\n\t\t* After we've calculated scores, loop through all of the possible candidate nodes we found\n\t\t* and find the one with the highest score.\n\t\t**/\n\t\t$topCandidate = null;\n\t\tif ($xpath) {\n\t\t\t// Using array of DOMElements after deletion is a path to DOOMElement.\n\t\t\t$candidates = $xpath->query('.//*[@data-candidate]', $page->documentElement);\n\t\t\tfor ($c = $candidates->length-1; $c >= 0; $c--) {\n\n\t\t\t\t// Scale the final candidates score based on link density. Good content should have a\n\t\t\t\t// relatively small link density (5% or less) and be mostly unaffected by this operation.\n\t\t\t\t// If not for this we would have used XPath to find maximum @readability.\n\n\t\t\t\t$readability = $candidates->item($c)->getAttributeNode('readability');\n\t\t\t\t$readability->value = round($readability->value * (1 - $this->getLinkDensity($candidates->item($c))), 0, PHP_ROUND_HALF_UP);\n\n\t\t\t\tif (!$topCandidate || $readability->value > (int)$topCandidate->getAttribute('readability')) {\n\t\t\t\t\t$this->dbg('Candidate: '.$candidates->item($c)->getNodePath().' ('.$candidates->item($c)->getAttribute('class').':'.$candidates->item($c)->getAttribute('id').') with score '.$readability->value);\n\t\t\t\t\t$topCandidate = $candidates->item($c);\n\t\t\t\t}\n\t\t\t}\n\t\t\tunset($candidates);\n\t\t}\n\n\t\t/**\n\t\t* If we still have no top candidate, just use the body as a last resort.\n\t\t* We also have to copy the body node so it is something we can modify.\n\t\t**/\n\t\tif ($topCandidate === null || strcasecmp($topCandidate->tagName, 'body') === 0) {\n\t\t\t$topCandidate = $this->dom->createElement('div');\n\t\t\tif ($page instanceof DOMDocument) {\n\t\t\t\tif (!isset($page->documentElement)) {\n\t\t\t\t\t// we don't have a body either? what a mess! :)\n\t\t\t\t\t$this->dbg('The page has no body!');\n\t\t\t\t} else {\n\t\t\t\t\t$this->dbg('Setting body to a raw HTML of original page!');\n\t\t\t\t\t$topCandidate->innerHTML = $page->documentElement->innerHTML;\n\t\t\t\t\t$page->documentElement->innerHTML = '';\n\t\t\t\t\t$page->documentElement->appendChild($topCandidate);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$topCandidate->innerHTML = $page->innerHTML;\n\t\t\t\t$page->innerHTML = '';\n\t\t\t\t$page->appendChild($topCandidate);\n\t\t\t}\n\t\t\t$this->initializeNode($topCandidate);\n\t\t}\n\n\t\t// Set table as the main node if resulted data is table element.\n\t\t$tagName = $topCandidate->tagName;\n\t\tif (strcasecmp($tagName, 'td') === 0 || strcasecmp($tagName, 'tr') === 0) {\n\t\t\t$up = $topCandidate;\n\t\t\twhile ($up->parentNode instanceof DOMElement) {\n\t\t\t\t$up = $up->parentNode;\n\t\t\t\tif (strcasecmp($up->tagName, 'table') === 0) {\n\t\t\t\t\t$topCandidate = $up;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$this->dbg('Top candidate: '.$topCandidate->getNodePath());\n\n\t\t/**\n\t\t* Now that we have the top candidate, look through its siblings for content that might also be related.\n\t\t* Things like preambles, content split by ads that we removed, etc.\n\t\t**/\n\t\t$articleContent = $this->dom->createElement('div');\n\t\t$articleContent->setAttribute('id', 'readability-content');\n\t\t$siblingScoreThreshold = max(10, ((int)$topCandidate->getAttribute('readability')) * 0.2);\n\t\t$siblingNodes = $topCandidate->parentNode->childNodes;\n\t\tif (!isset($siblingNodes)) {\n\t\t\t$siblingNodes = new stdClass;\n\t\t\t$siblingNodes->length = 0;\n\t\t}\n\n\t\tfor ($s = 0, $sl = $siblingNodes->length; $s < $sl; $s++) {\n\t\t\t$siblingNode = $siblingNodes->item($s);\n\t\t\t$siblingNodeName = $siblingNode->nodeName;\n\t\t\t$append = false;\n\n\t\t\t$this->dbg('Looking at sibling node: ' . $siblingNode->getNodePath() . (($siblingNode->nodeType === XML_ELEMENT_NODE && $siblingNode->hasAttribute('readability')) ? (' with score ' . $siblingNode->getAttribute('readability')) : ''));\n\n\t\t\t//$this->dbg('Sibling has score ' . ($siblingNode->readability ? siblingNode.readability.contentScore : 'Unknown'));\n\t\t\tif ($siblingNode->isSameNode($topCandidate)) {\n\t\t\t\t$append = true;\n\t\t\t}\n\n\t\t\t$contentBonus = 0;\n\t\t\t// Give a bonus if sibling nodes and top candidates have the same classname.\n\t\t\tif ($siblingNode->nodeType === XML_ELEMENT_NODE && $siblingNode->getAttribute('class') == $topCandidate->getAttribute('class') && $topCandidate->getAttribute('class') != '') {\n\t\t\t\t$contentBonus += ((int)$topCandidate->getAttribute('readability')) * 0.2;\n\t\t\t}\n\n\t\t\tif ($siblingNode->nodeType === XML_ELEMENT_NODE && $siblingNode->hasAttribute('readability') && (((int)$siblingNode->getAttribute('readability')) + $contentBonus) >= $siblingScoreThreshold) {\n\t\t\t\t$append = true;\n\t\t\t}\n\n\t\t\tif (strcasecmp($siblingNodeName, 'p') === 0) {\n\t\t\t\t$linkDensity = $this->getLinkDensity($siblingNode);\n\t\t\t\t$nodeContent = $this->getInnerText($siblingNode, true, true);\n\t\t\t\t$nodeLength  = mb_strlen($nodeContent);\n\n\t\t\t\tif ($nodeLength > self::MIN_NODE_LENGTH && $linkDensity < self::MAX_LINK_DENSITY) {\n\t\t\t\t\t$append = true;\n\t\t\t\t}\n\t\t\t\telse if ($nodeLength < self::MIN_NODE_LENGTH && $linkDensity === 0 && preg_match('/\\.( |$)/', $nodeContent)) {\n\t\t\t\t\t$append = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ($append) {\n\t\t\t\t$this->dbg('Appending node: ' . $siblingNode->getNodePath());\n\n\t\t\t\t$nodeToAppend = null;\n\t\t\t\tif (strcasecmp($siblingNodeName, 'div') !== 0 && strcasecmp($siblingNodeName, 'p') !== 0) {\n\t\t\t\t\t/* We have a node that isn't a common block level element, like a form or td tag. Turn it into a div so it doesn't get filtered out later by accident. */\n\n\t\t\t\t\t$this->dbg('Altering siblingNode ' . $siblingNodeName . ' to div.');\n\t\t\t\t\t$nodeToAppend = $this->dom->createElement('div');\n\t\t\t\t\ttry {\n\t\t\t\t\t\t$nodeToAppend->setAttribute('id', $siblingNode->getAttribute('id'));\n\t\t\t\t\t\t$nodeToAppend->setAttribute('alt', $siblingNodeName);\n\t\t\t\t\t\t$nodeToAppend->innerHTML = $siblingNode->innerHTML;\n\t\t\t\t\t} catch(Exception $e) {\n\t\t\t\t\t\t$this->dbg('Could not alter siblingNode ' . $siblingNodeName . ' to div, reverting to original.');\n\t\t\t\t\t\t$nodeToAppend = $siblingNode;\n\t\t\t\t\t\t$s--;\n\t\t\t\t\t\t$sl--;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$nodeToAppend = $siblingNode;\n\t\t\t\t\t$s--;\n\t\t\t\t\t$sl--;\n\t\t\t\t}\n\n\t\t\t\t// To ensure a node does not interfere with readability styles, remove its classnames & ids.\n\t\t\t\t// Now done via RegExp post_filter.\n\t\t\t\t//$nodeToAppend->removeAttribute('class');\n\t\t\t\t//$nodeToAppend->removeAttribute('id');\n\n\t\t\t\t// Append sibling and subtract from our list as appending removes a node.\n\t\t\t\t$articleContent->appendChild($nodeToAppend);\n\t\t\t}\n\t\t}\n\n\t\tunset($xpath);\n\n\t\t// So we have all of the content that we need. Now we clean it up for presentation.\n\t\t$this->prepArticle($articleContent);\n\n\t\t/**\n\t\t* Now that we've gone through the full algorithm, check to see if we got any meaningful content.\n\t\t* If we didn't, we may need to re-run grabArticle with different flags set. This gives us a higher\n\t\t* likelihood of finding the content, and the sieve approach gives us a higher likelihood of\n\t\t* finding the -right- content.\n\t\t**/\n\t\tif (mb_strlen($this->getInnerText($articleContent, false)) < self::MIN_ARTICLE_LENGTH) {\n\t\t\tif (!$this->body->hasChildNodes())\n\t\t\t\t$this->body = $this->dom->createElement('body');\n\t\t\t$this->body->innerHTML = $this->bodyCache;\n\n\t\t\tif ($this->flagIsActive(self::FLAG_STRIP_UNLIKELYS)) {\n\t\t\t\t$this->removeFlag(self::FLAG_STRIP_UNLIKELYS);\n\t\t\t\t$this->dbg(\"...content is shorter than \".self::MIN_ARTICLE_LENGTH.\" letters, trying not to strip unlikely content.\\n\");\n\t\t\t\treturn $this->grabArticle($this->body);\n\t\t\t}\n\t\t\telse if ($this->flagIsActive(self::FLAG_WEIGHT_ATTRIBUTES)) {\n\t\t\t\t$this->removeFlag(self::FLAG_WEIGHT_ATTRIBUTES);\n\t\t\t\t$this->dbg(\"...content is shorter than \".self::MIN_ARTICLE_LENGTH.\" letters, trying not to weight attributes.\\n\");\n\t\t\t\treturn $this->grabArticle($this->body);\n\t\t\t}\n\t\t\telse if ($this->flagIsActive(self::FLAG_CLEAN_CONDITIONALLY)) {\n\t\t\t\t$this->removeFlag(self::FLAG_CLEAN_CONDITIONALLY);\n\t\t\t\t$this->dbg(\"...content is shorter than \".self::MIN_ARTICLE_LENGTH.\" letters, trying not to clean at all.\\n\");\n\t\t\t\treturn $this->grabArticle($this->body);\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn $articleContent;\n\t}\n\n\t/**\n\t* Remove script tags from document\n\t*\n\t* @param DOMElement\n\t* @return void\n\t*/\n\tpublic function removeScripts($doc) {\n\t\t$scripts = $doc->getElementsByTagName('script');\n\t\tfor($i = $scripts->length-1; $i >= 0; $i--) {\n\t\t\t$scripts->item($i)->parentNode->removeChild($scripts->item($i));\n\t\t}\n\t}\n\n\t/**\n\t* Get the inner text of a node.\n\t* This also strips out any excess whitespace to be found.\n\t*\n\t* @param DOMElement $e\n\t* @param boolean $normalizeSpaces (default: true)\n\t* @param boolean $flattenLines (default: false)\n\t* @return string\n\t**/\n\tpublic function getInnerText($e, $normalizeSpaces=true, $flattenLines=false) {\n\t\tif (!isset($e->textContent) || $e->textContent === '') return '';\n\t\t$textContent = trim($e->textContent);\n\t\tif ($flattenLines) {\n\t\t\t$textContent = mb_ereg_replace('(?:[\\r\\n](?:\\s|&nbsp;)*)+', '', $textContent);\n\t\t} else if ($normalizeSpaces) {\n\t\t\t$textContent = mb_ereg_replace('\\s\\s+', ' ', $textContent);\n\t\t}\n\t\treturn $textContent;\n\t}\n\n\t/**\n\t* Remove the style attribute on every $e and under.\n\t*\n\t* @param DOMElement $e\n\t* @return void\n\t*/\n\tpublic function cleanStyles($e) {\n\t\tif (!is_object($e)) return;\n\t\t$elems = $e->getElementsByTagName('*');\n\t\tforeach ($elems as $elem) {\n\t\t\t$elem->removeAttribute('style');\n\t\t}\n\t}\n\n\t/**\n\t* Get comma number for a given text.\n\t*\n\t* @param string $text\n\t* @return number (integer)\n\t*/\n\tpublic function getCommaCount($text) {\n\t\treturn substr_count($text, ',');\n\t}\n\n\t/**\n\t* Get words number for a given text if words separated by a space.\n\t* Input string should be normalized.\n\t*\n\t* @param string $text\n\t* @return number (integer)\n\t*/\n\tpublic function getWordCount($text) {\n\t\treturn substr_count($text, ' ');\n\t}\n\n\t/**\n\t* Get the density of links as a percentage of the content\n\t* This is the amount of text that is inside a link divided by the total text in the node.\n\t* Can exclude external references to differentiate between simple text and menus/infoblocks.\n\t*\n\t* @param DOMElement $e\n\t* @param string $excludeExternal\n\t* @return number (float)\n\t*/\n\tpublic function getLinkDensity($e, $excludeExternal=false) {\n\t\t$links = $e->getElementsByTagName('a');\n\t\t$textLength = mb_strlen($this->getInnerText($e, true, true));\n\t\t$linkLength = 0;\n\t\tfor ($dRe = $this->domainRegExp, $i=0, $il=$links->length; $i < $il; $i++) {\n\t\t\tif ($excludeExternal && $dRe && !preg_match($dRe, $links->item($i)->getAttribute('href'))) continue;\n\t\t\t$linkLength += mb_strlen($this->getInnerText($links->item($i)));\n\t\t}\n\t\tif ($textLength > 0 && $linkLength > 0) {\n\t\t\treturn $linkLength / $textLength;\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\t/**\n\t* Get an element weight by attribute.\n\t* Uses regular expressions to tell if this element looks good or bad.\n\t*\n\t* @param DOMElement $element\n\t* @param string $attribute\n\t* @return number (Integer)\n\t*/\n\tprotected function weightAttribute($element, $attribute) {\n\t\tif (!$element->hasAttribute($attribute)) {\n\t\t\treturn 0;\n\t\t}\n\n\t\t$weight = 0;\n\t\t//$attribute_val = trim($element->getAttribute('class').\" \".$element->getAttribute('id'));\n\t\t$attribute_val = trim($element->getAttribute($attribute));\n\n\t\tif ($attribute_val != '') {\n\t\t\tif (preg_match($this->regexps['negative'], $attribute_val)) {\n\t\t\t\t$weight -= 25;\n\t\t\t}\n\t\t\tif (preg_match($this->regexps['positive'], $attribute_val)) {\n\t\t\t\t$weight += 25;\n\t\t\t}\n\t\t\tif (preg_match($this->regexps['unlikelyCandidates'], $attribute_val)) {\n\t\t\t\t$weight -= 5;\n\t\t\t}\n\t\t\tif (preg_match($this->regexps['okMaybeItsACandidate'], $attribute_val)) {\n\t\t\t\t$weight += 5;\n\t\t\t}\n\t\t}\n\t\treturn $weight;\n\t}\n\n\t/**\n\t* Get an element relative weight.\n\t*\n\t* @param DOMElement $e\n\t* @return number (Integer)\n\t*/\n\tpublic function getWeight($e) {\n\t\tif(!$this->flagIsActive(self::FLAG_WEIGHT_ATTRIBUTES)) {\n\t\t\treturn 0;\n\t\t}\n\n\t\t$weight = 0;\n\n\t\t/* Look for a special classname */\n\t\t$weight += $this->weightAttribute($e, 'class');\n\t\t/* Look for a special ID */\n\t\t$weight += $this->weightAttribute($e, 'id');\n\n\t\treturn $weight;\n\t}\n\n\t/**\n\t* Remove extraneous break tags from a node.\n\t*\n\t* @param DOMElement $node\n\t* @return void\n\t*/\n\tpublic function killBreaks($node) {\n\t\t$html = $node->innerHTML;\n\t\t$html = preg_replace($this->regexps['killBreaks'], '<br />', $html);\n\t\t$node->innerHTML = $html;\n\t}\n\n\t/**\n\t* Clean a node of all elements of type \"tag\".\n\t* (Unless it's a youtube/vimeo video. People love movies.)\n\t*\n\t* Updated 2012-09-18 to preserve youtube/vimeo iframes\n\t*\n\t* @param DOMElement $e\n\t* @param string $tag\n\t* @return void\n\t*/\n\tpublic function clean($e, $tag) {\n\t\t$targetList = $e->getElementsByTagName($tag);\n\t\t$isEmbed = ($tag === 'audio' || $tag === 'video' || $tag === 'iframe' || $tag === 'object' || $tag === 'embed');\n\n\t\tfor ($cur_item = null, $y = $targetList->length-1; $y >= 0; $y--) {\n\t\t\t/* Allow youtube and vimeo videos through as people usually want to see those. */\n\t\t\t$cur_item = $targetList->item($y);\n\t\t\tif ($isEmbed) {\n\t\t\t\t$attributeValues = $cur_item->getAttribute('src').' '.$cur_item->getAttribute('href');\n\n\t\t\t\t/* First, check the elements attributes to see if any of them contain known media hosts */\n\t\t\t\tif (preg_match($this->regexps['media'], $attributeValues)) continue;\n\n\t\t\t\t/* Then check the elements inside this element for the same. */\n\t\t\t\tif (preg_match($this->regexps['media'], $targetList->item($y)->innerHTML)) continue;\n\t\t\t}\n\t\t\t$cur_item->parentNode->removeChild($cur_item);\n\t\t}\n\t}\n\n\t/**\n\t* Clean an element of all tags of type \"tag\" if they look fishy.\n\t* \"Fishy\" is an algorithm based on content length, classnames,\n\t* link density, number of images & embeds, etc.\n\t*\n\t* @param DOMElement $e\n\t* @param string $tag\n\t* @return void\n\t*/\n\tpublic function cleanConditionally($e, $tag) {\n\t\tif (!$this->flagIsActive(self::FLAG_CLEAN_CONDITIONALLY)) {\n\t\t\treturn;\n\t\t}\n\n\t\t$tagsList = $e->getElementsByTagName($tag);\n\t\t$curTagsLength = $tagsList->length;\n\n\t\t/**\n\t\t* Gather counts for other typical elements embedded within.\n\t\t* Traverse backwards so we can remove nodes at the same time without effecting the traversal.\n\t\t*\n\t\t* TODO: Consider taking into account original contentScore here.\n\t\t*/\n\t\tfor ($node = null, $i = $curTagsLength - 1; $i >= 0; $i--) {\n\t\t\t$node = $tagsList->item($i);\n\t\t\t//$class = $node->getAttribute('class').' '.$node->getAttribute('id'); //debug\n\t\t\t$weight = $this->getWeight($node);\n\t\t\t$contentScore = ($node->hasAttribute('readability')) ? (int)$node->getAttribute('readability') : 0;\n\n\t\t\t$this->dbg('Start conditional cleaning of ' . $node->getNodePath() . ' (class=' . $node->getAttribute('class') . '; id=' . $node->getAttribute('id') . ')' . (($node->hasAttribute('readability')) ? (' with score ' . $node->getAttribute('readability')) : ''));\n\n\t\t\tif ($weight + $contentScore < 0) {\n\t\t\t\t$this->dbg('Removing...');\n\t\t\t\t$node->parentNode->removeChild($node);\n\t\t\t}\n\t\t\telse if ($this->getCommaCount($this->getInnerText($node)) < self::MIN_COMMAS_IN_PARAGRAPH) {\n\t\t\t\t/**\n\t\t\t\t* If there are not very many commas, and the number of\n\t\t\t\t* non-paragraph elements is more than paragraphs or other ominous signs, remove the element.\n\t\t\t\t**/\n\t\t\t\t$p = $node->getElementsByTagName('p')->length;\n\t\t\t\t$img = $node->getElementsByTagName('img')->length;\n\t\t\t\t$li = $node->getElementsByTagName('li')->length-100;\n\t\t\t\t$input = $node->getElementsByTagName('input')->length;\n\t\t\t\t$a = $node->getElementsByTagName('a')->length;\n\n\t\t\t\t$embedCount = 0;\n\t\t\t\t$embeds = $node->getElementsByTagName('embed');\n\t\t\t\tfor ($ei=0, $il=$embeds->length; $ei < $il; $ei++) {\n\t\t\t\t\tif (preg_match($this->regexps['media'], $embeds->item($ei)->getAttribute('src'))) {\n\t\t\t\t\t\t$embedCount++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$embeds = $node->getElementsByTagName('iframe');\n\t\t\t\tfor ($ei=0, $il=$embeds->length; $ei < $il; $ei++) {\n\t\t\t\t\tif (preg_match($this->regexps['media'], $embeds->item($ei)->getAttribute('src'))) {\n\t\t\t\t\t\t$embedCount++;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$linkDensity   = $this->getLinkDensity($node, true);\n\t\t\t\t$contentLength = mb_strlen($this->getInnerText($node));\n\t\t\t\t$toRemove = false;\n\n\t\t\t\tif ($this->lightClean) {\n\t\t\t\t\tif ($li > $p && $tag != 'ul' && $tag != 'ol') {\n\t\t\t\t\t\t$this->dbg(' too many <li> elements, and parent is not <ul> or <ol>');\n\t\t\t\t\t\t$toRemove = true;\n\t\t\t\t\t} else if ( $input > floor($p/3) ) {\n\t\t\t\t\t\t$this->dbg(' too many <input> elements');\n\t\t\t\t\t\t$toRemove = true;\n\t\t\t\t\t} else if ($contentLength < 6 && ($embedCount === 0 && ($img === 0 || $img > 2))) {\n\t\t\t\t\t\t$this->dbg(' content length less than 6 chars, 0 embeds and either 0 images or more than 2 images');\n\t\t\t\t\t\t$toRemove = true;\n\t\t\t\t\t} else if($weight < 25 && $linkDensity > 0.25) {\n\t\t\t\t\t\t$this->dbg(' weight is '.$weight.' < 25 and link density is '.sprintf(\"%.2f\", $linkDensity).' > 0.25');\n\t\t\t\t\t\t$toRemove = true;\n\t\t\t\t\t} else if($a > 2 && ($weight >= 25 && $linkDensity > 0.5)) {\n\t\t\t\t\t\t$this->dbg('  more than 2 links and weight is '.$weight.' > 25 but link density is '.sprintf(\"%.2f\", $linkDensity).' > 0.5');\n\t\t\t\t\t\t$toRemove = true;\n\t\t\t\t\t} else if($embedCount > 3) {\n\t\t\t\t\t\t$this->dbg(' more than 3 embeds');\n\t\t\t\t\t\t$toRemove = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif ( $img > $p ) {\n\t\t\t\t\t\t$this->dbg(' more image elements than paragraph elements');\n\t\t\t\t\t\t$toRemove = true;\n\t\t\t\t\t} else if ($li > $p && $tag != 'ul' && $tag != 'ol') {\n\t\t\t\t\t\t$this->dbg('  too many <li> elements, and parent is not <ul> or <ol>');\n\t\t\t\t\t\t$toRemove = true;\n\t\t\t\t\t} else if ( $input > floor($p/3) ) {\n\t\t\t\t\t\t$this->dbg('  too many <input> elements');\n\t\t\t\t\t\t$toRemove = true;\n\t\t\t\t\t} else if ($contentLength < 25 && ($img === 0 || $img > 2) ) {\n\t\t\t\t\t\t$this->dbg('  content length less than 25 chars and 0 images, or more than 2 images');\n\t\t\t\t\t\t$toRemove = true;\n\t\t\t\t\t} else if($weight < 25 && $linkDensity > 0.2) {\n\t\t\t\t\t\t$this->dbg('  weight is '.$weight.' lower than 0 and link density is '.sprintf(\"%.2f\", $linkDensity).' > 0.2');\n\t\t\t\t\t\t$toRemove = true;\n\t\t\t\t\t} else if($weight >= 25 && $linkDensity > 0.5) {\n\t\t\t\t\t\t$this->dbg('  weight above 25 but link density is '.sprintf(\"%.2f\", $linkDensity).' > 0.5');\n\t\t\t\t\t\t$toRemove = true;\n\t\t\t\t\t} else if(($embedCount == 1 && $contentLength < 75) || $embedCount > 1) {\n\t\t\t\t\t\t$this->dbg('  1 embed and content length smaller than 75 chars, or more than one embed');\n\t\t\t\t\t\t$toRemove = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ($toRemove) {\n\t\t\t\t\t//$this->dbg('Removing: '.$node->innerHTML);\n\t\t\t\t\t$this->dbg('Removing...');\n\t\t\t\t\t$node->parentNode->removeChild($node);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t* Clean out spurious headers from an Element. Checks things like classnames and link density.\n\t*\n\t* @param DOMElement $e\n\t* @return void\n\t*/\n\tpublic function cleanHeaders($e) {\n\t\tfor ($headerIndex = 1; $headerIndex < 3; $headerIndex++) {\n\t\t\t$headers = $e->getElementsByTagName('h' . $headerIndex);\n\t\t\tfor ($i=$headers->length-1; $i >=0; $i--) {\n\t\t\t\tif ($this->getWeight($headers->item($i)) < 0 || $this->getLinkDensity($headers->item($i)) > 0.33) {\n\t\t\t\t\t$headers->item($i)->parentNode->removeChild($headers->item($i));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic function flagIsActive($flag) {\n\t\treturn ($this->flags & $flag) > 0;\n\t}\n\n\tpublic function addFlag($flag) {\n\t\t$this->flags = $this->flags | $flag;\n\t}\n\n\tpublic function removeFlag($flag) {\n\t\t$this->flags = $this->flags & ~$flag;\n\t}\n}\n?>"
  },
  {
    "path": "libraries/simplepie/LICENSE.txt",
    "content": "Copyright (c) 2004-2007, Ryan Parman and Geoffrey Sneddon.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are \npermitted provided that the following conditions are met:\n\n\t* Redistributions of source code must retain the above copyright notice, this list of \n\t  conditions and the following disclaimer.\n\n\t* Redistributions in binary form must reproduce the above copyright notice, this list \n\t  of conditions and the following disclaimer in the documentation and/or other materials \n\t  provided with the distribution.\n\n\t* Neither the name of the SimplePie Team nor the names of its contributors may be used \n\t  to endorse or promote products derived from this software without specific prior \n\t  written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS \nOR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY \nAND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS \nAND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY \nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR \nOTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE \nPOSSIBILITY OF SUCH DAMAGE."
  },
  {
    "path": "libraries/simplepie/autoloader.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2009, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n\n// autoloader\nspl_autoload_register(array(new SimplePie_Autoloader(), 'autoload'));\n\nif (!class_exists('SimplePie'))\n{\n\ttrigger_error('Autoloader not registered properly', E_USER_ERROR);\n}\n\n/**\n * Autoloader class\n *\n * @package SimplePie\n * @subpackage API\n */\nclass SimplePie_Autoloader\n{\n\t/**\n\t * Constructor\n\t */\n\tpublic function __construct()\n\t{\n\t\t$this->path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'library';\n\t}\n\n\t/**\n\t * Autoloader\n\t *\n\t * @param string $class The name of the class to attempt to load.\n\t */\n\tpublic function autoload($class)\n\t{\n\t\t// Only load the class if it starts with \"SimplePie\"\n\t\tif (strpos($class, 'SimplePie') !== 0)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t$filename = $this->path . DIRECTORY_SEPARATOR . str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';\n\t\tinclude $filename;\n\t}\n}"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Author.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Manages all author-related data\n *\n * Used by {@see SimplePie_Item::get_author()} and {@see SimplePie::get_authors()}\n *\n * This class can be overloaded with {@see SimplePie::set_author_class()}\n *\n * @package SimplePie\n * @subpackage API\n */\nclass SimplePie_Author\n{\n\t/**\n\t * Author's name\n\t *\n\t * @var string\n\t * @see get_name()\n\t */\n\tvar $name;\n\n\t/**\n\t * Author's link\n\t *\n\t * @var string\n\t * @see get_link()\n\t */\n\tvar $link;\n\n\t/**\n\t * Author's email address\n\t *\n\t * @var string\n\t * @see get_email()\n\t */\n\tvar $email;\n\n\t/**\n\t * Constructor, used to input the data\n\t *\n\t * @param string $name\n\t * @param string $link\n\t * @param string $email\n\t */\n\tpublic function __construct($name = null, $link = null, $email = null)\n\t{\n\t\t$this->name = $name;\n\t\t$this->link = $link;\n\t\t$this->email = $email;\n\t}\n\n\t/**\n\t * String-ified version\n\t *\n\t * @return string\n\t */\n\tpublic function __toString()\n\t{\n\t\t// There is no $this->data here\n\t\treturn md5(serialize($this));\n\t}\n\n\t/**\n\t * Author's name\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_name()\n\t{\n\t\tif ($this->name !== null)\n\t\t{\n\t\t\treturn $this->name;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Author's link\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_link()\n\t{\n\t\tif ($this->link !== null)\n\t\t{\n\t\t\treturn $this->link;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Author's email address\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_email()\n\t{\n\t\tif ($this->email !== null)\n\t\t{\n\t\t\treturn $this->email;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Cache/Base.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Base for cache objects\n *\n * Classes to be used with {@see SimplePie_Cache::register()} are expected\n * to implement this interface.\n *\n * @package SimplePie\n * @subpackage Caching\n */\ninterface SimplePie_Cache_Base\n{\n\t/**\n\t * Feed cache type\n\t *\n\t * @var string\n\t */\n\tconst TYPE_FEED = 'spc';\n\n\t/**\n\t * Image cache type\n\t *\n\t * @var string\n\t */\n\tconst TYPE_IMAGE = 'spi';\n\n\t/**\n\t * Create a new cache object\n\t *\n\t * @param string $location Location string (from SimplePie::$cache_location)\n\t * @param string $name Unique ID for the cache\n\t * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data\n\t */\n\tpublic function __construct($location, $name, $type);\n\n\t/**\n\t * Save data to the cache\n\t *\n\t * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property\n\t * @return bool Successfulness\n\t */\n\tpublic function save($data);\n\n\t/**\n\t * Retrieve the data saved to the cache\n\t *\n\t * @return array Data for SimplePie::$data\n\t */\n\tpublic function load();\n\n\t/**\n\t * Retrieve the last modified time for the cache\n\t *\n\t * @return int Timestamp\n\t */\n\tpublic function mtime();\n\n\t/**\n\t * Set the last modified time to the current time\n\t *\n\t * @return bool Success status\n\t */\n\tpublic function touch();\n\n\t/**\n\t * Remove the cache\n\t *\n\t * @return bool Success status\n\t */\n\tpublic function unlink();\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Cache/DB.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Base class for database-based caches\n *\n * @package SimplePie\n * @subpackage Caching\n */\nabstract class SimplePie_Cache_DB implements SimplePie_Cache_Base\n{\n\t/**\n\t * Helper for database conversion\n\t *\n\t * Converts a given {@see SimplePie} object into data to be stored\n\t *\n\t * @param SimplePie $data\n\t * @return array First item is the serialized data for storage, second item is the unique ID for this item\n\t */\n\tprotected static function prepare_simplepie_object_for_cache($data)\n\t{\n\t\t$items = $data->get_items();\n\t\t$items_by_id = array();\n\n\t\tif (!empty($items))\n\t\t{\n\t\t\tforeach ($items as $item)\n\t\t\t{\n\t\t\t\t$items_by_id[$item->get_id()] = $item;\n\t\t\t}\n\n\t\t\tif (count($items_by_id) !== count($items))\n\t\t\t{\n\t\t\t\t$items_by_id = array();\n\t\t\t\tforeach ($items as $item)\n\t\t\t\t{\n\t\t\t\t\t$items_by_id[$item->get_id(true)] = $item;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))\n\t\t\t{\n\t\t\t\t$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];\n\t\t\t}\n\t\t\telseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))\n\t\t\t{\n\t\t\t\t$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];\n\t\t\t}\n\t\t\telseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))\n\t\t\t{\n\t\t\t\t$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];\n\t\t\t}\n\t\t\telseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))\n\t\t\t{\n\t\t\t\t$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$channel = null;\n\t\t\t}\n\n\t\t\tif ($channel !== null)\n\t\t\t{\n\t\t\t\tif (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))\n\t\t\t\t{\n\t\t\t\t\tunset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);\n\t\t\t\t}\n\t\t\t\tif (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))\n\t\t\t\t{\n\t\t\t\t\tunset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);\n\t\t\t\t}\n\t\t\t\tif (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))\n\t\t\t\t{\n\t\t\t\t\tunset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);\n\t\t\t\t}\n\t\t\t\tif (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))\n\t\t\t\t{\n\t\t\t\t\tunset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);\n\t\t\t\t}\n\t\t\t\tif (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))\n\t\t\t\t{\n\t\t\t\t\tunset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (isset($data->data['items']))\n\t\t\t{\n\t\t\t\tunset($data->data['items']);\n\t\t\t}\n\t\t\tif (isset($data->data['ordered_items']))\n\t\t\t{\n\t\t\t\tunset($data->data['ordered_items']);\n\t\t\t}\n\t\t}\n\t\treturn array(serialize($data->data), $items_by_id);\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Cache/File.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Caches data to the filesystem\n *\n * @package SimplePie\n * @subpackage Caching\n */\nclass SimplePie_Cache_File implements SimplePie_Cache_Base\n{\n\t/**\n\t * Location string\n\t *\n\t * @see SimplePie::$cache_location\n\t * @var string\n\t */\n\tprotected $location;\n\n\t/**\n\t * Filename\n\t *\n\t * @var string\n\t */\n\tprotected $filename;\n\n\t/**\n\t * File extension\n\t *\n\t * @var string\n\t */\n\tprotected $extension;\n\n\t/**\n\t * File path\n\t *\n\t * @var string\n\t */\n\tprotected $name;\n\n\t/**\n\t * Create a new cache object\n\t *\n\t * @param string $location Location string (from SimplePie::$cache_location)\n\t * @param string $name Unique ID for the cache\n\t * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data\n\t */\n\tpublic function __construct($location, $name, $type)\n\t{\n\t\t$this->location = $location;\n\t\t$this->filename = $name;\n\t\t$this->extension = $type;\n\t\t$this->name = \"$this->location/$this->filename.$this->extension\";\n\t}\n\n\t/**\n\t * Save data to the cache\n\t *\n\t * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property\n\t * @return bool Successfulness\n\t */\n\tpublic function save($data)\n\t{\n\t\tif (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))\n\t\t{\n\t\t\tif ($data instanceof SimplePie)\n\t\t\t{\n\t\t\t\t$data = $data->data;\n\t\t\t}\n\n\t\t\t$data = serialize($data);\n\t\t\treturn (bool) file_put_contents($this->name, $data);\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Retrieve the data saved to the cache\n\t *\n\t * @return array Data for SimplePie::$data\n\t */\n\tpublic function load()\n\t{\n\t\tif (file_exists($this->name) && is_readable($this->name))\n\t\t{\n\t\t\treturn unserialize(file_get_contents($this->name));\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Retrieve the last modified time for the cache\n\t *\n\t * @return int Timestamp\n\t */\n\tpublic function mtime()\n\t{\n\t\tif (file_exists($this->name))\n\t\t{\n\t\t\treturn filemtime($this->name);\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Set the last modified time to the current time\n\t *\n\t * @return bool Success status\n\t */\n\tpublic function touch()\n\t{\n\t\tif (file_exists($this->name))\n\t\t{\n\t\t\treturn touch($this->name);\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Remove the cache\n\t *\n\t * @return bool Success status\n\t */\n\tpublic function unlink()\n\t{\n\t\tif (file_exists($this->name))\n\t\t{\n\t\t\treturn unlink($this->name);\n\t\t}\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Cache/Memcache.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Caches data to memcache\n *\n * Registered for URLs with the \"memcache\" protocol\n *\n * For example, `memcache://localhost:11211/?timeout=3600&prefix=sp_` will\n * connect to memcache on `localhost` on port 11211. All tables will be\n * prefixed with `sp_` and data will expire after 3600 seconds\n *\n * @package SimplePie\n * @subpackage Caching\n * @uses Memcache\n */\nclass SimplePie_Cache_Memcache implements SimplePie_Cache_Base\n{\n\t/**\n\t * Memcache instance\n\t *\n\t * @var Memcache\n\t */\n\tprotected $cache;\n\n\t/**\n\t * Options\n\t *\n\t * @var array\n\t */\n\tprotected $options;\n\n\t/**\n\t * Cache name\n\t *\n\t * @var string\n\t */\n\tprotected $name;\n\n\t/**\n\t * Create a new cache object\n\t *\n\t * @param string $location Location string (from SimplePie::$cache_location)\n\t * @param string $name Unique ID for the cache\n\t * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data\n\t */\n\tpublic function __construct($location, $name, $type)\n\t{\n\t\t$this->options = array(\n\t\t\t'host' => '127.0.0.1',\n\t\t\t'port' => 11211,\n\t\t\t'extras' => array(\n\t\t\t\t'timeout' => 3600, // one hour\n\t\t\t\t'prefix' => 'simplepie_',\n\t\t\t),\n\t\t);\n\t\t$parsed = SimplePie_Cache::parse_URL($location);\n\t\t$this->options['host'] = empty($parsed['host']) ? $this->options['host'] : $parsed['host'];\n\t\t$this->options['port'] = empty($parsed['port']) ? $this->options['port'] : $parsed['port'];\n\t\t$this->options['extras'] = array_merge($this->options['extras'], $parsed['extras']);\n\t\t$this->name = $this->options['extras']['prefix'] . md5(\"$name:$type\");\n\n\t\t$this->cache = new Memcache();\n\t\t$this->cache->addServer($this->options['host'], (int) $this->options['port']);\n\t}\n\n\t/**\n\t * Save data to the cache\n\t *\n\t * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property\n\t * @return bool Successfulness\n\t */\n\tpublic function save($data)\n\t{\n\t\tif ($data instanceof SimplePie)\n\t\t{\n\t\t\t$data = $data->data;\n\t\t}\n\t\treturn $this->cache->set($this->name, serialize($data), MEMCACHE_COMPRESSED, (int) $this->options['extras']['timeout']);\n\t}\n\n\t/**\n\t * Retrieve the data saved to the cache\n\t *\n\t * @return array Data for SimplePie::$data\n\t */\n\tpublic function load()\n\t{\n\t\t$data = $this->cache->get($this->name);\n\n\t\tif ($data !== false)\n\t\t{\n\t\t\treturn unserialize($data);\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Retrieve the last modified time for the cache\n\t *\n\t * @return int Timestamp\n\t */\n\tpublic function mtime()\n\t{\n\t\t$data = $this->cache->get($this->name);\n\n\t\tif ($data !== false)\n\t\t{\n\t\t\t// essentially ignore the mtime because Memcache expires on it's own\n\t\t\treturn time();\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Set the last modified time to the current time\n\t *\n\t * @return bool Success status\n\t */\n\tpublic function touch()\n\t{\n\t\t$data = $this->cache->get($this->name);\n\n\t\tif ($data !== false)\n\t\t{\n\t\t\treturn $this->cache->set($this->name, $data, MEMCACHE_COMPRESSED, (int) $this->duration);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Remove the cache\n\t *\n\t * @return bool Success status\n\t */\n\tpublic function unlink()\n\t{\n\t\treturn $this->cache->delete($this->name, 0);\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Cache/MySQL.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Caches data to a MySQL database\n *\n * Registered for URLs with the \"mysql\" protocol\n *\n * For example, `mysql://root:password@localhost:3306/mydb?prefix=sp_` will\n * connect to the `mydb` database on `localhost` on port 3306, with the user\n * `root` and the password `password`. All tables will be prefixed with `sp_`\n *\n * @package SimplePie\n * @subpackage Caching\n */\nclass SimplePie_Cache_MySQL extends SimplePie_Cache_DB\n{\n\t/**\n\t * PDO instance\n\t *\n\t * @var PDO\n\t */\n\tprotected $mysql;\n\n\t/**\n\t * Options\n\t *\n\t * @var array\n\t */\n\tprotected $options;\n\n\t/**\n\t * Cache ID\n\t *\n\t * @var string\n\t */\n\tprotected $id;\n\n\t/**\n\t * Create a new cache object\n\t *\n\t * @param string $location Location string (from SimplePie::$cache_location)\n\t * @param string $name Unique ID for the cache\n\t * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data\n\t */\n\tpublic function __construct($location, $name, $type)\n\t{\n\t\t$this->options = array(\n\t\t\t'user' => null,\n\t\t\t'pass' => null,\n\t\t\t'host' => '127.0.0.1',\n\t\t\t'port' => '3306',\n\t\t\t'path' => '',\n\t\t\t'extras' => array(\n\t\t\t\t'prefix' => '',\n\t\t\t),\n\t\t);\n\t\t$this->options = array_merge_recursive($this->options, SimplePie_Cache::parse_URL($location));\n\n\t\t// Path is prefixed with a \"/\"\n\t\t$this->options['dbname'] = substr($this->options['path'], 1);\n\n\t\ttry\n\t\t{\n\t\t\t$this->mysql = new PDO(\"mysql:dbname={$this->options['dbname']};host={$this->options['host']};port={$this->options['port']}\", $this->options['user'], $this->options['pass'], array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));\n\t\t}\n\t\tcatch (PDOException $e)\n\t\t{\n\t\t\t$this->mysql = null;\n\t\t\treturn;\n\t\t}\n\n\t\t$this->id = $name . $type;\n\n\t\tif (!$query = $this->mysql->query('SHOW TABLES'))\n\t\t{\n\t\t\t$this->mysql = null;\n\t\t\treturn;\n\t\t}\n\n\t\t$db = array();\n\t\twhile ($row = $query->fetchColumn())\n\t\t{\n\t\t\t$db[] = $row;\n\t\t}\n\n\t\tif (!in_array($this->options['extras']['prefix'] . 'cache_data', $db))\n\t\t{\n\t\t\t$query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))');\n\t\t\tif ($query === false)\n\t\t\t{\n\t\t\t\t$this->mysql = null;\n\t\t\t}\n\t\t}\n\n\t\tif (!in_array($this->options['extras']['prefix'] . 'items', $db))\n\t\t{\n\t\t\t$query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` TEXT CHARACTER SET utf8 NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))');\n\t\t\tif ($query === false)\n\t\t\t{\n\t\t\t\t$this->mysql = null;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Save data to the cache\n\t *\n\t * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property\n\t * @return bool Successfulness\n\t */\n\tpublic function save($data)\n\t{\n\t\tif ($this->mysql === null)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\tif ($data instanceof SimplePie)\n\t\t{\n\t\t\t$data = clone $data;\n\n\t\t\t$prepared = self::prepare_simplepie_object_for_cache($data);\n\n\t\t\t$query = $this->mysql->prepare('SELECT COUNT(*) FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed');\n\t\t\t$query->bindValue(':feed', $this->id);\n\t\t\tif ($query->execute())\n\t\t\t{\n\t\t\t\tif ($query->fetchColumn() > 0)\n\t\t\t\t{\n\t\t\t\t\t$items = count($prepared[1]);\n\t\t\t\t\tif ($items)\n\t\t\t\t\t{\n\t\t\t\t\t\t$sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = :items, `data` = :data, `mtime` = :time WHERE `id` = :feed';\n\t\t\t\t\t\t$query = $this->mysql->prepare($sql);\n\t\t\t\t\t\t$query->bindValue(':items', $items);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `data` = :data, `mtime` = :time WHERE `id` = :feed';\n\t\t\t\t\t\t$query = $this->mysql->prepare($sql);\n\t\t\t\t\t}\n\n\t\t\t\t\t$query->bindValue(':data', $prepared[0]);\n\t\t\t\t\t$query->bindValue(':time', time());\n\t\t\t\t\t$query->bindValue(':feed', $this->id);\n\t\t\t\t\tif (!$query->execute())\n\t\t\t\t\t{\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:feed, :count, :data, :time)');\n\t\t\t\t\t$query->bindValue(':feed', $this->id);\n\t\t\t\t\t$query->bindValue(':count', count($prepared[1]));\n\t\t\t\t\t$query->bindValue(':data', $prepared[0]);\n\t\t\t\t\t$query->bindValue(':time', time());\n\t\t\t\t\tif (!$query->execute())\n\t\t\t\t\t{\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$ids = array_keys($prepared[1]);\n\t\t\t\tif (!empty($ids))\n\t\t\t\t{\n\t\t\t\t\tforeach ($ids as $id)\n\t\t\t\t\t{\n\t\t\t\t\t\t$database_ids[] = $this->mysql->quote($id);\n\t\t\t\t\t}\n\n\t\t\t\t\t$query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `id` = ' . implode(' OR `id` = ', $database_ids) . ' AND `feed_id` = :feed');\n\t\t\t\t\t$query->bindValue(':feed', $this->id);\n\n\t\t\t\t\tif ($query->execute())\n\t\t\t\t\t{\n\t\t\t\t\t\t$existing_ids = array();\n\t\t\t\t\t\twhile ($row = $query->fetchColumn())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$existing_ids[] = $row;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$new_ids = array_diff($ids, $existing_ids);\n\n\t\t\t\t\t\tforeach ($new_ids as $new_id)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!($date = $prepared[1][$new_id]->get_date('U')))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$date = time();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t$query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(:feed, :id, :data, :date)');\n\t\t\t\t\t\t\t$query->bindValue(':feed', $this->id);\n\t\t\t\t\t\t\t$query->bindValue(':id', $new_id);\n\t\t\t\t\t\t\t$query->bindValue(':data', serialize($prepared[1][$new_id]->data));\n\t\t\t\t\t\t\t$query->bindValue(':date', $date);\n\t\t\t\t\t\t\tif (!$query->execute())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed');\n\t\t\t$query->bindValue(':feed', $this->id);\n\t\t\tif ($query->execute())\n\t\t\t{\n\t\t\t\tif ($query->rowCount() > 0)\n\t\t\t\t{\n\t\t\t\t\t$query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = 0, `data` = :data, `mtime` = :time WHERE `id` = :feed');\n\t\t\t\t\t$query->bindValue(':data', serialize($data));\n\t\t\t\t\t$query->bindValue(':time', time());\n\t\t\t\t\t$query->bindValue(':feed', $this->id);\n\t\t\t\t\tif ($this->execute())\n\t\t\t\t\t{\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:id, 0, :data, :time)');\n\t\t\t\t\t$query->bindValue(':id', $this->id);\n\t\t\t\t\t$query->bindValue(':data', serialize($data));\n\t\t\t\t\t$query->bindValue(':time', time());\n\t\t\t\t\tif ($query->execute())\n\t\t\t\t\t{\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Retrieve the data saved to the cache\n\t *\n\t * @return array Data for SimplePie::$data\n\t */\n\tpublic function load()\n\t{\n\t\tif ($this->mysql === null)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\t$query = $this->mysql->prepare('SELECT `items`, `data` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');\n\t\t$query->bindValue(':id', $this->id);\n\t\tif ($query->execute() && ($row = $query->fetch()))\n\t\t{\n\t\t\t$data = unserialize($row[1]);\n\n\t\t\tif (isset($this->options['items'][0]))\n\t\t\t{\n\t\t\t\t$items = (int) $this->options['items'][0];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$items = (int) $row[0];\n\t\t\t}\n\n\t\t\tif ($items !== 0)\n\t\t\t{\n\t\t\t\tif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))\n\t\t\t\t{\n\t\t\t\t\t$feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];\n\t\t\t\t}\n\t\t\t\telseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))\n\t\t\t\t{\n\t\t\t\t\t$feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];\n\t\t\t\t}\n\t\t\t\telseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))\n\t\t\t\t{\n\t\t\t\t\t$feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];\n\t\t\t\t}\n\t\t\t\telseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))\n\t\t\t\t{\n\t\t\t\t\t$feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$feed = null;\n\t\t\t\t}\n\n\t\t\t\tif ($feed !== null)\n\t\t\t\t{\n\t\t\t\t\t$sql = 'SELECT `data` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :feed ORDER BY `posted` DESC';\n\t\t\t\t\tif ($items > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t$sql .= ' LIMIT ' . $items;\n\t\t\t\t\t}\n\n\t\t\t\t\t$query = $this->mysql->prepare($sql);\n\t\t\t\t\t$query->bindValue(':feed', $this->id);\n\t\t\t\t\tif ($query->execute())\n\t\t\t\t\t{\n\t\t\t\t\t\twhile ($row = $query->fetchColumn())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn $data;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Retrieve the last modified time for the cache\n\t *\n\t * @return int Timestamp\n\t */\n\tpublic function mtime()\n\t{\n\t\tif ($this->mysql === null)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\t$query = $this->mysql->prepare('SELECT `mtime` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');\n\t\t$query->bindValue(':id', $this->id);\n\t\tif ($query->execute() && ($time = $query->fetchColumn()))\n\t\t{\n\t\t\treturn $time;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Set the last modified time to the current time\n\t *\n\t * @return bool Success status\n\t */\n\tpublic function touch()\n\t{\n\t\tif ($this->mysql === null)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\t$query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `mtime` = :time WHERE `id` = :id');\n\t\t$query->bindValue(':time', time());\n\t\t$query->bindValue(':id', $this->id);\n\t\tif ($query->execute() && $query->rowCount() > 0)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Remove the cache\n\t *\n\t * @return bool Success status\n\t */\n\tpublic function unlink()\n\t{\n\t\tif ($this->mysql === null)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\t$query = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');\n\t\t$query->bindValue(':id', $this->id);\n\t\t$query2 = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :id');\n\t\t$query2->bindValue(':id', $this->id);\n\t\tif ($query->execute() && $query2->execute())\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Cache.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Used to create cache objects\n *\n * This class can be overloaded with {@see SimplePie::set_cache_class()},\n * although the preferred way is to create your own handler\n * via {@see register()}\n *\n * @package SimplePie\n * @subpackage Caching\n */\nclass SimplePie_Cache\n{\n\t/**\n\t * Cache handler classes\n\t *\n\t * These receive 3 parameters to their constructor, as documented in\n\t * {@see register()}\n\t * @var array\n\t */\n\tprotected static $handlers = array(\n\t\t'mysql' => 'SimplePie_Cache_MySQL',\n\t\t'memcache' => 'SimplePie_Cache_Memcache',\n\t);\n\n\t/**\n\t * Don't call the constructor. Please.\n\t */\n\tprivate function __construct() { }\n\n\t/**\n\t * Create a new SimplePie_Cache object\n\t *\n\t * @param string $location URL location (scheme is used to determine handler)\n\t * @param string $filename Unique identifier for cache object\n\t * @param string $extension 'spi' or 'spc'\n\t * @return SimplePie_Cache_Base Type of object depends on scheme of `$location`\n\t */\n\tpublic static function get_handler($location, $filename, $extension)\n\t{\n\t\t$type = explode(':', $location, 2);\n\t\t$type = $type[0];\n\t\tif (!empty(self::$handlers[$type]))\n\t\t{\n\t\t\t$class = self::$handlers[$type];\n\t\t\treturn new $class($location, $filename, $extension);\n\t\t}\n\n\t\treturn new SimplePie_Cache_File($location, $filename, $extension);\n\t}\n\n\t/**\n\t * Create a new SimplePie_Cache object\n\t *\n\t * @deprecated Use {@see get_handler} instead\n\t */\n\tpublic function create($location, $filename, $extension)\n\t{\n\t\ttrigger_error('Cache::create() has been replaced with Cache::get_handler(). Switch to the registry system to use this.', E_USER_DEPRECATED);\n\t\treturn self::get_handler($location, $filename, $extension);\n\t}\n\n\t/**\n\t * Register a handler\n\t *\n\t * @param string $type DSN type to register for\n\t * @param string $class Name of handler class. Must implement SimplePie_Cache_Base\n\t */\n\tpublic static function register($type, $class)\n\t{\n\t\tself::$handlers[$type] = $class;\n\t}\n\n\t/**\n\t * Parse a URL into an array\n\t *\n\t * @param string $url\n\t * @return array\n\t */\n\tpublic static function parse_URL($url)\n\t{\n\t\t$params = parse_url($url);\n\t\t$params['extras'] = array();\n\t\tif (isset($params['query']))\n\t\t{\n\t\t\tparse_str($params['query'], $params['extras']);\n\t\t}\n\t\treturn $params;\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Caption.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n\n/**\n * Handles `<media:text>` captions as defined in Media RSS.\n *\n * Used by {@see SimplePie_Enclosure::get_caption()} and {@see SimplePie_Enclosure::get_captions()}\n *\n * This class can be overloaded with {@see SimplePie::set_caption_class()}\n *\n * @package SimplePie\n * @subpackage API\n */\nclass SimplePie_Caption\n{\n\t/**\n\t * Content type\n\t *\n\t * @var string\n\t * @see get_type()\n\t */\n\tvar $type;\n\n\t/**\n\t * Language\n\t *\n\t * @var string\n\t * @see get_language()\n\t */\n\tvar $lang;\n\n\t/**\n\t * Start time\n\t *\n\t * @var string\n\t * @see get_starttime()\n\t */\n\tvar $startTime;\n\n\t/**\n\t * End time\n\t *\n\t * @var string\n\t * @see get_endtime()\n\t */\n\tvar $endTime;\n\n\t/**\n\t * Caption text\n\t *\n\t * @var string\n\t * @see get_text()\n\t */\n\tvar $text;\n\n\t/**\n\t * Constructor, used to input the data\n\t *\n\t * For documentation on all the parameters, see the corresponding\n\t * properties and their accessors\n\t */\n\tpublic function __construct($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)\n\t{\n\t\t$this->type = $type;\n\t\t$this->lang = $lang;\n\t\t$this->startTime = $startTime;\n\t\t$this->endTime = $endTime;\n\t\t$this->text = $text;\n\t}\n\n\t/**\n\t * String-ified version\n\t *\n\t * @return string\n\t */\n\tpublic function __toString()\n\t{\n\t\t// There is no $this->data here\n\t\treturn md5(serialize($this));\n\t}\n\n\t/**\n\t * Get the end time\n\t *\n\t * @return string|null Time in the format 'hh:mm:ss.SSS'\n\t */\n\tpublic function get_endtime()\n\t{\n\t\tif ($this->endTime !== null)\n\t\t{\n\t\t\treturn $this->endTime;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the language\n\t *\n\t * @link http://tools.ietf.org/html/rfc3066\n\t * @return string|null Language code as per RFC 3066\n\t */\n\tpublic function get_language()\n\t{\n\t\tif ($this->lang !== null)\n\t\t{\n\t\t\treturn $this->lang;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the start time\n\t *\n\t * @return string|null Time in the format 'hh:mm:ss.SSS'\n\t */\n\tpublic function get_starttime()\n\t{\n\t\tif ($this->startTime !== null)\n\t\t{\n\t\t\treturn $this->startTime;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the text of the caption\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_text()\n\t{\n\t\tif ($this->text !== null)\n\t\t{\n\t\t\treturn $this->text;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the content type (not MIME type)\n\t *\n\t * @return string|null Either 'text' or 'html'\n\t */\n\tpublic function get_type()\n\t{\n\t\tif ($this->type !== null)\n\t\t{\n\t\t\treturn $this->type;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Category.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Manages all category-related data\n *\n * Used by {@see SimplePie_Item::get_category()} and {@see SimplePie_Item::get_categories()}\n *\n * This class can be overloaded with {@see SimplePie::set_category_class()}\n *\n * @package SimplePie\n * @subpackage API\n */\nclass SimplePie_Category\n{\n\t/**\n\t * Category identifier\n\t *\n\t * @var string\n\t * @see get_term\n\t */\n\tvar $term;\n\n\t/**\n\t * Categorization scheme identifier\n\t *\n\t * @var string\n\t * @see get_scheme()\n\t */\n\tvar $scheme;\n\n\t/**\n\t * Human readable label\n\t *\n\t * @var string\n\t * @see get_label()\n\t */\n\tvar $label;\n\n\t/**\n\t * Constructor, used to input the data\n\t *\n\t * @param string $term\n\t * @param string $scheme\n\t * @param string $label\n\t */\n\tpublic function __construct($term = null, $scheme = null, $label = null)\n\t{\n\t\t$this->term = $term;\n\t\t$this->scheme = $scheme;\n\t\t$this->label = $label;\n\t}\n\n\t/**\n\t * String-ified version\n\t *\n\t * @return string\n\t */\n\tpublic function __toString()\n\t{\n\t\t// There is no $this->data here\n\t\treturn md5(serialize($this));\n\t}\n\n\t/**\n\t * Get the category identifier\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_term()\n\t{\n\t\tif ($this->term !== null)\n\t\t{\n\t\t\treturn $this->term;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the categorization scheme identifier\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_scheme()\n\t{\n\t\tif ($this->scheme !== null)\n\t\t{\n\t\t\treturn $this->scheme;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the human readable label\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_label()\n\t{\n\t\tif ($this->label !== null)\n\t\t{\n\t\t\treturn $this->label;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn $this->get_term();\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Content/Type/Sniffer.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n\n/**\n * Content-type sniffing\n *\n * Based on the rules in http://tools.ietf.org/html/draft-abarth-mime-sniff-06\n *\n * This is used since we can't always trust Content-Type headers, and is based\n * upon the HTML5 parsing rules.\n *\n *\n * This class can be overloaded with {@see SimplePie::set_content_type_sniffer_class()}\n *\n * @package SimplePie\n * @subpackage HTTP\n */\nclass SimplePie_Content_Type_Sniffer\n{\n\t/**\n\t * File object\n\t *\n\t * @var SimplePie_File\n\t */\n\tvar $file;\n\n\t/**\n\t * Create an instance of the class with the input file\n\t *\n\t * @param SimplePie_Content_Type_Sniffer $file Input file\n\t */\n\tpublic function __construct($file)\n\t{\n\t\t$this->file = $file;\n\t}\n\n\t/**\n\t * Get the Content-Type of the specified file\n\t *\n\t * @return string Actual Content-Type\n\t */\n\tpublic function get_type()\n\t{\n\t\tif (isset($this->file->headers['content-type']))\n\t\t{\n\t\t\tif (!isset($this->file->headers['content-encoding'])\n\t\t\t\t&& ($this->file->headers['content-type'] === 'text/plain'\n\t\t\t\t\t|| $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'\n\t\t\t\t\t|| $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'\n\t\t\t\t\t|| $this->file->headers['content-type'] === 'text/plain; charset=UTF-8'))\n\t\t\t{\n\t\t\t\treturn $this->text_or_binary();\n\t\t\t}\n\n\t\t\tif (($pos = strpos($this->file->headers['content-type'], ';')) !== false)\n\t\t\t{\n\t\t\t\t$official = substr($this->file->headers['content-type'], 0, $pos);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$official = $this->file->headers['content-type'];\n\t\t\t}\n\t\t\t$official = trim(strtolower($official));\n\n\t\t\tif ($official === 'unknown/unknown'\n\t\t\t\t|| $official === 'application/unknown')\n\t\t\t{\n\t\t\t\treturn $this->unknown();\n\t\t\t}\n\t\t\telseif (substr($official, -4) === '+xml'\n\t\t\t\t|| $official === 'text/xml'\n\t\t\t\t|| $official === 'application/xml')\n\t\t\t{\n\t\t\t\treturn $official;\n\t\t\t}\n\t\t\telseif (substr($official, 0, 6) === 'image/')\n\t\t\t{\n\t\t\t\tif ($return = $this->image())\n\t\t\t\t{\n\t\t\t\t\treturn $return;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn $official;\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($official === 'text/html')\n\t\t\t{\n\t\t\t\treturn $this->feed_or_html();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn $official;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn $this->unknown();\n\t\t}\n\t}\n\n\t/**\n\t * Sniff text or binary\n\t *\n\t * @return string Actual Content-Type\n\t */\n\tpublic function text_or_binary()\n\t{\n\t\tif (substr($this->file->body, 0, 2) === \"\\xFE\\xFF\"\n\t\t\t|| substr($this->file->body, 0, 2) === \"\\xFF\\xFE\"\n\t\t\t|| substr($this->file->body, 0, 4) === \"\\x00\\x00\\xFE\\xFF\"\n\t\t\t|| substr($this->file->body, 0, 3) === \"\\xEF\\xBB\\xBF\")\n\t\t{\n\t\t\treturn 'text/plain';\n\t\t}\n\t\telseif (preg_match('/[\\x00-\\x08\\x0E-\\x1A\\x1C-\\x1F]/', $this->file->body))\n\t\t{\n\t\t\treturn 'application/octect-stream';\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn 'text/plain';\n\t\t}\n\t}\n\n\t/**\n\t * Sniff unknown\n\t *\n\t * @return string Actual Content-Type\n\t */\n\tpublic function unknown()\n\t{\n\t\t$ws = strspn($this->file->body, \"\\x09\\x0A\\x0B\\x0C\\x0D\\x20\");\n\t\tif (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'\n\t\t\t|| strtolower(substr($this->file->body, $ws, 5)) === '<html'\n\t\t\t|| strtolower(substr($this->file->body, $ws, 7)) === '<script')\n\t\t{\n\t\t\treturn 'text/html';\n\t\t}\n\t\telseif (substr($this->file->body, 0, 5) === '%PDF-')\n\t\t{\n\t\t\treturn 'application/pdf';\n\t\t}\n\t\telseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')\n\t\t{\n\t\t\treturn 'application/postscript';\n\t\t}\n\t\telseif (substr($this->file->body, 0, 6) === 'GIF87a'\n\t\t\t|| substr($this->file->body, 0, 6) === 'GIF89a')\n\t\t{\n\t\t\treturn 'image/gif';\n\t\t}\n\t\telseif (substr($this->file->body, 0, 8) === \"\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A\")\n\t\t{\n\t\t\treturn 'image/png';\n\t\t}\n\t\telseif (substr($this->file->body, 0, 3) === \"\\xFF\\xD8\\xFF\")\n\t\t{\n\t\t\treturn 'image/jpeg';\n\t\t}\n\t\telseif (substr($this->file->body, 0, 2) === \"\\x42\\x4D\")\n\t\t{\n\t\t\treturn 'image/bmp';\n\t\t}\n\t\telseif (substr($this->file->body, 0, 4) === \"\\x00\\x00\\x01\\x00\")\n\t\t{\n\t\t\treturn 'image/vnd.microsoft.icon';\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn $this->text_or_binary();\n\t\t}\n\t}\n\n\t/**\n\t * Sniff images\n\t *\n\t * @return string Actual Content-Type\n\t */\n\tpublic function image()\n\t{\n\t\tif (substr($this->file->body, 0, 6) === 'GIF87a'\n\t\t\t|| substr($this->file->body, 0, 6) === 'GIF89a')\n\t\t{\n\t\t\treturn 'image/gif';\n\t\t}\n\t\telseif (substr($this->file->body, 0, 8) === \"\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A\")\n\t\t{\n\t\t\treturn 'image/png';\n\t\t}\n\t\telseif (substr($this->file->body, 0, 3) === \"\\xFF\\xD8\\xFF\")\n\t\t{\n\t\t\treturn 'image/jpeg';\n\t\t}\n\t\telseif (substr($this->file->body, 0, 2) === \"\\x42\\x4D\")\n\t\t{\n\t\t\treturn 'image/bmp';\n\t\t}\n\t\telseif (substr($this->file->body, 0, 4) === \"\\x00\\x00\\x01\\x00\")\n\t\t{\n\t\t\treturn 'image/vnd.microsoft.icon';\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Sniff HTML\n\t *\n\t * @return string Actual Content-Type\n\t */\n\tpublic function feed_or_html()\n\t{\n\t\t$len = strlen($this->file->body);\n\t\t$pos = strspn($this->file->body, \"\\x09\\x0A\\x0D\\x20\");\n\n\t\twhile ($pos < $len)\n\t\t{\n\t\t\tswitch ($this->file->body[$pos])\n\t\t\t{\n\t\t\t\tcase \"\\x09\":\n\t\t\t\tcase \"\\x0A\":\n\t\t\t\tcase \"\\x0D\":\n\t\t\t\tcase \"\\x20\":\n\t\t\t\t\t$pos += strspn($this->file->body, \"\\x09\\x0A\\x0D\\x20\", $pos);\n\t\t\t\t\tcontinue 2;\n\n\t\t\t\tcase '<':\n\t\t\t\t\t$pos++;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn 'text/html';\n\t\t\t}\n\n\t\t\tif (substr($this->file->body, $pos, 3) === '!--')\n\t\t\t{\n\t\t\t\t$pos += 3;\n\t\t\t\tif ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)\n\t\t\t\t{\n\t\t\t\t\t$pos += 3;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn 'text/html';\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif (substr($this->file->body, $pos, 1) === '!')\n\t\t\t{\n\t\t\t\tif ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)\n\t\t\t\t{\n\t\t\t\t\t$pos++;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn 'text/html';\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif (substr($this->file->body, $pos, 1) === '?')\n\t\t\t{\n\t\t\t\tif ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)\n\t\t\t\t{\n\t\t\t\t\t$pos += 2;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn 'text/html';\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif (substr($this->file->body, $pos, 3) === 'rss'\n\t\t\t\t|| substr($this->file->body, $pos, 7) === 'rdf:RDF')\n\t\t\t{\n\t\t\t\treturn 'application/rss+xml';\n\t\t\t}\n\t\t\telseif (substr($this->file->body, $pos, 4) === 'feed')\n\t\t\t{\n\t\t\t\treturn 'application/atom+xml';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn 'text/html';\n\t\t\t}\n\t\t}\n\n\t\treturn 'text/html';\n\t}\n}\n\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Copyright.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Manages `<media:copyright>` copyright tags as defined in Media RSS\n *\n * Used by {@see SimplePie_Enclosure::get_copyright()}\n *\n * This class can be overloaded with {@see SimplePie::set_copyright_class()}\n *\n * @package SimplePie\n * @subpackage API\n */\nclass SimplePie_Copyright\n{\n\t/**\n\t * Copyright URL\n\t *\n\t * @var string\n\t * @see get_url()\n\t */\n\tvar $url;\n\n\t/**\n\t * Attribution\n\t *\n\t * @var string\n\t * @see get_attribution()\n\t */\n\tvar $label;\n\n\t/**\n\t * Constructor, used to input the data\n\t *\n\t * For documentation on all the parameters, see the corresponding\n\t * properties and their accessors\n\t */\n\tpublic function __construct($url = null, $label = null)\n\t{\n\t\t$this->url = $url;\n\t\t$this->label = $label;\n\t}\n\n\t/**\n\t * String-ified version\n\t *\n\t * @return string\n\t */\n\tpublic function __toString()\n\t{\n\t\t// There is no $this->data here\n\t\treturn md5(serialize($this));\n\t}\n\n\t/**\n\t * Get the copyright URL\n\t *\n\t * @return string|null URL to copyright information\n\t */\n\tpublic function get_url()\n\t{\n\t\tif ($this->url !== null)\n\t\t{\n\t\t\treturn $this->url;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the attribution text\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_attribution()\n\t{\n\t\tif ($this->label !== null)\n\t\t{\n\t\t\treturn $this->label;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Core.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2009, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * SimplePie class.\n *\n * Class for backward compatibility.\n *\n * @deprecated Use {@see SimplePie} directly\n * @package SimplePie\n * @subpackage API\n */\nclass SimplePie_Core extends SimplePie\n{\n\n}"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Credit.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Handles `<media:credit>` as defined in Media RSS\n *\n * Used by {@see SimplePie_Enclosure::get_credit()} and {@see SimplePie_Enclosure::get_credits()}\n *\n * This class can be overloaded with {@see SimplePie::set_credit_class()}\n *\n * @package SimplePie\n * @subpackage API\n */\nclass SimplePie_Credit\n{\n\t/**\n\t * Credited role\n\t *\n\t * @var string\n\t * @see get_role()\n\t */\n\tvar $role;\n\n\t/**\n\t * Organizational scheme\n\t *\n\t * @var string\n\t * @see get_scheme()\n\t */\n\tvar $scheme;\n\n\t/**\n\t * Credited name\n\t *\n\t * @var string\n\t * @see get_name()\n\t */\n\tvar $name;\n\n\t/**\n\t * Constructor, used to input the data\n\t *\n\t * For documentation on all the parameters, see the corresponding\n\t * properties and their accessors\n\t */\n\tpublic function __construct($role = null, $scheme = null, $name = null)\n\t{\n\t\t$this->role = $role;\n\t\t$this->scheme = $scheme;\n\t\t$this->name = $name;\n\t}\n\n\t/**\n\t * String-ified version\n\t *\n\t * @return string\n\t */\n\tpublic function __toString()\n\t{\n\t\t// There is no $this->data here\n\t\treturn md5(serialize($this));\n\t}\n\n\t/**\n\t * Get the role of the person receiving credit\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_role()\n\t{\n\t\tif ($this->role !== null)\n\t\t{\n\t\t\treturn $this->role;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the organizational scheme\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_scheme()\n\t{\n\t\tif ($this->scheme !== null)\n\t\t{\n\t\t\treturn $this->scheme;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the credited person/entity's name\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_name()\n\t{\n\t\tif ($this->name !== null)\n\t\t{\n\t\t\treturn $this->name;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Decode/HTML/Entities.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n\n/**\n * Decode HTML Entities\n *\n * This implements HTML5 as of revision 967 (2007-06-28)\n *\n * @deprecated Use DOMDocument instead!\n * @package SimplePie\n */\nclass SimplePie_Decode_HTML_Entities\n{\n\t/**\n\t * Data to be parsed\n\t *\n\t * @access private\n\t * @var string\n\t */\n\tvar $data = '';\n\n\t/**\n\t * Currently consumed bytes\n\t *\n\t * @access private\n\t * @var string\n\t */\n\tvar $consumed = '';\n\n\t/**\n\t * Position of the current byte being parsed\n\t *\n\t * @access private\n\t * @var int\n\t */\n\tvar $position = 0;\n\n\t/**\n\t * Create an instance of the class with the input data\n\t *\n\t * @access public\n\t * @param string $data Input data\n\t */\n\tpublic function __construct($data)\n\t{\n\t\t$this->data = $data;\n\t}\n\n\t/**\n\t * Parse the input data\n\t *\n\t * @access public\n\t * @return string Output data\n\t */\n\tpublic function parse()\n\t{\n\t\twhile (($this->position = strpos($this->data, '&', $this->position)) !== false)\n\t\t{\n\t\t\t$this->consume();\n\t\t\t$this->entity();\n\t\t\t$this->consumed = '';\n\t\t}\n\t\treturn $this->data;\n\t}\n\n\t/**\n\t * Consume the next byte\n\t *\n\t * @access private\n\t * @return mixed The next byte, or false, if there is no more data\n\t */\n\tpublic function consume()\n\t{\n\t\tif (isset($this->data[$this->position]))\n\t\t{\n\t\t\t$this->consumed .= $this->data[$this->position];\n\t\t\treturn $this->data[$this->position++];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Consume a range of characters\n\t *\n\t * @access private\n\t * @param string $chars Characters to consume\n\t * @return mixed A series of characters that match the range, or false\n\t */\n\tpublic function consume_range($chars)\n\t{\n\t\tif ($len = strspn($this->data, $chars, $this->position))\n\t\t{\n\t\t\t$data = substr($this->data, $this->position, $len);\n\t\t\t$this->consumed .= $data;\n\t\t\t$this->position += $len;\n\t\t\treturn $data;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Unconsume one byte\n\t *\n\t * @access private\n\t */\n\tpublic function unconsume()\n\t{\n\t\t$this->consumed = substr($this->consumed, 0, -1);\n\t\t$this->position--;\n\t}\n\n\t/**\n\t * Decode an entity\n\t *\n\t * @access private\n\t */\n\tpublic function entity()\n\t{\n\t\tswitch ($this->consume())\n\t\t{\n\t\t\tcase \"\\x09\":\n\t\t\tcase \"\\x0A\":\n\t\t\tcase \"\\x0B\":\n\t\t\tcase \"\\x0B\":\n\t\t\tcase \"\\x0C\":\n\t\t\tcase \"\\x20\":\n\t\t\tcase \"\\x3C\":\n\t\t\tcase \"\\x26\":\n\t\t\tcase false:\n\t\t\t\tbreak;\n\n\t\t\tcase \"\\x23\":\n\t\t\t\tswitch ($this->consume())\n\t\t\t\t{\n\t\t\t\t\tcase \"\\x78\":\n\t\t\t\t\tcase \"\\x58\":\n\t\t\t\t\t\t$range = '0123456789ABCDEFabcdef';\n\t\t\t\t\t\t$hex = true;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t$range = '0123456789';\n\t\t\t\t\t\t$hex = false;\n\t\t\t\t\t\t$this->unconsume();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ($codepoint = $this->consume_range($range))\n\t\t\t\t{\n\t\t\t\t\tstatic $windows_1252_specials = array(0x0D => \"\\x0A\", 0x80 => \"\\xE2\\x82\\xAC\", 0x81 => \"\\xEF\\xBF\\xBD\", 0x82 => \"\\xE2\\x80\\x9A\", 0x83 => \"\\xC6\\x92\", 0x84 => \"\\xE2\\x80\\x9E\", 0x85 => \"\\xE2\\x80\\xA6\", 0x86 => \"\\xE2\\x80\\xA0\", 0x87 => \"\\xE2\\x80\\xA1\", 0x88 => \"\\xCB\\x86\", 0x89 => \"\\xE2\\x80\\xB0\", 0x8A => \"\\xC5\\xA0\", 0x8B => \"\\xE2\\x80\\xB9\", 0x8C => \"\\xC5\\x92\", 0x8D => \"\\xEF\\xBF\\xBD\", 0x8E => \"\\xC5\\xBD\", 0x8F => \"\\xEF\\xBF\\xBD\", 0x90 => \"\\xEF\\xBF\\xBD\", 0x91 => \"\\xE2\\x80\\x98\", 0x92 => \"\\xE2\\x80\\x99\", 0x93 => \"\\xE2\\x80\\x9C\", 0x94 => \"\\xE2\\x80\\x9D\", 0x95 => \"\\xE2\\x80\\xA2\", 0x96 => \"\\xE2\\x80\\x93\", 0x97 => \"\\xE2\\x80\\x94\", 0x98 => \"\\xCB\\x9C\", 0x99 => \"\\xE2\\x84\\xA2\", 0x9A => \"\\xC5\\xA1\", 0x9B => \"\\xE2\\x80\\xBA\", 0x9C => \"\\xC5\\x93\", 0x9D => \"\\xEF\\xBF\\xBD\", 0x9E => \"\\xC5\\xBE\", 0x9F => \"\\xC5\\xB8\");\n\n\t\t\t\t\tif ($hex)\n\t\t\t\t\t{\n\t\t\t\t\t\t$codepoint = hexdec($codepoint);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$codepoint = intval($codepoint);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (isset($windows_1252_specials[$codepoint]))\n\t\t\t\t\t{\n\t\t\t\t\t\t$replacement = $windows_1252_specials[$codepoint];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!in_array($this->consume(), array(';', false), true))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->unconsume();\n\t\t\t\t\t}\n\n\t\t\t\t\t$consumed_length = strlen($this->consumed);\n\t\t\t\t\t$this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);\n\t\t\t\t\t$this->position += strlen($replacement) - $consumed_length;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tstatic $entities = array(\n\t\t\t\t\t'Aacute' => \"\\xC3\\x81\",\n\t\t\t\t\t'aacute' => \"\\xC3\\xA1\",\n\t\t\t\t\t'Aacute;' => \"\\xC3\\x81\",\n\t\t\t\t\t'aacute;' => \"\\xC3\\xA1\",\n\t\t\t\t\t'Acirc' => \"\\xC3\\x82\",\n\t\t\t\t\t'acirc' => \"\\xC3\\xA2\",\n\t\t\t\t\t'Acirc;' => \"\\xC3\\x82\",\n\t\t\t\t\t'acirc;' => \"\\xC3\\xA2\",\n\t\t\t\t\t'acute' => \"\\xC2\\xB4\",\n\t\t\t\t\t'acute;' => \"\\xC2\\xB4\",\n\t\t\t\t\t'AElig' => \"\\xC3\\x86\",\n\t\t\t\t\t'aelig' => \"\\xC3\\xA6\",\n\t\t\t\t\t'AElig;' => \"\\xC3\\x86\",\n\t\t\t\t\t'aelig;' => \"\\xC3\\xA6\",\n\t\t\t\t\t'Agrave' => \"\\xC3\\x80\",\n\t\t\t\t\t'agrave' => \"\\xC3\\xA0\",\n\t\t\t\t\t'Agrave;' => \"\\xC3\\x80\",\n\t\t\t\t\t'agrave;' => \"\\xC3\\xA0\",\n\t\t\t\t\t'alefsym;' => \"\\xE2\\x84\\xB5\",\n\t\t\t\t\t'Alpha;' => \"\\xCE\\x91\",\n\t\t\t\t\t'alpha;' => \"\\xCE\\xB1\",\n\t\t\t\t\t'AMP' => \"\\x26\",\n\t\t\t\t\t'amp' => \"\\x26\",\n\t\t\t\t\t'AMP;' => \"\\x26\",\n\t\t\t\t\t'amp;' => \"\\x26\",\n\t\t\t\t\t'and;' => \"\\xE2\\x88\\xA7\",\n\t\t\t\t\t'ang;' => \"\\xE2\\x88\\xA0\",\n\t\t\t\t\t'apos;' => \"\\x27\",\n\t\t\t\t\t'Aring' => \"\\xC3\\x85\",\n\t\t\t\t\t'aring' => \"\\xC3\\xA5\",\n\t\t\t\t\t'Aring;' => \"\\xC3\\x85\",\n\t\t\t\t\t'aring;' => \"\\xC3\\xA5\",\n\t\t\t\t\t'asymp;' => \"\\xE2\\x89\\x88\",\n\t\t\t\t\t'Atilde' => \"\\xC3\\x83\",\n\t\t\t\t\t'atilde' => \"\\xC3\\xA3\",\n\t\t\t\t\t'Atilde;' => \"\\xC3\\x83\",\n\t\t\t\t\t'atilde;' => \"\\xC3\\xA3\",\n\t\t\t\t\t'Auml' => \"\\xC3\\x84\",\n\t\t\t\t\t'auml' => \"\\xC3\\xA4\",\n\t\t\t\t\t'Auml;' => \"\\xC3\\x84\",\n\t\t\t\t\t'auml;' => \"\\xC3\\xA4\",\n\t\t\t\t\t'bdquo;' => \"\\xE2\\x80\\x9E\",\n\t\t\t\t\t'Beta;' => \"\\xCE\\x92\",\n\t\t\t\t\t'beta;' => \"\\xCE\\xB2\",\n\t\t\t\t\t'brvbar' => \"\\xC2\\xA6\",\n\t\t\t\t\t'brvbar;' => \"\\xC2\\xA6\",\n\t\t\t\t\t'bull;' => \"\\xE2\\x80\\xA2\",\n\t\t\t\t\t'cap;' => \"\\xE2\\x88\\xA9\",\n\t\t\t\t\t'Ccedil' => \"\\xC3\\x87\",\n\t\t\t\t\t'ccedil' => \"\\xC3\\xA7\",\n\t\t\t\t\t'Ccedil;' => \"\\xC3\\x87\",\n\t\t\t\t\t'ccedil;' => \"\\xC3\\xA7\",\n\t\t\t\t\t'cedil' => \"\\xC2\\xB8\",\n\t\t\t\t\t'cedil;' => \"\\xC2\\xB8\",\n\t\t\t\t\t'cent' => \"\\xC2\\xA2\",\n\t\t\t\t\t'cent;' => \"\\xC2\\xA2\",\n\t\t\t\t\t'Chi;' => \"\\xCE\\xA7\",\n\t\t\t\t\t'chi;' => \"\\xCF\\x87\",\n\t\t\t\t\t'circ;' => \"\\xCB\\x86\",\n\t\t\t\t\t'clubs;' => \"\\xE2\\x99\\xA3\",\n\t\t\t\t\t'cong;' => \"\\xE2\\x89\\x85\",\n\t\t\t\t\t'COPY' => \"\\xC2\\xA9\",\n\t\t\t\t\t'copy' => \"\\xC2\\xA9\",\n\t\t\t\t\t'COPY;' => \"\\xC2\\xA9\",\n\t\t\t\t\t'copy;' => \"\\xC2\\xA9\",\n\t\t\t\t\t'crarr;' => \"\\xE2\\x86\\xB5\",\n\t\t\t\t\t'cup;' => \"\\xE2\\x88\\xAA\",\n\t\t\t\t\t'curren' => \"\\xC2\\xA4\",\n\t\t\t\t\t'curren;' => \"\\xC2\\xA4\",\n\t\t\t\t\t'Dagger;' => \"\\xE2\\x80\\xA1\",\n\t\t\t\t\t'dagger;' => \"\\xE2\\x80\\xA0\",\n\t\t\t\t\t'dArr;' => \"\\xE2\\x87\\x93\",\n\t\t\t\t\t'darr;' => \"\\xE2\\x86\\x93\",\n\t\t\t\t\t'deg' => \"\\xC2\\xB0\",\n\t\t\t\t\t'deg;' => \"\\xC2\\xB0\",\n\t\t\t\t\t'Delta;' => \"\\xCE\\x94\",\n\t\t\t\t\t'delta;' => \"\\xCE\\xB4\",\n\t\t\t\t\t'diams;' => \"\\xE2\\x99\\xA6\",\n\t\t\t\t\t'divide' => \"\\xC3\\xB7\",\n\t\t\t\t\t'divide;' => \"\\xC3\\xB7\",\n\t\t\t\t\t'Eacute' => \"\\xC3\\x89\",\n\t\t\t\t\t'eacute' => \"\\xC3\\xA9\",\n\t\t\t\t\t'Eacute;' => \"\\xC3\\x89\",\n\t\t\t\t\t'eacute;' => \"\\xC3\\xA9\",\n\t\t\t\t\t'Ecirc' => \"\\xC3\\x8A\",\n\t\t\t\t\t'ecirc' => \"\\xC3\\xAA\",\n\t\t\t\t\t'Ecirc;' => \"\\xC3\\x8A\",\n\t\t\t\t\t'ecirc;' => \"\\xC3\\xAA\",\n\t\t\t\t\t'Egrave' => \"\\xC3\\x88\",\n\t\t\t\t\t'egrave' => \"\\xC3\\xA8\",\n\t\t\t\t\t'Egrave;' => \"\\xC3\\x88\",\n\t\t\t\t\t'egrave;' => \"\\xC3\\xA8\",\n\t\t\t\t\t'empty;' => \"\\xE2\\x88\\x85\",\n\t\t\t\t\t'emsp;' => \"\\xE2\\x80\\x83\",\n\t\t\t\t\t'ensp;' => \"\\xE2\\x80\\x82\",\n\t\t\t\t\t'Epsilon;' => \"\\xCE\\x95\",\n\t\t\t\t\t'epsilon;' => \"\\xCE\\xB5\",\n\t\t\t\t\t'equiv;' => \"\\xE2\\x89\\xA1\",\n\t\t\t\t\t'Eta;' => \"\\xCE\\x97\",\n\t\t\t\t\t'eta;' => \"\\xCE\\xB7\",\n\t\t\t\t\t'ETH' => \"\\xC3\\x90\",\n\t\t\t\t\t'eth' => \"\\xC3\\xB0\",\n\t\t\t\t\t'ETH;' => \"\\xC3\\x90\",\n\t\t\t\t\t'eth;' => \"\\xC3\\xB0\",\n\t\t\t\t\t'Euml' => \"\\xC3\\x8B\",\n\t\t\t\t\t'euml' => \"\\xC3\\xAB\",\n\t\t\t\t\t'Euml;' => \"\\xC3\\x8B\",\n\t\t\t\t\t'euml;' => \"\\xC3\\xAB\",\n\t\t\t\t\t'euro;' => \"\\xE2\\x82\\xAC\",\n\t\t\t\t\t'exist;' => \"\\xE2\\x88\\x83\",\n\t\t\t\t\t'fnof;' => \"\\xC6\\x92\",\n\t\t\t\t\t'forall;' => \"\\xE2\\x88\\x80\",\n\t\t\t\t\t'frac12' => \"\\xC2\\xBD\",\n\t\t\t\t\t'frac12;' => \"\\xC2\\xBD\",\n\t\t\t\t\t'frac14' => \"\\xC2\\xBC\",\n\t\t\t\t\t'frac14;' => \"\\xC2\\xBC\",\n\t\t\t\t\t'frac34' => \"\\xC2\\xBE\",\n\t\t\t\t\t'frac34;' => \"\\xC2\\xBE\",\n\t\t\t\t\t'frasl;' => \"\\xE2\\x81\\x84\",\n\t\t\t\t\t'Gamma;' => \"\\xCE\\x93\",\n\t\t\t\t\t'gamma;' => \"\\xCE\\xB3\",\n\t\t\t\t\t'ge;' => \"\\xE2\\x89\\xA5\",\n\t\t\t\t\t'GT' => \"\\x3E\",\n\t\t\t\t\t'gt' => \"\\x3E\",\n\t\t\t\t\t'GT;' => \"\\x3E\",\n\t\t\t\t\t'gt;' => \"\\x3E\",\n\t\t\t\t\t'hArr;' => \"\\xE2\\x87\\x94\",\n\t\t\t\t\t'harr;' => \"\\xE2\\x86\\x94\",\n\t\t\t\t\t'hearts;' => \"\\xE2\\x99\\xA5\",\n\t\t\t\t\t'hellip;' => \"\\xE2\\x80\\xA6\",\n\t\t\t\t\t'Iacute' => \"\\xC3\\x8D\",\n\t\t\t\t\t'iacute' => \"\\xC3\\xAD\",\n\t\t\t\t\t'Iacute;' => \"\\xC3\\x8D\",\n\t\t\t\t\t'iacute;' => \"\\xC3\\xAD\",\n\t\t\t\t\t'Icirc' => \"\\xC3\\x8E\",\n\t\t\t\t\t'icirc' => \"\\xC3\\xAE\",\n\t\t\t\t\t'Icirc;' => \"\\xC3\\x8E\",\n\t\t\t\t\t'icirc;' => \"\\xC3\\xAE\",\n\t\t\t\t\t'iexcl' => \"\\xC2\\xA1\",\n\t\t\t\t\t'iexcl;' => \"\\xC2\\xA1\",\n\t\t\t\t\t'Igrave' => \"\\xC3\\x8C\",\n\t\t\t\t\t'igrave' => \"\\xC3\\xAC\",\n\t\t\t\t\t'Igrave;' => \"\\xC3\\x8C\",\n\t\t\t\t\t'igrave;' => \"\\xC3\\xAC\",\n\t\t\t\t\t'image;' => \"\\xE2\\x84\\x91\",\n\t\t\t\t\t'infin;' => \"\\xE2\\x88\\x9E\",\n\t\t\t\t\t'int;' => \"\\xE2\\x88\\xAB\",\n\t\t\t\t\t'Iota;' => \"\\xCE\\x99\",\n\t\t\t\t\t'iota;' => \"\\xCE\\xB9\",\n\t\t\t\t\t'iquest' => \"\\xC2\\xBF\",\n\t\t\t\t\t'iquest;' => \"\\xC2\\xBF\",\n\t\t\t\t\t'isin;' => \"\\xE2\\x88\\x88\",\n\t\t\t\t\t'Iuml' => \"\\xC3\\x8F\",\n\t\t\t\t\t'iuml' => \"\\xC3\\xAF\",\n\t\t\t\t\t'Iuml;' => \"\\xC3\\x8F\",\n\t\t\t\t\t'iuml;' => \"\\xC3\\xAF\",\n\t\t\t\t\t'Kappa;' => \"\\xCE\\x9A\",\n\t\t\t\t\t'kappa;' => \"\\xCE\\xBA\",\n\t\t\t\t\t'Lambda;' => \"\\xCE\\x9B\",\n\t\t\t\t\t'lambda;' => \"\\xCE\\xBB\",\n\t\t\t\t\t'lang;' => \"\\xE3\\x80\\x88\",\n\t\t\t\t\t'laquo' => \"\\xC2\\xAB\",\n\t\t\t\t\t'laquo;' => \"\\xC2\\xAB\",\n\t\t\t\t\t'lArr;' => \"\\xE2\\x87\\x90\",\n\t\t\t\t\t'larr;' => \"\\xE2\\x86\\x90\",\n\t\t\t\t\t'lceil;' => \"\\xE2\\x8C\\x88\",\n\t\t\t\t\t'ldquo;' => \"\\xE2\\x80\\x9C\",\n\t\t\t\t\t'le;' => \"\\xE2\\x89\\xA4\",\n\t\t\t\t\t'lfloor;' => \"\\xE2\\x8C\\x8A\",\n\t\t\t\t\t'lowast;' => \"\\xE2\\x88\\x97\",\n\t\t\t\t\t'loz;' => \"\\xE2\\x97\\x8A\",\n\t\t\t\t\t'lrm;' => \"\\xE2\\x80\\x8E\",\n\t\t\t\t\t'lsaquo;' => \"\\xE2\\x80\\xB9\",\n\t\t\t\t\t'lsquo;' => \"\\xE2\\x80\\x98\",\n\t\t\t\t\t'LT' => \"\\x3C\",\n\t\t\t\t\t'lt' => \"\\x3C\",\n\t\t\t\t\t'LT;' => \"\\x3C\",\n\t\t\t\t\t'lt;' => \"\\x3C\",\n\t\t\t\t\t'macr' => \"\\xC2\\xAF\",\n\t\t\t\t\t'macr;' => \"\\xC2\\xAF\",\n\t\t\t\t\t'mdash;' => \"\\xE2\\x80\\x94\",\n\t\t\t\t\t'micro' => \"\\xC2\\xB5\",\n\t\t\t\t\t'micro;' => \"\\xC2\\xB5\",\n\t\t\t\t\t'middot' => \"\\xC2\\xB7\",\n\t\t\t\t\t'middot;' => \"\\xC2\\xB7\",\n\t\t\t\t\t'minus;' => \"\\xE2\\x88\\x92\",\n\t\t\t\t\t'Mu;' => \"\\xCE\\x9C\",\n\t\t\t\t\t'mu;' => \"\\xCE\\xBC\",\n\t\t\t\t\t'nabla;' => \"\\xE2\\x88\\x87\",\n\t\t\t\t\t'nbsp' => \"\\xC2\\xA0\",\n\t\t\t\t\t'nbsp;' => \"\\xC2\\xA0\",\n\t\t\t\t\t'ndash;' => \"\\xE2\\x80\\x93\",\n\t\t\t\t\t'ne;' => \"\\xE2\\x89\\xA0\",\n\t\t\t\t\t'ni;' => \"\\xE2\\x88\\x8B\",\n\t\t\t\t\t'not' => \"\\xC2\\xAC\",\n\t\t\t\t\t'not;' => \"\\xC2\\xAC\",\n\t\t\t\t\t'notin;' => \"\\xE2\\x88\\x89\",\n\t\t\t\t\t'nsub;' => \"\\xE2\\x8A\\x84\",\n\t\t\t\t\t'Ntilde' => \"\\xC3\\x91\",\n\t\t\t\t\t'ntilde' => \"\\xC3\\xB1\",\n\t\t\t\t\t'Ntilde;' => \"\\xC3\\x91\",\n\t\t\t\t\t'ntilde;' => \"\\xC3\\xB1\",\n\t\t\t\t\t'Nu;' => \"\\xCE\\x9D\",\n\t\t\t\t\t'nu;' => \"\\xCE\\xBD\",\n\t\t\t\t\t'Oacute' => \"\\xC3\\x93\",\n\t\t\t\t\t'oacute' => \"\\xC3\\xB3\",\n\t\t\t\t\t'Oacute;' => \"\\xC3\\x93\",\n\t\t\t\t\t'oacute;' => \"\\xC3\\xB3\",\n\t\t\t\t\t'Ocirc' => \"\\xC3\\x94\",\n\t\t\t\t\t'ocirc' => \"\\xC3\\xB4\",\n\t\t\t\t\t'Ocirc;' => \"\\xC3\\x94\",\n\t\t\t\t\t'ocirc;' => \"\\xC3\\xB4\",\n\t\t\t\t\t'OElig;' => \"\\xC5\\x92\",\n\t\t\t\t\t'oelig;' => \"\\xC5\\x93\",\n\t\t\t\t\t'Ograve' => \"\\xC3\\x92\",\n\t\t\t\t\t'ograve' => \"\\xC3\\xB2\",\n\t\t\t\t\t'Ograve;' => \"\\xC3\\x92\",\n\t\t\t\t\t'ograve;' => \"\\xC3\\xB2\",\n\t\t\t\t\t'oline;' => \"\\xE2\\x80\\xBE\",\n\t\t\t\t\t'Omega;' => \"\\xCE\\xA9\",\n\t\t\t\t\t'omega;' => \"\\xCF\\x89\",\n\t\t\t\t\t'Omicron;' => \"\\xCE\\x9F\",\n\t\t\t\t\t'omicron;' => \"\\xCE\\xBF\",\n\t\t\t\t\t'oplus;' => \"\\xE2\\x8A\\x95\",\n\t\t\t\t\t'or;' => \"\\xE2\\x88\\xA8\",\n\t\t\t\t\t'ordf' => \"\\xC2\\xAA\",\n\t\t\t\t\t'ordf;' => \"\\xC2\\xAA\",\n\t\t\t\t\t'ordm' => \"\\xC2\\xBA\",\n\t\t\t\t\t'ordm;' => \"\\xC2\\xBA\",\n\t\t\t\t\t'Oslash' => \"\\xC3\\x98\",\n\t\t\t\t\t'oslash' => \"\\xC3\\xB8\",\n\t\t\t\t\t'Oslash;' => \"\\xC3\\x98\",\n\t\t\t\t\t'oslash;' => \"\\xC3\\xB8\",\n\t\t\t\t\t'Otilde' => \"\\xC3\\x95\",\n\t\t\t\t\t'otilde' => \"\\xC3\\xB5\",\n\t\t\t\t\t'Otilde;' => \"\\xC3\\x95\",\n\t\t\t\t\t'otilde;' => \"\\xC3\\xB5\",\n\t\t\t\t\t'otimes;' => \"\\xE2\\x8A\\x97\",\n\t\t\t\t\t'Ouml' => \"\\xC3\\x96\",\n\t\t\t\t\t'ouml' => \"\\xC3\\xB6\",\n\t\t\t\t\t'Ouml;' => \"\\xC3\\x96\",\n\t\t\t\t\t'ouml;' => \"\\xC3\\xB6\",\n\t\t\t\t\t'para' => \"\\xC2\\xB6\",\n\t\t\t\t\t'para;' => \"\\xC2\\xB6\",\n\t\t\t\t\t'part;' => \"\\xE2\\x88\\x82\",\n\t\t\t\t\t'permil;' => \"\\xE2\\x80\\xB0\",\n\t\t\t\t\t'perp;' => \"\\xE2\\x8A\\xA5\",\n\t\t\t\t\t'Phi;' => \"\\xCE\\xA6\",\n\t\t\t\t\t'phi;' => \"\\xCF\\x86\",\n\t\t\t\t\t'Pi;' => \"\\xCE\\xA0\",\n\t\t\t\t\t'pi;' => \"\\xCF\\x80\",\n\t\t\t\t\t'piv;' => \"\\xCF\\x96\",\n\t\t\t\t\t'plusmn' => \"\\xC2\\xB1\",\n\t\t\t\t\t'plusmn;' => \"\\xC2\\xB1\",\n\t\t\t\t\t'pound' => \"\\xC2\\xA3\",\n\t\t\t\t\t'pound;' => \"\\xC2\\xA3\",\n\t\t\t\t\t'Prime;' => \"\\xE2\\x80\\xB3\",\n\t\t\t\t\t'prime;' => \"\\xE2\\x80\\xB2\",\n\t\t\t\t\t'prod;' => \"\\xE2\\x88\\x8F\",\n\t\t\t\t\t'prop;' => \"\\xE2\\x88\\x9D\",\n\t\t\t\t\t'Psi;' => \"\\xCE\\xA8\",\n\t\t\t\t\t'psi;' => \"\\xCF\\x88\",\n\t\t\t\t\t'QUOT' => \"\\x22\",\n\t\t\t\t\t'quot' => \"\\x22\",\n\t\t\t\t\t'QUOT;' => \"\\x22\",\n\t\t\t\t\t'quot;' => \"\\x22\",\n\t\t\t\t\t'radic;' => \"\\xE2\\x88\\x9A\",\n\t\t\t\t\t'rang;' => \"\\xE3\\x80\\x89\",\n\t\t\t\t\t'raquo' => \"\\xC2\\xBB\",\n\t\t\t\t\t'raquo;' => \"\\xC2\\xBB\",\n\t\t\t\t\t'rArr;' => \"\\xE2\\x87\\x92\",\n\t\t\t\t\t'rarr;' => \"\\xE2\\x86\\x92\",\n\t\t\t\t\t'rceil;' => \"\\xE2\\x8C\\x89\",\n\t\t\t\t\t'rdquo;' => \"\\xE2\\x80\\x9D\",\n\t\t\t\t\t'real;' => \"\\xE2\\x84\\x9C\",\n\t\t\t\t\t'REG' => \"\\xC2\\xAE\",\n\t\t\t\t\t'reg' => \"\\xC2\\xAE\",\n\t\t\t\t\t'REG;' => \"\\xC2\\xAE\",\n\t\t\t\t\t'reg;' => \"\\xC2\\xAE\",\n\t\t\t\t\t'rfloor;' => \"\\xE2\\x8C\\x8B\",\n\t\t\t\t\t'Rho;' => \"\\xCE\\xA1\",\n\t\t\t\t\t'rho;' => \"\\xCF\\x81\",\n\t\t\t\t\t'rlm;' => \"\\xE2\\x80\\x8F\",\n\t\t\t\t\t'rsaquo;' => \"\\xE2\\x80\\xBA\",\n\t\t\t\t\t'rsquo;' => \"\\xE2\\x80\\x99\",\n\t\t\t\t\t'sbquo;' => \"\\xE2\\x80\\x9A\",\n\t\t\t\t\t'Scaron;' => \"\\xC5\\xA0\",\n\t\t\t\t\t'scaron;' => \"\\xC5\\xA1\",\n\t\t\t\t\t'sdot;' => \"\\xE2\\x8B\\x85\",\n\t\t\t\t\t'sect' => \"\\xC2\\xA7\",\n\t\t\t\t\t'sect;' => \"\\xC2\\xA7\",\n\t\t\t\t\t'shy' => \"\\xC2\\xAD\",\n\t\t\t\t\t'shy;' => \"\\xC2\\xAD\",\n\t\t\t\t\t'Sigma;' => \"\\xCE\\xA3\",\n\t\t\t\t\t'sigma;' => \"\\xCF\\x83\",\n\t\t\t\t\t'sigmaf;' => \"\\xCF\\x82\",\n\t\t\t\t\t'sim;' => \"\\xE2\\x88\\xBC\",\n\t\t\t\t\t'spades;' => \"\\xE2\\x99\\xA0\",\n\t\t\t\t\t'sub;' => \"\\xE2\\x8A\\x82\",\n\t\t\t\t\t'sube;' => \"\\xE2\\x8A\\x86\",\n\t\t\t\t\t'sum;' => \"\\xE2\\x88\\x91\",\n\t\t\t\t\t'sup;' => \"\\xE2\\x8A\\x83\",\n\t\t\t\t\t'sup1' => \"\\xC2\\xB9\",\n\t\t\t\t\t'sup1;' => \"\\xC2\\xB9\",\n\t\t\t\t\t'sup2' => \"\\xC2\\xB2\",\n\t\t\t\t\t'sup2;' => \"\\xC2\\xB2\",\n\t\t\t\t\t'sup3' => \"\\xC2\\xB3\",\n\t\t\t\t\t'sup3;' => \"\\xC2\\xB3\",\n\t\t\t\t\t'supe;' => \"\\xE2\\x8A\\x87\",\n\t\t\t\t\t'szlig' => \"\\xC3\\x9F\",\n\t\t\t\t\t'szlig;' => \"\\xC3\\x9F\",\n\t\t\t\t\t'Tau;' => \"\\xCE\\xA4\",\n\t\t\t\t\t'tau;' => \"\\xCF\\x84\",\n\t\t\t\t\t'there4;' => \"\\xE2\\x88\\xB4\",\n\t\t\t\t\t'Theta;' => \"\\xCE\\x98\",\n\t\t\t\t\t'theta;' => \"\\xCE\\xB8\",\n\t\t\t\t\t'thetasym;' => \"\\xCF\\x91\",\n\t\t\t\t\t'thinsp;' => \"\\xE2\\x80\\x89\",\n\t\t\t\t\t'THORN' => \"\\xC3\\x9E\",\n\t\t\t\t\t'thorn' => \"\\xC3\\xBE\",\n\t\t\t\t\t'THORN;' => \"\\xC3\\x9E\",\n\t\t\t\t\t'thorn;' => \"\\xC3\\xBE\",\n\t\t\t\t\t'tilde;' => \"\\xCB\\x9C\",\n\t\t\t\t\t'times' => \"\\xC3\\x97\",\n\t\t\t\t\t'times;' => \"\\xC3\\x97\",\n\t\t\t\t\t'TRADE;' => \"\\xE2\\x84\\xA2\",\n\t\t\t\t\t'trade;' => \"\\xE2\\x84\\xA2\",\n\t\t\t\t\t'Uacute' => \"\\xC3\\x9A\",\n\t\t\t\t\t'uacute' => \"\\xC3\\xBA\",\n\t\t\t\t\t'Uacute;' => \"\\xC3\\x9A\",\n\t\t\t\t\t'uacute;' => \"\\xC3\\xBA\",\n\t\t\t\t\t'uArr;' => \"\\xE2\\x87\\x91\",\n\t\t\t\t\t'uarr;' => \"\\xE2\\x86\\x91\",\n\t\t\t\t\t'Ucirc' => \"\\xC3\\x9B\",\n\t\t\t\t\t'ucirc' => \"\\xC3\\xBB\",\n\t\t\t\t\t'Ucirc;' => \"\\xC3\\x9B\",\n\t\t\t\t\t'ucirc;' => \"\\xC3\\xBB\",\n\t\t\t\t\t'Ugrave' => \"\\xC3\\x99\",\n\t\t\t\t\t'ugrave' => \"\\xC3\\xB9\",\n\t\t\t\t\t'Ugrave;' => \"\\xC3\\x99\",\n\t\t\t\t\t'ugrave;' => \"\\xC3\\xB9\",\n\t\t\t\t\t'uml' => \"\\xC2\\xA8\",\n\t\t\t\t\t'uml;' => \"\\xC2\\xA8\",\n\t\t\t\t\t'upsih;' => \"\\xCF\\x92\",\n\t\t\t\t\t'Upsilon;' => \"\\xCE\\xA5\",\n\t\t\t\t\t'upsilon;' => \"\\xCF\\x85\",\n\t\t\t\t\t'Uuml' => \"\\xC3\\x9C\",\n\t\t\t\t\t'uuml' => \"\\xC3\\xBC\",\n\t\t\t\t\t'Uuml;' => \"\\xC3\\x9C\",\n\t\t\t\t\t'uuml;' => \"\\xC3\\xBC\",\n\t\t\t\t\t'weierp;' => \"\\xE2\\x84\\x98\",\n\t\t\t\t\t'Xi;' => \"\\xCE\\x9E\",\n\t\t\t\t\t'xi;' => \"\\xCE\\xBE\",\n\t\t\t\t\t'Yacute' => \"\\xC3\\x9D\",\n\t\t\t\t\t'yacute' => \"\\xC3\\xBD\",\n\t\t\t\t\t'Yacute;' => \"\\xC3\\x9D\",\n\t\t\t\t\t'yacute;' => \"\\xC3\\xBD\",\n\t\t\t\t\t'yen' => \"\\xC2\\xA5\",\n\t\t\t\t\t'yen;' => \"\\xC2\\xA5\",\n\t\t\t\t\t'yuml' => \"\\xC3\\xBF\",\n\t\t\t\t\t'Yuml;' => \"\\xC5\\xB8\",\n\t\t\t\t\t'yuml;' => \"\\xC3\\xBF\",\n\t\t\t\t\t'Zeta;' => \"\\xCE\\x96\",\n\t\t\t\t\t'zeta;' => \"\\xCE\\xB6\",\n\t\t\t\t\t'zwj;' => \"\\xE2\\x80\\x8D\",\n\t\t\t\t\t'zwnj;' => \"\\xE2\\x80\\x8C\"\n\t\t\t\t);\n\n\t\t\t\tfor ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)\n\t\t\t\t{\n\t\t\t\t\t$consumed = substr($this->consumed, 1);\n\t\t\t\t\tif (isset($entities[$consumed]))\n\t\t\t\t\t{\n\t\t\t\t\t\t$match = $consumed;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ($match !== null)\n\t\t\t\t{\n \t\t\t\t\t$this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);\n\t\t\t\t\t$this->position += strlen($entities[$match]) - strlen($consumed) - 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Enclosure.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Handles everything related to enclosures (including Media RSS and iTunes RSS)\n *\n * Used by {@see SimplePie_Item::get_enclosure()} and {@see SimplePie_Item::get_enclosures()}\n *\n * This class can be overloaded with {@see SimplePie::set_enclosure_class()}\n *\n * @package SimplePie\n * @subpackage API\n */\nclass SimplePie_Enclosure\n{\n\t/**\n\t * @var string\n\t * @see get_bitrate()\n\t */\n\tvar $bitrate;\n\n\t/**\n\t * @var array\n\t * @see get_captions()\n\t */\n\tvar $captions;\n\n\t/**\n\t * @var array\n\t * @see get_categories()\n\t */\n\tvar $categories;\n\n\t/**\n\t * @var int\n\t * @see get_channels()\n\t */\n\tvar $channels;\n\n\t/**\n\t * @var SimplePie_Copyright\n\t * @see get_copyright()\n\t */\n\tvar $copyright;\n\n\t/**\n\t * @var array\n\t * @see get_credits()\n\t */\n\tvar $credits;\n\n\t/**\n\t * @var string\n\t * @see get_description()\n\t */\n\tvar $description;\n\n\t/**\n\t * @var int\n\t * @see get_duration()\n\t */\n\tvar $duration;\n\n\t/**\n\t * @var string\n\t * @see get_expression()\n\t */\n\tvar $expression;\n\n\t/**\n\t * @var string\n\t * @see get_framerate()\n\t */\n\tvar $framerate;\n\n\t/**\n\t * @var string\n\t * @see get_handler()\n\t */\n\tvar $handler;\n\n\t/**\n\t * @var array\n\t * @see get_hashes()\n\t */\n\tvar $hashes;\n\n\t/**\n\t * @var string\n\t * @see get_height()\n\t */\n\tvar $height;\n\n\t/**\n\t * @deprecated\n\t * @var null\n\t */\n\tvar $javascript;\n\n\t/**\n\t * @var array\n\t * @see get_keywords()\n\t */\n\tvar $keywords;\n\n\t/**\n\t * @var string\n\t * @see get_language()\n\t */\n\tvar $lang;\n\n\t/**\n\t * @var string\n\t * @see get_length()\n\t */\n\tvar $length;\n\n\t/**\n\t * @var string\n\t * @see get_link()\n\t */\n\tvar $link;\n\n\t/**\n\t * @var string\n\t * @see get_medium()\n\t */\n\tvar $medium;\n\n\t/**\n\t * @var string\n\t * @see get_player()\n\t */\n\tvar $player;\n\n\t/**\n\t * @var array\n\t * @see get_ratings()\n\t */\n\tvar $ratings;\n\n\t/**\n\t * @var array\n\t * @see get_restrictions()\n\t */\n\tvar $restrictions;\n\n\t/**\n\t * @var string\n\t * @see get_sampling_rate()\n\t */\n\tvar $samplingrate;\n\n\t/**\n\t * @var array\n\t * @see get_thumbnails()\n\t */\n\tvar $thumbnails;\n\n\t/**\n\t * @var string\n\t * @see get_title()\n\t */\n\tvar $title;\n\n\t/**\n\t * @var string\n\t * @see get_type()\n\t */\n\tvar $type;\n\n\t/**\n\t * @var string\n\t * @see get_width()\n\t */\n\tvar $width;\n\n\t/**\n\t * Constructor, used to input the data\n\t *\n\t * For documentation on all the parameters, see the corresponding\n\t * properties and their accessors\n\t *\n\t * @uses idna_convert If available, this will convert an IDN\n\t */\n\tpublic function __construct($link = null, $type = null, $length = null, $javascript = null, $bitrate = null, $captions = null, $categories = null, $channels = null, $copyright = null, $credits = null, $description = null, $duration = null, $expression = null, $framerate = null, $hashes = null, $height = null, $keywords = null, $lang = null, $medium = null, $player = null, $ratings = null, $restrictions = null, $samplingrate = null, $thumbnails = null, $title = null, $width = null)\n\t{\n\t\t$this->bitrate = $bitrate;\n\t\t$this->captions = $captions;\n\t\t$this->categories = $categories;\n\t\t$this->channels = $channels;\n\t\t$this->copyright = $copyright;\n\t\t$this->credits = $credits;\n\t\t$this->description = $description;\n\t\t$this->duration = $duration;\n\t\t$this->expression = $expression;\n\t\t$this->framerate = $framerate;\n\t\t$this->hashes = $hashes;\n\t\t$this->height = $height;\n\t\t$this->keywords = $keywords;\n\t\t$this->lang = $lang;\n\t\t$this->length = $length;\n\t\t$this->link = $link;\n\t\t$this->medium = $medium;\n\t\t$this->player = $player;\n\t\t$this->ratings = $ratings;\n\t\t$this->restrictions = $restrictions;\n\t\t$this->samplingrate = $samplingrate;\n\t\t$this->thumbnails = $thumbnails;\n\t\t$this->title = $title;\n\t\t$this->type = $type;\n\t\t$this->width = $width;\n\n\t\tif (class_exists('idna_convert'))\n\t\t{\n\t\t\t$idn = new idna_convert();\n\t\t\t$parsed = SimplePie_Misc::parse_url($link);\n\t\t\t$this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);\n\t\t}\n\t\t$this->handler = $this->get_handler(); // Needs to load last\n\t}\n\n\t/**\n\t * String-ified version\n\t *\n\t * @return string\n\t */\n\tpublic function __toString()\n\t{\n\t\t// There is no $this->data here\n\t\treturn md5(serialize($this));\n\t}\n\n\t/**\n\t * Get the bitrate\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_bitrate()\n\t{\n\t\tif ($this->bitrate !== null)\n\t\t{\n\t\t\treturn $this->bitrate;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get a single caption\n\t *\n\t * @param int $key\n\t * @return SimplePie_Caption|null\n\t */\n\tpublic function get_caption($key = 0)\n\t{\n\t\t$captions = $this->get_captions();\n\t\tif (isset($captions[$key]))\n\t\t{\n\t\t\treturn $captions[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all captions\n\t *\n\t * @return array|null Array of {@see SimplePie_Caption} objects\n\t */\n\tpublic function get_captions()\n\t{\n\t\tif ($this->captions !== null)\n\t\t{\n\t\t\treturn $this->captions;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get a single category\n\t *\n\t * @param int $key\n\t * @return SimplePie_Category|null\n\t */\n\tpublic function get_category($key = 0)\n\t{\n\t\t$categories = $this->get_categories();\n\t\tif (isset($categories[$key]))\n\t\t{\n\t\t\treturn $categories[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all categories\n\t *\n\t * @return array|null Array of {@see SimplePie_Category} objects\n\t */\n\tpublic function get_categories()\n\t{\n\t\tif ($this->categories !== null)\n\t\t{\n\t\t\treturn $this->categories;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the number of audio channels\n\t *\n\t * @return int|null\n\t */\n\tpublic function get_channels()\n\t{\n\t\tif ($this->channels !== null)\n\t\t{\n\t\t\treturn $this->channels;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the copyright information\n\t *\n\t * @return SimplePie_Copyright|null\n\t */\n\tpublic function get_copyright()\n\t{\n\t\tif ($this->copyright !== null)\n\t\t{\n\t\t\treturn $this->copyright;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get a single credit\n\t *\n\t * @param int $key\n\t * @return SimplePie_Credit|null\n\t */\n\tpublic function get_credit($key = 0)\n\t{\n\t\t$credits = $this->get_credits();\n\t\tif (isset($credits[$key]))\n\t\t{\n\t\t\treturn $credits[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all credits\n\t *\n\t * @return array|null Array of {@see SimplePie_Credit} objects\n\t */\n\tpublic function get_credits()\n\t{\n\t\tif ($this->credits !== null)\n\t\t{\n\t\t\treturn $this->credits;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the description of the enclosure\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_description()\n\t{\n\t\tif ($this->description !== null)\n\t\t{\n\t\t\treturn $this->description;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the duration of the enclosure\n\t *\n\t * @param string $convert Convert seconds into hh:mm:ss\n\t * @return string|int|null 'hh:mm:ss' string if `$convert` was specified, otherwise integer (or null if none found)\n\t */\n\tpublic function get_duration($convert = false)\n\t{\n\t\tif ($this->duration !== null)\n\t\t{\n\t\t\tif ($convert)\n\t\t\t{\n\t\t\t\t$time = SimplePie_Misc::time_hms($this->duration);\n\t\t\t\treturn $time;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn $this->duration;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the expression\n\t *\n\t * @return string Probably one of 'sample', 'full', 'nonstop', 'clip'. Defaults to 'full'\n\t */\n\tpublic function get_expression()\n\t{\n\t\tif ($this->expression !== null)\n\t\t{\n\t\t\treturn $this->expression;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn 'full';\n\t\t}\n\t}\n\n\t/**\n\t * Get the file extension\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_extension()\n\t{\n\t\tif ($this->link !== null)\n\t\t{\n\t\t\t$url = SimplePie_Misc::parse_url($this->link);\n\t\t\tif ($url['path'] !== '')\n\t\t\t{\n\t\t\t\treturn pathinfo($url['path'], PATHINFO_EXTENSION);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Get the framerate (in frames-per-second)\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_framerate()\n\t{\n\t\tif ($this->framerate !== null)\n\t\t{\n\t\t\treturn $this->framerate;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the preferred handler\n\t *\n\t * @return string|null One of 'flash', 'fmedia', 'quicktime', 'wmedia', 'mp3'\n\t */\n\tpublic function get_handler()\n\t{\n\t\treturn $this->get_real_type(true);\n\t}\n\n\t/**\n\t * Get a single hash\n\t *\n\t * @link http://www.rssboard.org/media-rss#media-hash\n\t * @param int $key\n\t * @return string|null Hash as per `media:hash`, prefixed with \"$algo:\"\n\t */\n\tpublic function get_hash($key = 0)\n\t{\n\t\t$hashes = $this->get_hashes();\n\t\tif (isset($hashes[$key]))\n\t\t{\n\t\t\treturn $hashes[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all credits\n\t *\n\t * @return array|null Array of strings, see {@see get_hash()}\n\t */\n\tpublic function get_hashes()\n\t{\n\t\tif ($this->hashes !== null)\n\t\t{\n\t\t\treturn $this->hashes;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the height\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_height()\n\t{\n\t\tif ($this->height !== null)\n\t\t{\n\t\t\treturn $this->height;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the language\n\t *\n\t * @link http://tools.ietf.org/html/rfc3066\n\t * @return string|null Language code as per RFC 3066\n\t */\n\tpublic function get_language()\n\t{\n\t\tif ($this->lang !== null)\n\t\t{\n\t\t\treturn $this->lang;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get a single keyword\n\t *\n\t * @param int $key\n\t * @return string|null\n\t */\n\tpublic function get_keyword($key = 0)\n\t{\n\t\t$keywords = $this->get_keywords();\n\t\tif (isset($keywords[$key]))\n\t\t{\n\t\t\treturn $keywords[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all keywords\n\t *\n\t * @return array|null Array of strings\n\t */\n\tpublic function get_keywords()\n\t{\n\t\tif ($this->keywords !== null)\n\t\t{\n\t\t\treturn $this->keywords;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get length\n\t *\n\t * @return float Length in bytes\n\t */\n\tpublic function get_length()\n\t{\n\t\tif ($this->length !== null)\n\t\t{\n\t\t\treturn $this->length;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the URL\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_link()\n\t{\n\t\tif ($this->link !== null)\n\t\t{\n\t\t\treturn urldecode($this->link);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the medium\n\t *\n\t * @link http://www.rssboard.org/media-rss#media-content\n\t * @return string|null Should be one of 'image', 'audio', 'video', 'document', 'executable'\n\t */\n\tpublic function get_medium()\n\t{\n\t\tif ($this->medium !== null)\n\t\t{\n\t\t\treturn $this->medium;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the player URL\n\t *\n\t * Typically the same as {@see get_permalink()}\n\t * @return string|null Player URL\n\t */\n\tpublic function get_player()\n\t{\n\t\tif ($this->player !== null)\n\t\t{\n\t\t\treturn $this->player;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get a single rating\n\t *\n\t * @param int $key\n\t * @return SimplePie_Rating|null\n\t */\n\tpublic function get_rating($key = 0)\n\t{\n\t\t$ratings = $this->get_ratings();\n\t\tif (isset($ratings[$key]))\n\t\t{\n\t\t\treturn $ratings[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all ratings\n\t *\n\t * @return array|null Array of {@see SimplePie_Rating} objects\n\t */\n\tpublic function get_ratings()\n\t{\n\t\tif ($this->ratings !== null)\n\t\t{\n\t\t\treturn $this->ratings;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get a single restriction\n\t *\n\t * @param int $key\n\t * @return SimplePie_Restriction|null\n\t */\n\tpublic function get_restriction($key = 0)\n\t{\n\t\t$restrictions = $this->get_restrictions();\n\t\tif (isset($restrictions[$key]))\n\t\t{\n\t\t\treturn $restrictions[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all restrictions\n\t *\n\t * @return array|null Array of {@see SimplePie_Restriction} objects\n\t */\n\tpublic function get_restrictions()\n\t{\n\t\tif ($this->restrictions !== null)\n\t\t{\n\t\t\treturn $this->restrictions;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the sampling rate (in kHz)\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_sampling_rate()\n\t{\n\t\tif ($this->samplingrate !== null)\n\t\t{\n\t\t\treturn $this->samplingrate;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the file size (in MiB)\n\t *\n\t * @return float|null File size in mebibytes (1048 bytes)\n\t */\n\tpublic function get_size()\n\t{\n\t\t$length = $this->get_length();\n\t\tif ($length !== null)\n\t\t{\n\t\t\treturn round($length/1048576, 2);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get a single thumbnail\n\t *\n\t * @param int $key\n\t * @return string|null Thumbnail URL\n\t */\n\tpublic function get_thumbnail($key = 0)\n\t{\n\t\t$thumbnails = $this->get_thumbnails();\n\t\tif (isset($thumbnails[$key]))\n\t\t{\n\t\t\treturn $thumbnails[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all thumbnails\n\t *\n\t * @return array|null Array of thumbnail URLs\n\t */\n\tpublic function get_thumbnails()\n\t{\n\t\tif ($this->thumbnails !== null)\n\t\t{\n\t\t\treturn $this->thumbnails;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the title\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_title()\n\t{\n\t\tif ($this->title !== null)\n\t\t{\n\t\t\treturn $this->title;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get mimetype of the enclosure\n\t *\n\t * @see get_real_type()\n\t * @return string|null MIME type\n\t */\n\tpublic function get_type()\n\t{\n\t\tif ($this->type !== null)\n\t\t{\n\t\t\treturn $this->type;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the width\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_width()\n\t{\n\t\tif ($this->width !== null)\n\t\t{\n\t\t\treturn $this->width;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Embed the enclosure using `<embed>`\n\t *\n\t * @deprecated Use the second parameter to {@see embed} instead\n\t *\n\t * @param array|string $options See first paramter to {@see embed}\n\t * @return string HTML string to output\n\t */\n\tpublic function native_embed($options='')\n\t{\n\t\treturn $this->embed($options, true);\n\t}\n\n\t/**\n\t * Embed the enclosure using Javascript\n\t *\n\t * `$options` is an array or comma-separated key:value string, with the\n\t * following properties:\n\t *\n\t * - `alt` (string): Alternate content for when an end-user does not have\n\t *    the appropriate handler installed or when a file type is\n\t *    unsupported. Can be any text or HTML. Defaults to blank.\n\t * - `altclass` (string): If a file type is unsupported, the end-user will\n\t *    see the alt text (above) linked directly to the content. That link\n\t *    will have this value as its class name. Defaults to blank.\n\t * - `audio` (string): This is an image that should be used as a\n\t *    placeholder for audio files before they're loaded (QuickTime-only).\n\t *    Can be any relative or absolute URL. Defaults to blank.\n\t * - `bgcolor` (string): The background color for the media, if not\n\t *    already transparent. Defaults to `#ffffff`.\n\t * - `height` (integer): The height of the embedded media. Accepts any\n\t *    numeric pixel value (such as `360`) or `auto`. Defaults to `auto`,\n\t *    and it is recommended that you use this default.\n\t * - `loop` (boolean): Do you want the media to loop when its done?\n\t *    Defaults to `false`.\n\t * - `mediaplayer` (string): The location of the included\n\t *    `mediaplayer.swf` file. This allows for the playback of Flash Video\n\t *    (`.flv`) files, and is the default handler for non-Odeo MP3's.\n\t *    Defaults to blank.\n\t * - `video` (string): This is an image that should be used as a\n\t *    placeholder for video files before they're loaded (QuickTime-only).\n\t *    Can be any relative or absolute URL. Defaults to blank.\n\t * - `width` (integer): The width of the embedded media. Accepts any\n\t *    numeric pixel value (such as `480`) or `auto`. Defaults to `auto`,\n\t *    and it is recommended that you use this default.\n\t * - `widescreen` (boolean): Is the enclosure widescreen or standard?\n\t *    This applies only to video enclosures, and will automatically resize\n\t *    the content appropriately.  Defaults to `false`, implying 4:3 mode.\n\t *\n\t * Note: Non-widescreen (4:3) mode with `width` and `height` set to `auto`\n\t * will default to 480x360 video resolution.  Widescreen (16:9) mode with\n\t * `width` and `height` set to `auto` will default to 480x270 video resolution.\n\t *\n\t * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.\n\t * @param array|string $options Comma-separated key:value list, or array\n\t * @param bool $native Use `<embed>`\n\t * @return string HTML string to output\n\t */\n\tpublic function embed($options = '', $native = false)\n\t{\n\t\t// Set up defaults\n\t\t$audio = '';\n\t\t$video = '';\n\t\t$alt = '';\n\t\t$altclass = '';\n\t\t$loop = 'false';\n\t\t$width = 'auto';\n\t\t$height = 'auto';\n\t\t$bgcolor = '#ffffff';\n\t\t$mediaplayer = '';\n\t\t$widescreen = false;\n\t\t$handler = $this->get_handler();\n\t\t$type = $this->get_real_type();\n\n\t\t// Process options and reassign values as necessary\n\t\tif (is_array($options))\n\t\t{\n\t\t\textract($options);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$options = explode(',', $options);\n\t\t\tforeach($options as $option)\n\t\t\t{\n\t\t\t\t$opt = explode(':', $option, 2);\n\t\t\t\tif (isset($opt[0], $opt[1]))\n\t\t\t\t{\n\t\t\t\t\t$opt[0] = trim($opt[0]);\n\t\t\t\t\t$opt[1] = trim($opt[1]);\n\t\t\t\t\tswitch ($opt[0])\n\t\t\t\t\t{\n\t\t\t\t\t\tcase 'audio':\n\t\t\t\t\t\t\t$audio = $opt[1];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'video':\n\t\t\t\t\t\t\t$video = $opt[1];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'alt':\n\t\t\t\t\t\t\t$alt = $opt[1];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'altclass':\n\t\t\t\t\t\t\t$altclass = $opt[1];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'loop':\n\t\t\t\t\t\t\t$loop = $opt[1];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'width':\n\t\t\t\t\t\t\t$width = $opt[1];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'height':\n\t\t\t\t\t\t\t$height = $opt[1];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'bgcolor':\n\t\t\t\t\t\t\t$bgcolor = $opt[1];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'mediaplayer':\n\t\t\t\t\t\t\t$mediaplayer = $opt[1];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 'widescreen':\n\t\t\t\t\t\t\t$widescreen = $opt[1];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$mime = explode('/', $type, 2);\n\t\t$mime = $mime[0];\n\n\t\t// Process values for 'auto'\n\t\tif ($width === 'auto')\n\t\t{\n\t\t\tif ($mime === 'video')\n\t\t\t{\n\t\t\t\tif ($height === 'auto')\n\t\t\t\t{\n\t\t\t\t\t$width = 480;\n\t\t\t\t}\n\t\t\t\telseif ($widescreen)\n\t\t\t\t{\n\t\t\t\t\t$width = round((intval($height)/9)*16);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$width = round((intval($height)/3)*4);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$width = '100%';\n\t\t\t}\n\t\t}\n\n\t\tif ($height === 'auto')\n\t\t{\n\t\t\tif ($mime === 'audio')\n\t\t\t{\n\t\t\t\t$height = 0;\n\t\t\t}\n\t\t\telseif ($mime === 'video')\n\t\t\t{\n\t\t\t\tif ($width === 'auto')\n\t\t\t\t{\n\t\t\t\t\tif ($widescreen)\n\t\t\t\t\t{\n\t\t\t\t\t\t$height = 270;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$height = 360;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telseif ($widescreen)\n\t\t\t\t{\n\t\t\t\t\t$height = round((intval($width)/16)*9);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$height = round((intval($width)/4)*3);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$height = 376;\n\t\t\t}\n\t\t}\n\t\telseif ($mime === 'audio')\n\t\t{\n\t\t\t$height = 0;\n\t\t}\n\n\t\t// Set proper placeholder value\n\t\tif ($mime === 'audio')\n\t\t{\n\t\t\t$placeholder = $audio;\n\t\t}\n\t\telseif ($mime === 'video')\n\t\t{\n\t\t\t$placeholder = $video;\n\t\t}\n\n\t\t$embed = '';\n\n\t\t// Flash\n\t\tif ($handler === 'flash')\n\t\t{\n\t\t\tif ($native)\n\t\t\t{\n\t\t\t\t$embed .= \"<embed src=\\\"\" . $this->get_link() . \"\\\" pluginspage=\\\"http://adobe.com/go/getflashplayer\\\" type=\\\"$type\\\" quality=\\\"high\\\" width=\\\"$width\\\" height=\\\"$height\\\" bgcolor=\\\"$bgcolor\\\" loop=\\\"$loop\\\"></embed>\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$embed .= \"<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '\" . $this->get_link() . \"', '$loop', '$type');</script>\";\n\t\t\t}\n\t\t}\n\n\t\t// Flash Media Player file types.\n\t\t// Preferred handler for MP3 file types.\n\t\telseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))\n\t\t{\n\t\t\t$height += 20;\n\t\t\tif ($native)\n\t\t\t{\n\t\t\t\t$embed .= \"<embed src=\\\"$mediaplayer\\\" pluginspage=\\\"http://adobe.com/go/getflashplayer\\\" type=\\\"application/x-shockwave-flash\\\" quality=\\\"high\\\" width=\\\"$width\\\" height=\\\"$height\\\" wmode=\\\"transparent\\\" flashvars=\\\"file=\" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . \"&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\\\"></embed>\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$embed .= \"<script type='text/javascript'>embed_flv('$width', '$height', '\" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . \"', '$placeholder', '$loop', '$mediaplayer');</script>\";\n\t\t\t}\n\t\t}\n\n\t\t// QuickTime 7 file types.  Need to test with QuickTime 6.\n\t\t// Only handle MP3's if the Flash Media Player is not present.\n\t\telseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))\n\t\t{\n\t\t\t$height += 16;\n\t\t\tif ($native)\n\t\t\t{\n\t\t\t\tif ($placeholder !== '')\n\t\t\t\t{\n\t\t\t\t\t$embed .= \"<embed type=\\\"$type\\\" style=\\\"cursor:hand; cursor:pointer;\\\" href=\\\"\" . $this->get_link() . \"\\\" src=\\\"$placeholder\\\" width=\\\"$width\\\" height=\\\"$height\\\" autoplay=\\\"false\\\" target=\\\"myself\\\" controller=\\\"false\\\" loop=\\\"$loop\\\" scale=\\\"aspect\\\" bgcolor=\\\"$bgcolor\\\" pluginspage=\\\"http://apple.com/quicktime/download/\\\"></embed>\";\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$embed .= \"<embed type=\\\"$type\\\" style=\\\"cursor:hand; cursor:pointer;\\\" src=\\\"\" . $this->get_link() . \"\\\" width=\\\"$width\\\" height=\\\"$height\\\" autoplay=\\\"false\\\" target=\\\"myself\\\" controller=\\\"true\\\" loop=\\\"$loop\\\" scale=\\\"aspect\\\" bgcolor=\\\"$bgcolor\\\" pluginspage=\\\"http://apple.com/quicktime/download/\\\"></embed>\";\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$embed .= \"<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '\" . $this->get_link() . \"', '$placeholder', '$loop');</script>\";\n\t\t\t}\n\t\t}\n\n\t\t// Windows Media\n\t\telseif ($handler === 'wmedia')\n\t\t{\n\t\t\t$height += 45;\n\t\t\tif ($native)\n\t\t\t{\n\t\t\t\t$embed .= \"<embed type=\\\"application/x-mplayer2\\\" src=\\\"\" . $this->get_link() . \"\\\" autosize=\\\"1\\\" width=\\\"$width\\\" height=\\\"$height\\\" showcontrols=\\\"1\\\" showstatusbar=\\\"0\\\" showdisplay=\\\"0\\\" autostart=\\\"0\\\"></embed>\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$embed .= \"<script type='text/javascript'>embed_wmedia('$width', '$height', '\" . $this->get_link() . \"');</script>\";\n\t\t\t}\n\t\t}\n\n\t\t// Everything else\n\t\telse $embed .= '<a href=\"' . $this->get_link() . '\" class=\"' . $altclass . '\">' . $alt . '</a>';\n\n\t\treturn $embed;\n\t}\n\n\t/**\n\t * Get the real media type\n\t *\n\t * Often, feeds lie to us, necessitating a bit of deeper inspection. This\n\t * converts types to their canonical representations based on the file\n\t * extension\n\t *\n\t * @see get_type()\n\t * @param bool $find_handler Internal use only, use {@see get_handler()} instead\n\t * @return string MIME type\n\t */\n\tpublic function get_real_type($find_handler = false)\n\t{\n\t\t// Mime-types by handler.\n\t\t$types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash\n\t\t$types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player\n\t\t$types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video'); // QuickTime\n\t\t$types_wmedia = array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx'); // Windows Media\n\t\t$types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3\n\n\t\tif ($this->get_type() !== null)\n\t\t{\n\t\t\t$type = strtolower($this->type);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$type = null;\n\t\t}\n\n\t\t// If we encounter an unsupported mime-type, check the file extension and guess intelligently.\n\t\tif (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))\n\t\t{\n\t\t\tswitch (strtolower($this->get_extension()))\n\t\t\t{\n\t\t\t\t// Audio mime-types\n\t\t\t\tcase 'aac':\n\t\t\t\tcase 'adts':\n\t\t\t\t\t$type = 'audio/acc';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'aif':\n\t\t\t\tcase 'aifc':\n\t\t\t\tcase 'aiff':\n\t\t\t\tcase 'cdda':\n\t\t\t\t\t$type = 'audio/aiff';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'bwf':\n\t\t\t\t\t$type = 'audio/wav';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'kar':\n\t\t\t\tcase 'mid':\n\t\t\t\tcase 'midi':\n\t\t\t\tcase 'smf':\n\t\t\t\t\t$type = 'audio/midi';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'm4a':\n\t\t\t\t\t$type = 'audio/x-m4a';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'mp3':\n\t\t\t\tcase 'swa':\n\t\t\t\t\t$type = 'audio/mp3';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'wav':\n\t\t\t\t\t$type = 'audio/wav';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'wax':\n\t\t\t\t\t$type = 'audio/x-ms-wax';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'wma':\n\t\t\t\t\t$type = 'audio/x-ms-wma';\n\t\t\t\t\tbreak;\n\n\t\t\t\t// Video mime-types\n\t\t\t\tcase '3gp':\n\t\t\t\tcase '3gpp':\n\t\t\t\t\t$type = 'video/3gpp';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase '3g2':\n\t\t\t\tcase '3gp2':\n\t\t\t\t\t$type = 'video/3gpp2';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'asf':\n\t\t\t\t\t$type = 'video/x-ms-asf';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'flv':\n\t\t\t\t\t$type = 'video/x-flv';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'm1a':\n\t\t\t\tcase 'm1s':\n\t\t\t\tcase 'm1v':\n\t\t\t\tcase 'm15':\n\t\t\t\tcase 'm75':\n\t\t\t\tcase 'mp2':\n\t\t\t\tcase 'mpa':\n\t\t\t\tcase 'mpeg':\n\t\t\t\tcase 'mpg':\n\t\t\t\tcase 'mpm':\n\t\t\t\tcase 'mpv':\n\t\t\t\t\t$type = 'video/mpeg';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'm4v':\n\t\t\t\t\t$type = 'video/x-m4v';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'mov':\n\t\t\t\tcase 'qt':\n\t\t\t\t\t$type = 'video/quicktime';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'mp4':\n\t\t\t\tcase 'mpg4':\n\t\t\t\t\t$type = 'video/mp4';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'sdv':\n\t\t\t\t\t$type = 'video/sd-video';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'wm':\n\t\t\t\t\t$type = 'video/x-ms-wm';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'wmv':\n\t\t\t\t\t$type = 'video/x-ms-wmv';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'wvx':\n\t\t\t\t\t$type = 'video/x-ms-wvx';\n\t\t\t\t\tbreak;\n\n\t\t\t\t// Flash mime-types\n\t\t\t\tcase 'spl':\n\t\t\t\t\t$type = 'application/futuresplash';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'swf':\n\t\t\t\t\t$type = 'application/x-shockwave-flash';\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ($find_handler)\n\t\t{\n\t\t\tif (in_array($type, $types_flash))\n\t\t\t{\n\t\t\t\treturn 'flash';\n\t\t\t}\n\t\t\telseif (in_array($type, $types_fmedia))\n\t\t\t{\n\t\t\t\treturn 'fmedia';\n\t\t\t}\n\t\t\telseif (in_array($type, $types_quicktime))\n\t\t\t{\n\t\t\t\treturn 'quicktime';\n\t\t\t}\n\t\t\telseif (in_array($type, $types_wmedia))\n\t\t\t{\n\t\t\t\treturn 'wmedia';\n\t\t\t}\n\t\t\telseif (in_array($type, $types_mp3))\n\t\t\t{\n\t\t\t\treturn 'mp3';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn $type;\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Exception.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.4-dev\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * General SimplePie exception class\n *\n * @package SimplePie\n */\nclass SimplePie_Exception extends Exception\n{\n}"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/File.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Used for fetching remote files and reading local files\n *\n * Supports HTTP 1.0 via cURL or fsockopen, with spotty HTTP 1.1 support\n *\n * This class can be overloaded with {@see SimplePie::set_file_class()}\n *\n * @package SimplePie\n * @subpackage HTTP\n * @todo Move to properly supporting RFC2616 (HTTP/1.1)\n */\nclass SimplePie_File\n{\n\tvar $url;\n\tvar $useragent;\n\tvar $success = true;\n\tvar $headers = array();\n\tvar $body;\n\tvar $status_code;\n\tvar $redirects = 0;\n\tvar $error;\n\tvar $method = SIMPLEPIE_FILE_SOURCE_NONE;\n\n\tpublic function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)\n\t{\n\t\tif (class_exists('idna_convert'))\n\t\t{\n\t\t\t$idn = new idna_convert();\n\t\t\t$parsed = SimplePie_Misc::parse_url($url);\n\t\t\t$url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);\n\t\t}\n\t\t$this->url = $url;\n\t\t$this->useragent = $useragent;\n\t\tif (preg_match('/^http(s)?:\\/\\//i', $url))\n\t\t{\n\t\t\tif ($useragent === null)\n\t\t\t{\n\t\t\t\t$useragent = ini_get('user_agent');\n\t\t\t\t$this->useragent = $useragent;\n\t\t\t}\n\t\t\tif (!is_array($headers))\n\t\t\t{\n\t\t\t\t$headers = array();\n\t\t\t}\n\t\t\tif (!$force_fsockopen && function_exists('curl_exec'))\n\t\t\t{\n\t\t\t\t$this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;\n\t\t\t\t$fp = curl_init();\n\t\t\t\t$headers2 = array();\n\t\t\t\tforeach ($headers as $key => $value)\n\t\t\t\t{\n\t\t\t\t\t$headers2[] = \"$key: $value\";\n\t\t\t\t}\n\t\t\t\tif (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))\n\t\t\t\t{\n\t\t\t\t\tcurl_setopt($fp, CURLOPT_ENCODING, '');\n\t\t\t\t}\n\t\t\t\tcurl_setopt($fp, CURLOPT_URL, $url);\n\t\t\t\tcurl_setopt($fp, CURLOPT_HEADER, 1);\n\t\t\t\tcurl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);\n\t\t\t\tcurl_setopt($fp, CURLOPT_TIMEOUT, $timeout);\n\t\t\t\tcurl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);\n\t\t\t\tcurl_setopt($fp, CURLOPT_REFERER, $url);\n\t\t\t\tcurl_setopt($fp, CURLOPT_USERAGENT, $useragent);\n\t\t\t\tcurl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);\n\t\t\t\tif (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))\n\t\t\t\t{\n\t\t\t\t\tcurl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);\n\t\t\t\t\tcurl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);\n\t\t\t\t}\n\n\t\t\t\t$this->headers = curl_exec($fp);\n\t\t\t\tif (curl_errno($fp) === 23 || curl_errno($fp) === 61)\n\t\t\t\t{\n\t\t\t\t\tcurl_setopt($fp, CURLOPT_ENCODING, 'none');\n\t\t\t\t\t$this->headers = curl_exec($fp);\n\t\t\t\t}\n\t\t\t\tif (curl_errno($fp))\n\t\t\t\t{\n\t\t\t\t\t$this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);\n\t\t\t\t\t$this->success = false;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$info = curl_getinfo($fp);\n\t\t\t\t\tcurl_close($fp);\n\t\t\t\t\t$this->headers = explode(\"\\r\\n\\r\\n\", $this->headers, $info['redirect_count'] + 1);\n\t\t\t\t\t$this->headers = array_pop($this->headers);\n\t\t\t\t\t$parser = new SimplePie_HTTP_Parser($this->headers);\n\t\t\t\t\tif ($parser->parse())\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->headers = $parser->headers;\n\t\t\t\t\t\t$this->body = $parser->body;\n\t\t\t\t\t\t$this->status_code = $parser->status_code;\n\t\t\t\t\t\tif ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->redirects++;\n\t\t\t\t\t\t\t$location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);\n\t\t\t\t\t\t\treturn $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;\n\t\t\t\t$url_parts = parse_url($url);\n\t\t\t\t$socket_host = $url_parts['host'];\n\t\t\t\tif (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')\n\t\t\t\t{\n\t\t\t\t\t$socket_host = \"ssl://$url_parts[host]\";\n\t\t\t\t\t$url_parts['port'] = 443;\n\t\t\t\t}\n\t\t\t\tif (!isset($url_parts['port']))\n\t\t\t\t{\n\t\t\t\t\t$url_parts['port'] = 80;\n\t\t\t\t}\n\t\t\t\t$fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout);\n\t\t\t\tif (!$fp)\n\t\t\t\t{\n\t\t\t\t\t$this->error = 'fsockopen error: ' . $errstr;\n\t\t\t\t\t$this->success = false;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tstream_set_timeout($fp, $timeout);\n\t\t\t\t\tif (isset($url_parts['path']))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (isset($url_parts['query']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$get = \"$url_parts[path]?$url_parts[query]\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$get = $url_parts['path'];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$get = '/';\n\t\t\t\t\t}\n\t\t\t\t\t$out = \"GET $get HTTP/1.1\\r\\n\";\n\t\t\t\t\t$out .= \"Host: $url_parts[host]\\r\\n\";\n\t\t\t\t\t$out .= \"User-Agent: $useragent\\r\\n\";\n\t\t\t\t\tif (extension_loaded('zlib'))\n\t\t\t\t\t{\n\t\t\t\t\t\t$out .= \"Accept-Encoding: x-gzip,gzip,deflate\\r\\n\";\n\t\t\t\t\t}\n\n\t\t\t\t\tif (isset($url_parts['user']) && isset($url_parts['pass']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$out .= \"Authorization: Basic \" . base64_encode(\"$url_parts[user]:$url_parts[pass]\") . \"\\r\\n\";\n\t\t\t\t\t}\n\t\t\t\t\tforeach ($headers as $key => $value)\n\t\t\t\t\t{\n\t\t\t\t\t\t$out .= \"$key: $value\\r\\n\";\n\t\t\t\t\t}\n\t\t\t\t\t$out .= \"Connection: Close\\r\\n\\r\\n\";\n\t\t\t\t\tfwrite($fp, $out);\n\n\t\t\t\t\t$info = stream_get_meta_data($fp);\n\n\t\t\t\t\t$this->headers = '';\n\t\t\t\t\twhile (!$info['eof'] && !$info['timed_out'])\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->headers .= fread($fp, 1160);\n\t\t\t\t\t\t$info = stream_get_meta_data($fp);\n\t\t\t\t\t}\n\t\t\t\t\tif (!$info['timed_out'])\n\t\t\t\t\t{\n\t\t\t\t\t\t$parser = new SimplePie_HTTP_Parser($this->headers);\n\t\t\t\t\t\tif ($parser->parse())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->headers = $parser->headers;\n\t\t\t\t\t\t\t$this->body = $parser->body;\n\t\t\t\t\t\t\t$this->status_code = $parser->status_code;\n\t\t\t\t\t\t\tif ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$this->redirects++;\n\t\t\t\t\t\t\t\t$location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);\n\t\t\t\t\t\t\t\treturn $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (isset($this->headers['content-encoding']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// Hey, we act dumb elsewhere, so let's do that here too\n\t\t\t\t\t\t\t\tswitch (strtolower(trim($this->headers['content-encoding'], \"\\x09\\x0A\\x0D\\x20\")))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcase 'gzip':\n\t\t\t\t\t\t\t\t\tcase 'x-gzip':\n\t\t\t\t\t\t\t\t\t\t$decoder = new SimplePie_gzdecode($this->body);\n\t\t\t\t\t\t\t\t\t\tif (!$decoder->parse())\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$this->error = 'Unable to decode HTTP \"gzip\" stream';\n\t\t\t\t\t\t\t\t\t\t\t$this->success = false;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$this->body = $decoder->data;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\tcase 'deflate':\n\t\t\t\t\t\t\t\t\t\tif (($decompressed = gzinflate($this->body)) !== false)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$this->body = $decompressed;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if (($decompressed = gzuncompress($this->body)) !== false)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$this->body = $decompressed;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse if (function_exists('gzdecode') && ($decompressed = gzdecode($this->body)) !== false)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$this->body = $decompressed;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$this->error = 'Unable to decode HTTP \"deflate\" stream';\n\t\t\t\t\t\t\t\t\t\t\t$this->success = false;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t$this->error = 'Unknown content coding';\n\t\t\t\t\t\t\t\t\t\t$this->success = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->error = 'fsocket timed out';\n\t\t\t\t\t\t$this->success = false;\n\t\t\t\t\t}\n\t\t\t\t\tfclose($fp);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;\n\t\t\tif (!$this->body = file_get_contents($url))\n\t\t\t{\n\t\t\t\t$this->error = 'file_get_contents could not read the file';\n\t\t\t\t$this->success = false;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/HTTP/Parser.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n\n/**\n * HTTP Response Parser\n *\n * @package SimplePie\n * @subpackage HTTP\n */\nclass SimplePie_HTTP_Parser\n{\n\t/**\n\t * HTTP Version\n\t *\n\t * @var float\n\t */\n\tpublic $http_version = 0.0;\n\n\t/**\n\t * Status code\n\t *\n\t * @var int\n\t */\n\tpublic $status_code = 0;\n\n\t/**\n\t * Reason phrase\n\t *\n\t * @var string\n\t */\n\tpublic $reason = '';\n\n\t/**\n\t * Key/value pairs of the headers\n\t *\n\t * @var array\n\t */\n\tpublic $headers = array();\n\n\t/**\n\t * Body of the response\n\t *\n\t * @var string\n\t */\n\tpublic $body = '';\n\n\t/**\n\t * Current state of the state machine\n\t *\n\t * @var string\n\t */\n\tprotected $state = 'http_version';\n\n\t/**\n\t * Input data\n\t *\n\t * @var string\n\t */\n\tprotected $data = '';\n\n\t/**\n\t * Input data length (to avoid calling strlen() everytime this is needed)\n\t *\n\t * @var int\n\t */\n\tprotected $data_length = 0;\n\n\t/**\n\t * Current position of the pointer\n\t *\n\t * @var int\n\t */\n\tprotected $position = 0;\n\n\t/**\n\t * Name of the hedaer currently being parsed\n\t *\n\t * @var string\n\t */\n\tprotected $name = '';\n\n\t/**\n\t * Value of the hedaer currently being parsed\n\t *\n\t * @var string\n\t */\n\tprotected $value = '';\n\n\t/**\n\t * Create an instance of the class with the input data\n\t *\n\t * @param string $data Input data\n\t */\n\tpublic function __construct($data)\n\t{\n\t\t$this->data = $data;\n\t\t$this->data_length = strlen($this->data);\n\t}\n\n\t/**\n\t * Parse the input data\n\t *\n\t * @return bool true on success, false on failure\n\t */\n\tpublic function parse()\n\t{\n\t\twhile ($this->state && $this->state !== 'emit' && $this->has_data())\n\t\t{\n\t\t\t$state = $this->state;\n\t\t\t$this->$state();\n\t\t}\n\t\t$this->data = '';\n\t\tif ($this->state === 'emit' || $this->state === 'body')\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->http_version = '';\n\t\t\t$this->status_code = '';\n\t\t\t$this->reason = '';\n\t\t\t$this->headers = array();\n\t\t\t$this->body = '';\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Check whether there is data beyond the pointer\n\t *\n\t * @return bool true if there is further data, false if not\n\t */\n\tprotected function has_data()\n\t{\n\t\treturn (bool) ($this->position < $this->data_length);\n\t}\n\n\t/**\n\t * See if the next character is LWS\n\t *\n\t * @return bool true if the next character is LWS, false if not\n\t */\n\tprotected function is_linear_whitespace()\n\t{\n\t\treturn (bool) ($this->data[$this->position] === \"\\x09\"\n\t\t\t|| $this->data[$this->position] === \"\\x20\"\n\t\t\t|| ($this->data[$this->position] === \"\\x0A\"\n\t\t\t\t&& isset($this->data[$this->position + 1])\n\t\t\t\t&& ($this->data[$this->position + 1] === \"\\x09\" || $this->data[$this->position + 1] === \"\\x20\")));\n\t}\n\n\t/**\n\t * Parse the HTTP version\n\t */\n\tprotected function http_version()\n\t{\n\t\tif (strpos($this->data, \"\\x0A\") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')\n\t\t{\n\t\t\t$len = strspn($this->data, '0123456789.', 5);\n\t\t\t$this->http_version = substr($this->data, 5, $len);\n\t\t\t$this->position += 5 + $len;\n\t\t\tif (substr_count($this->http_version, '.') <= 1)\n\t\t\t{\n\t\t\t\t$this->http_version = (float) $this->http_version;\n\t\t\t\t$this->position += strspn($this->data, \"\\x09\\x20\", $this->position);\n\t\t\t\t$this->state = 'status';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->state = false;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = false;\n\t\t}\n\t}\n\n\t/**\n\t * Parse the status code\n\t */\n\tprotected function status()\n\t{\n\t\tif ($len = strspn($this->data, '0123456789', $this->position))\n\t\t{\n\t\t\t$this->status_code = (int) substr($this->data, $this->position, $len);\n\t\t\t$this->position += $len;\n\t\t\t$this->state = 'reason';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = false;\n\t\t}\n\t}\n\n\t/**\n\t * Parse the reason phrase\n\t */\n\tprotected function reason()\n\t{\n\t\t$len = strcspn($this->data, \"\\x0A\", $this->position);\n\t\t$this->reason = trim(substr($this->data, $this->position, $len), \"\\x09\\x0D\\x20\");\n\t\t$this->position += $len + 1;\n\t\t$this->state = 'new_line';\n\t}\n\n\t/**\n\t * Deal with a new line, shifting data around as needed\n\t */\n\tprotected function new_line()\n\t{\n\t\t$this->value = trim($this->value, \"\\x0D\\x20\");\n\t\tif ($this->name !== '' && $this->value !== '')\n\t\t{\n\t\t\t$this->name = strtolower($this->name);\n\t\t\t// We should only use the last Content-Type header. c.f. issue #1\n\t\t\tif (isset($this->headers[$this->name]) && $this->name !== 'content-type')\n\t\t\t{\n\t\t\t\t$this->headers[$this->name] .= ', ' . $this->value;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->headers[$this->name] = $this->value;\n\t\t\t}\n\t\t}\n\t\t$this->name = '';\n\t\t$this->value = '';\n\t\tif (substr($this->data[$this->position], 0, 2) === \"\\x0D\\x0A\")\n\t\t{\n\t\t\t$this->position += 2;\n\t\t\t$this->state = 'body';\n\t\t}\n\t\telseif ($this->data[$this->position] === \"\\x0A\")\n\t\t{\n\t\t\t$this->position++;\n\t\t\t$this->state = 'body';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = 'name';\n\t\t}\n\t}\n\n\t/**\n\t * Parse a header name\n\t */\n\tprotected function name()\n\t{\n\t\t$len = strcspn($this->data, \"\\x0A:\", $this->position);\n\t\tif (isset($this->data[$this->position + $len]))\n\t\t{\n\t\t\tif ($this->data[$this->position + $len] === \"\\x0A\")\n\t\t\t{\n\t\t\t\t$this->position += $len;\n\t\t\t\t$this->state = 'new_line';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->name = substr($this->data, $this->position, $len);\n\t\t\t\t$this->position += $len + 1;\n\t\t\t\t$this->state = 'value';\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = false;\n\t\t}\n\t}\n\n\t/**\n\t * Parse LWS, replacing consecutive LWS characters with a single space\n\t */\n\tprotected function linear_whitespace()\n\t{\n\t\tdo\n\t\t{\n\t\t\tif (substr($this->data, $this->position, 2) === \"\\x0D\\x0A\")\n\t\t\t{\n\t\t\t\t$this->position += 2;\n\t\t\t}\n\t\t\telseif ($this->data[$this->position] === \"\\x0A\")\n\t\t\t{\n\t\t\t\t$this->position++;\n\t\t\t}\n\t\t\t$this->position += strspn($this->data, \"\\x09\\x20\", $this->position);\n\t\t} while ($this->has_data() && $this->is_linear_whitespace());\n\t\t$this->value .= \"\\x20\";\n\t}\n\n\t/**\n\t * See what state to move to while within non-quoted header values\n\t */\n\tprotected function value()\n\t{\n\t\tif ($this->is_linear_whitespace())\n\t\t{\n\t\t\t$this->linear_whitespace();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tswitch ($this->data[$this->position])\n\t\t\t{\n\t\t\t\tcase '\"':\n\t\t\t\t\t// Workaround for ETags: we have to include the quotes as\n\t\t\t\t\t// part of the tag.\n\t\t\t\t\tif (strtolower($this->name) === 'etag')\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->value .= '\"';\n\t\t\t\t\t\t$this->position++;\n\t\t\t\t\t\t$this->state = 'value_char';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t$this->position++;\n\t\t\t\t\t$this->state = 'quote';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"\\x0A\":\n\t\t\t\t\t$this->position++;\n\t\t\t\t\t$this->state = 'new_line';\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\t$this->state = 'value_char';\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Parse a header value while outside quotes\n\t */\n\tprotected function value_char()\n\t{\n\t\t$len = strcspn($this->data, \"\\x09\\x20\\x0A\\\"\", $this->position);\n\t\t$this->value .= substr($this->data, $this->position, $len);\n\t\t$this->position += $len;\n\t\t$this->state = 'value';\n\t}\n\n\t/**\n\t * See what state to move to while within quoted header values\n\t */\n\tprotected function quote()\n\t{\n\t\tif ($this->is_linear_whitespace())\n\t\t{\n\t\t\t$this->linear_whitespace();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tswitch ($this->data[$this->position])\n\t\t\t{\n\t\t\t\tcase '\"':\n\t\t\t\t\t$this->position++;\n\t\t\t\t\t$this->state = 'value';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"\\x0A\":\n\t\t\t\t\t$this->position++;\n\t\t\t\t\t$this->state = 'new_line';\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase '\\\\':\n\t\t\t\t\t$this->position++;\n\t\t\t\t\t$this->state = 'quote_escaped';\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\t$this->state = 'quote_char';\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Parse a header value while within quotes\n\t */\n\tprotected function quote_char()\n\t{\n\t\t$len = strcspn($this->data, \"\\x09\\x20\\x0A\\\"\\\\\", $this->position);\n\t\t$this->value .= substr($this->data, $this->position, $len);\n\t\t$this->position += $len;\n\t\t$this->state = 'value';\n\t}\n\n\t/**\n\t * Parse an escaped character within quotes\n\t */\n\tprotected function quote_escaped()\n\t{\n\t\t$this->value .= $this->data[$this->position];\n\t\t$this->position++;\n\t\t$this->state = 'quote';\n\t}\n\n\t/**\n\t * Parse the body\n\t */\n\tprotected function body()\n\t{\n\t\t$this->body = substr($this->data, $this->position);\n\t\tif (!empty($this->headers['transfer-encoding']))\n\t\t{\n\t\t\tunset($this->headers['transfer-encoding']);\n\t\t\t$this->state = 'chunked';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = 'emit';\n\t\t}\n\t}\n\n\t/**\n\t * Parsed a \"Transfer-Encoding: chunked\" body\n\t */\n\tprotected function chunked()\n\t{\n\t\tif (!preg_match('/^([0-9a-f]+)[^\\r\\n]*\\r\\n/i', trim($this->body)))\n\t\t{\n\t\t\t$this->state = 'emit';\n\t\t\treturn;\n\t\t}\n\n\t\t$decoded = '';\n\t\t$encoded = $this->body;\n\n\t\twhile (true)\n\t\t{\n\t\t\t$is_chunked = (bool) preg_match( '/^([0-9a-f]+)[^\\r\\n]*\\r\\n/i', $encoded, $matches );\n\t\t\tif (!$is_chunked)\n\t\t\t{\n\t\t\t\t// Looks like it's not chunked after all\n\t\t\t\t$this->state = 'emit';\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$length = hexdec(trim($matches[1]));\n\t\t\tif ($length === 0)\n\t\t\t{\n\t\t\t\t// Ignore trailer headers\n\t\t\t\t$this->state = 'emit';\n\t\t\t\t$this->body = $decoded;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$chunk_length = strlen($matches[0]);\n\t\t\t$decoded .= $part = substr($encoded, $chunk_length, $length);\n\t\t\t$encoded = substr($encoded, $chunk_length + $length + 2);\n\n\t\t\tif (trim($encoded) === '0' || empty($encoded))\n\t\t\t{\n\t\t\t\t$this->state = 'emit';\n\t\t\t\t$this->body = $decoded;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/IRI.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * IRI parser/serialiser/normaliser\n *\n * @package SimplePie\n * @subpackage HTTP\n * @author Geoffrey Sneddon\n * @author Steve Minutillo\n * @author Ryan McCue\n * @copyright 2007-2012 Geoffrey Sneddon, Steve Minutillo, Ryan McCue\n * @license http://www.opensource.org/licenses/bsd-license.php\n */\nclass SimplePie_IRI\n{\n\t/**\n\t * Scheme\n\t *\n\t * @var string\n\t */\n\tprotected $scheme = null;\n\n\t/**\n\t * User Information\n\t *\n\t * @var string\n\t */\n\tprotected $iuserinfo = null;\n\n\t/**\n\t * ihost\n\t *\n\t * @var string\n\t */\n\tprotected $ihost = null;\n\n\t/**\n\t * Port\n\t *\n\t * @var string\n\t */\n\tprotected $port = null;\n\n\t/**\n\t * ipath\n\t *\n\t * @var string\n\t */\n\tprotected $ipath = '';\n\n\t/**\n\t * iquery\n\t *\n\t * @var string\n\t */\n\tprotected $iquery = null;\n\n\t/**\n\t * ifragment\n\t *\n\t * @var string\n\t */\n\tprotected $ifragment = null;\n\n\t/**\n\t * Normalization database\n\t *\n\t * Each key is the scheme, each value is an array with each key as the IRI\n\t * part and value as the default value for that part.\n\t */\n\tprotected $normalization = array(\n\t\t'acap' => array(\n\t\t\t'port' => 674\n\t\t),\n\t\t'dict' => array(\n\t\t\t'port' => 2628\n\t\t),\n\t\t'file' => array(\n\t\t\t'ihost' => 'localhost'\n\t\t),\n\t\t'http' => array(\n\t\t\t'port' => 80,\n\t\t\t'ipath' => '/'\n\t\t),\n\t\t'https' => array(\n\t\t\t'port' => 443,\n\t\t\t'ipath' => '/'\n\t\t),\n\t);\n\n\t/**\n\t * Return the entire IRI when you try and read the object as a string\n\t *\n\t * @return string\n\t */\n\tpublic function __toString()\n\t{\n\t\treturn $this->get_iri();\n\t}\n\n\t/**\n\t * Overload __set() to provide access via properties\n\t *\n\t * @param string $name Property name\n\t * @param mixed $value Property value\n\t */\n\tpublic function __set($name, $value)\n\t{\n\t\tif (method_exists($this, 'set_' . $name))\n\t\t{\n\t\t\tcall_user_func(array($this, 'set_' . $name), $value);\n\t\t}\n\t\telseif (\n\t\t\t   $name === 'iauthority'\n\t\t\t|| $name === 'iuserinfo'\n\t\t\t|| $name === 'ihost'\n\t\t\t|| $name === 'ipath'\n\t\t\t|| $name === 'iquery'\n\t\t\t|| $name === 'ifragment'\n\t\t)\n\t\t{\n\t\t\tcall_user_func(array($this, 'set_' . substr($name, 1)), $value);\n\t\t}\n\t}\n\n\t/**\n\t * Overload __get() to provide access via properties\n\t *\n\t * @param string $name Property name\n\t * @return mixed\n\t */\n\tpublic function __get($name)\n\t{\n\t\t// isset() returns false for null, we don't want to do that\n\t\t// Also why we use array_key_exists below instead of isset()\n\t\t$props = get_object_vars($this);\n\n\t\tif (\n\t\t\t$name === 'iri' ||\n\t\t\t$name === 'uri' ||\n\t\t\t$name === 'iauthority' ||\n\t\t\t$name === 'authority'\n\t\t)\n\t\t{\n\t\t\t$return = $this->{\"get_$name\"}();\n\t\t}\n\t\telseif (array_key_exists($name, $props))\n\t\t{\n\t\t\t$return = $this->$name;\n\t\t}\n\t\t// host -> ihost\n\t\telseif (($prop = 'i' . $name) && array_key_exists($prop, $props))\n\t\t{\n\t\t\t$name = $prop;\n\t\t\t$return = $this->$prop;\n\t\t}\n\t\t// ischeme -> scheme\n\t\telseif (($prop = substr($name, 1)) && array_key_exists($prop, $props))\n\t\t{\n\t\t\t$name = $prop;\n\t\t\t$return = $this->$prop;\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttrigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE);\n\t\t\t$return = null;\n\t\t}\n\n\t\tif ($return === null && isset($this->normalization[$this->scheme][$name]))\n\t\t{\n\t\t\treturn $this->normalization[$this->scheme][$name];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn $return;\n\t\t}\n\t}\n\n\t/**\n\t * Overload __isset() to provide access via properties\n\t *\n\t * @param string $name Property name\n\t * @return bool\n\t */\n\tpublic function __isset($name)\n\t{\n\t\tif (method_exists($this, 'get_' . $name) || isset($this->$name))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Overload __unset() to provide access via properties\n\t *\n\t * @param string $name Property name\n\t */\n\tpublic function __unset($name)\n\t{\n\t\tif (method_exists($this, 'set_' . $name))\n\t\t{\n\t\t\tcall_user_func(array($this, 'set_' . $name), '');\n\t\t}\n\t}\n\n\t/**\n\t * Create a new IRI object, from a specified string\n\t *\n\t * @param string $iri\n\t */\n\tpublic function __construct($iri = null)\n\t{\n\t\t$this->set_iri($iri);\n\t}\n\n\t/**\n\t * Create a new IRI object by resolving a relative IRI\n\t *\n\t * Returns false if $base is not absolute, otherwise an IRI.\n\t *\n\t * @param IRI|string $base (Absolute) Base IRI\n\t * @param IRI|string $relative Relative IRI\n\t * @return IRI|false\n\t */\n\tpublic static function absolutize($base, $relative)\n\t{\n\t\tif (!($relative instanceof SimplePie_IRI))\n\t\t{\n\t\t\t$relative = new SimplePie_IRI($relative);\n\t\t}\n\t\tif (!$relative->is_valid())\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\telseif ($relative->scheme !== null)\n\t\t{\n\t\t\treturn clone $relative;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (!($base instanceof SimplePie_IRI))\n\t\t\t{\n\t\t\t\t$base = new SimplePie_IRI($base);\n\t\t\t}\n\t\t\tif ($base->scheme !== null && $base->is_valid())\n\t\t\t{\n\t\t\t\tif ($relative->get_iri() !== '')\n\t\t\t\t{\n\t\t\t\t\tif ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null)\n\t\t\t\t\t{\n\t\t\t\t\t\t$target = clone $relative;\n\t\t\t\t\t\t$target->scheme = $base->scheme;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$target = new SimplePie_IRI;\n\t\t\t\t\t\t$target->scheme = $base->scheme;\n\t\t\t\t\t\t$target->iuserinfo = $base->iuserinfo;\n\t\t\t\t\t\t$target->ihost = $base->ihost;\n\t\t\t\t\t\t$target->port = $base->port;\n\t\t\t\t\t\tif ($relative->ipath !== '')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ($relative->ipath[0] === '/')\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$target->ipath = $relative->ipath;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '')\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$target->ipath = '/' . $relative->ipath;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (($last_segment = strrpos($base->ipath, '/')) !== false)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$target->ipath = $relative->ipath;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$target->ipath = $target->remove_dot_segments($target->ipath);\n\t\t\t\t\t\t\t$target->iquery = $relative->iquery;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$target->ipath = $base->ipath;\n\t\t\t\t\t\t\tif ($relative->iquery !== null)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$target->iquery = $relative->iquery;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif ($base->iquery !== null)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$target->iquery = $base->iquery;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$target->ifragment = $relative->ifragment;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$target = clone $base;\n\t\t\t\t\t$target->ifragment = null;\n\t\t\t\t}\n\t\t\t\t$target->scheme_normalization();\n\t\t\t\treturn $target;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Parse an IRI into scheme/authority/path/query/fragment segments\n\t *\n\t * @param string $iri\n\t * @return array\n\t */\n\tprotected function parse_iri($iri)\n\t{\n\t\t$iri = trim($iri, \"\\x20\\x09\\x0A\\x0C\\x0D\");\n\t\tif (preg_match('/^((?P<scheme>[^:\\/?#]+):)?(\\/\\/(?P<authority>[^\\/?#]*))?(?P<path>[^?#]*)(\\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$/', $iri, $match))\n\t\t{\n\t\t\tif ($match[1] === '')\n\t\t\t{\n\t\t\t\t$match['scheme'] = null;\n\t\t\t}\n\t\t\tif (!isset($match[3]) || $match[3] === '')\n\t\t\t{\n\t\t\t\t$match['authority'] = null;\n\t\t\t}\n\t\t\tif (!isset($match[5]))\n\t\t\t{\n\t\t\t\t$match['path'] = '';\n\t\t\t}\n\t\t\tif (!isset($match[6]) || $match[6] === '')\n\t\t\t{\n\t\t\t\t$match['query'] = null;\n\t\t\t}\n\t\t\tif (!isset($match[8]) || $match[8] === '')\n\t\t\t{\n\t\t\t\t$match['fragment'] = null;\n\t\t\t}\n\t\t\treturn $match;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// This can occur when a paragraph is accidentally parsed as a URI\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Remove dot segments from a path\n\t *\n\t * @param string $input\n\t * @return string\n\t */\n\tprotected function remove_dot_segments($input)\n\t{\n\t\t$output = '';\n\t\twhile (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')\n\t\t{\n\t\t\t// A: If the input buffer begins with a prefix of \"../\" or \"./\", then remove that prefix from the input buffer; otherwise,\n\t\t\tif (strpos($input, '../') === 0)\n\t\t\t{\n\t\t\t\t$input = substr($input, 3);\n\t\t\t}\n\t\t\telseif (strpos($input, './') === 0)\n\t\t\t{\n\t\t\t\t$input = substr($input, 2);\n\t\t\t}\n\t\t\t// B: if the input buffer begins with a prefix of \"/./\" or \"/.\", where \".\" is a complete path segment, then replace that prefix with \"/\" in the input buffer; otherwise,\n\t\t\telseif (strpos($input, '/./') === 0)\n\t\t\t{\n\t\t\t\t$input = substr($input, 2);\n\t\t\t}\n\t\t\telseif ($input === '/.')\n\t\t\t{\n\t\t\t\t$input = '/';\n\t\t\t}\n\t\t\t// C: if the input buffer begins with a prefix of \"/../\" or \"/..\", where \"..\" is a complete path segment, then replace that prefix with \"/\" in the input buffer and remove the last segment and its preceding \"/\" (if any) from the output buffer; otherwise,\n\t\t\telseif (strpos($input, '/../') === 0)\n\t\t\t{\n\t\t\t\t$input = substr($input, 3);\n\t\t\t\t$output = substr_replace($output, '', strrpos($output, '/'));\n\t\t\t}\n\t\t\telseif ($input === '/..')\n\t\t\t{\n\t\t\t\t$input = '/';\n\t\t\t\t$output = substr_replace($output, '', strrpos($output, '/'));\n\t\t\t}\n\t\t\t// D: if the input buffer consists only of \".\" or \"..\", then remove that from the input buffer; otherwise,\n\t\t\telseif ($input === '.' || $input === '..')\n\t\t\t{\n\t\t\t\t$input = '';\n\t\t\t}\n\t\t\t// E: move the first path segment in the input buffer to the end of the output buffer, including the initial \"/\" character (if any) and any subsequent characters up to, but not including, the next \"/\" character or the end of the input buffer\n\t\t\telseif (($pos = strpos($input, '/', 1)) !== false)\n\t\t\t{\n\t\t\t\t$output .= substr($input, 0, $pos);\n\t\t\t\t$input = substr_replace($input, '', 0, $pos);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$output .= $input;\n\t\t\t\t$input = '';\n\t\t\t}\n\t\t}\n\t\treturn $output . $input;\n\t}\n\n\t/**\n\t * Replace invalid character with percent encoding\n\t *\n\t * @param string $string Input string\n\t * @param string $extra_chars Valid characters not in iunreserved or\n\t *                            iprivate (this is ASCII-only)\n\t * @param bool $iprivate Allow iprivate\n\t * @return string\n\t */\n\tprotected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false)\n\t{\n\t\t// Normalize as many pct-encoded sections as possible\n\t\t$string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array($this, 'remove_iunreserved_percent_encoded'), $string);\n\n\t\t// Replace invalid percent characters\n\t\t$string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);\n\n\t\t// Add unreserved and % to $extra_chars (the latter is safe because all\n\t\t// pct-encoded sections are now valid).\n\t\t$extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';\n\n\t\t// Now replace any bytes that aren't allowed with their pct-encoded versions\n\t\t$position = 0;\n\t\t$strlen = strlen($string);\n\t\twhile (($position += strspn($string, $extra_chars, $position)) < $strlen)\n\t\t{\n\t\t\t$value = ord($string[$position]);\n\n\t\t\t// Start position\n\t\t\t$start = $position;\n\n\t\t\t// By default we are valid\n\t\t\t$valid = true;\n\n\t\t\t// No one byte sequences are valid due to the while.\n\t\t\t// Two byte sequence:\n\t\t\tif (($value & 0xE0) === 0xC0)\n\t\t\t{\n\t\t\t\t$character = ($value & 0x1F) << 6;\n\t\t\t\t$length = 2;\n\t\t\t\t$remaining = 1;\n\t\t\t}\n\t\t\t// Three byte sequence:\n\t\t\telseif (($value & 0xF0) === 0xE0)\n\t\t\t{\n\t\t\t\t$character = ($value & 0x0F) << 12;\n\t\t\t\t$length = 3;\n\t\t\t\t$remaining = 2;\n\t\t\t}\n\t\t\t// Four byte sequence:\n\t\t\telseif (($value & 0xF8) === 0xF0)\n\t\t\t{\n\t\t\t\t$character = ($value & 0x07) << 18;\n\t\t\t\t$length = 4;\n\t\t\t\t$remaining = 3;\n\t\t\t}\n\t\t\t// Invalid byte:\n\t\t\telse\n\t\t\t{\n\t\t\t\t$valid = false;\n\t\t\t\t$length = 1;\n\t\t\t\t$remaining = 0;\n\t\t\t}\n\n\t\t\tif ($remaining)\n\t\t\t{\n\t\t\t\tif ($position + $length <= $strlen)\n\t\t\t\t{\n\t\t\t\t\tfor ($position++; $remaining; $position++)\n\t\t\t\t\t{\n\t\t\t\t\t\t$value = ord($string[$position]);\n\n\t\t\t\t\t\t// Check that the byte is valid, then add it to the character:\n\t\t\t\t\t\tif (($value & 0xC0) === 0x80)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$character |= ($value & 0x3F) << (--$remaining * 6);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// If it is invalid, count the sequence as invalid and reprocess the current byte:\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$valid = false;\n\t\t\t\t\t\t\t$position--;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$position = $strlen - 1;\n\t\t\t\t\t$valid = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Percent encode anything invalid or not in ucschar\n\t\t\tif (\n\t\t\t\t// Invalid sequences\n\t\t\t\t!$valid\n\t\t\t\t// Non-shortest form sequences are invalid\n\t\t\t\t|| $length > 1 && $character <= 0x7F\n\t\t\t\t|| $length > 2 && $character <= 0x7FF\n\t\t\t\t|| $length > 3 && $character <= 0xFFFF\n\t\t\t\t// Outside of range of ucschar codepoints\n\t\t\t\t// Noncharacters\n\t\t\t\t|| ($character & 0xFFFE) === 0xFFFE\n\t\t\t\t|| $character >= 0xFDD0 && $character <= 0xFDEF\n\t\t\t\t|| (\n\t\t\t\t\t// Everything else not in ucschar\n\t\t\t\t\t   $character > 0xD7FF && $character < 0xF900\n\t\t\t\t\t|| $character < 0xA0\n\t\t\t\t\t|| $character > 0xEFFFD\n\t\t\t\t)\n\t\t\t\t&& (\n\t\t\t\t\t// Everything not in iprivate, if it applies\n\t\t\t\t\t   !$iprivate\n\t\t\t\t\t|| $character < 0xE000\n\t\t\t\t\t|| $character > 0x10FFFD\n\t\t\t\t)\n\t\t\t)\n\t\t\t{\n\t\t\t\t// If we were a character, pretend we weren't, but rather an error.\n\t\t\t\tif ($valid)\n\t\t\t\t\t$position--;\n\n\t\t\t\tfor ($j = $start; $j <= $position; $j++)\n\t\t\t\t{\n\t\t\t\t\t$string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);\n\t\t\t\t\t$j += 2;\n\t\t\t\t\t$position += 2;\n\t\t\t\t\t$strlen += 2;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $string;\n\t}\n\n\t/**\n\t * Callback function for preg_replace_callback.\n\t *\n\t * Removes sequences of percent encoded bytes that represent UTF-8\n\t * encoded characters in iunreserved\n\t *\n\t * @param array $match PCRE match\n\t * @return string Replacement\n\t */\n\tprotected function remove_iunreserved_percent_encoded($match)\n\t{\n\t\t// As we just have valid percent encoded sequences we can just explode\n\t\t// and ignore the first member of the returned array (an empty string).\n\t\t$bytes = explode('%', $match[0]);\n\n\t\t// Initialize the new string (this is what will be returned) and that\n\t\t// there are no bytes remaining in the current sequence (unsurprising\n\t\t// at the first byte!).\n\t\t$string = '';\n\t\t$remaining = 0;\n\n\t\t// Loop over each and every byte, and set $value to its value\n\t\tfor ($i = 1, $len = count($bytes); $i < $len; $i++)\n\t\t{\n\t\t\t$value = hexdec($bytes[$i]);\n\n\t\t\t// If we're the first byte of sequence:\n\t\t\tif (!$remaining)\n\t\t\t{\n\t\t\t\t// Start position\n\t\t\t\t$start = $i;\n\n\t\t\t\t// By default we are valid\n\t\t\t\t$valid = true;\n\n\t\t\t\t// One byte sequence:\n\t\t\t\tif ($value <= 0x7F)\n\t\t\t\t{\n\t\t\t\t\t$character = $value;\n\t\t\t\t\t$length = 1;\n\t\t\t\t}\n\t\t\t\t// Two byte sequence:\n\t\t\t\telseif (($value & 0xE0) === 0xC0)\n\t\t\t\t{\n\t\t\t\t\t$character = ($value & 0x1F) << 6;\n\t\t\t\t\t$length = 2;\n\t\t\t\t\t$remaining = 1;\n\t\t\t\t}\n\t\t\t\t// Three byte sequence:\n\t\t\t\telseif (($value & 0xF0) === 0xE0)\n\t\t\t\t{\n\t\t\t\t\t$character = ($value & 0x0F) << 12;\n\t\t\t\t\t$length = 3;\n\t\t\t\t\t$remaining = 2;\n\t\t\t\t}\n\t\t\t\t// Four byte sequence:\n\t\t\t\telseif (($value & 0xF8) === 0xF0)\n\t\t\t\t{\n\t\t\t\t\t$character = ($value & 0x07) << 18;\n\t\t\t\t\t$length = 4;\n\t\t\t\t\t$remaining = 3;\n\t\t\t\t}\n\t\t\t\t// Invalid byte:\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$valid = false;\n\t\t\t\t\t$remaining = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Continuation byte:\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Check that the byte is valid, then add it to the character:\n\t\t\t\tif (($value & 0xC0) === 0x80)\n\t\t\t\t{\n\t\t\t\t\t$remaining--;\n\t\t\t\t\t$character |= ($value & 0x3F) << ($remaining * 6);\n\t\t\t\t}\n\t\t\t\t// If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$valid = false;\n\t\t\t\t\t$remaining = 0;\n\t\t\t\t\t$i--;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If we've reached the end of the current byte sequence, append it to Unicode::$data\n\t\t\tif (!$remaining)\n\t\t\t{\n\t\t\t\t// Percent encode anything invalid or not in iunreserved\n\t\t\t\tif (\n\t\t\t\t\t// Invalid sequences\n\t\t\t\t\t!$valid\n\t\t\t\t\t// Non-shortest form sequences are invalid\n\t\t\t\t\t|| $length > 1 && $character <= 0x7F\n\t\t\t\t\t|| $length > 2 && $character <= 0x7FF\n\t\t\t\t\t|| $length > 3 && $character <= 0xFFFF\n\t\t\t\t\t// Outside of range of iunreserved codepoints\n\t\t\t\t\t|| $character < 0x2D\n\t\t\t\t\t|| $character > 0xEFFFD\n\t\t\t\t\t// Noncharacters\n\t\t\t\t\t|| ($character & 0xFFFE) === 0xFFFE\n\t\t\t\t\t|| $character >= 0xFDD0 && $character <= 0xFDEF\n\t\t\t\t\t// Everything else not in iunreserved (this is all BMP)\n\t\t\t\t\t|| $character === 0x2F\n\t\t\t\t\t|| $character > 0x39 && $character < 0x41\n\t\t\t\t\t|| $character > 0x5A && $character < 0x61\n\t\t\t\t\t|| $character > 0x7A && $character < 0x7E\n\t\t\t\t\t|| $character > 0x7E && $character < 0xA0\n\t\t\t\t\t|| $character > 0xD7FF && $character < 0xF900\n\t\t\t\t)\n\t\t\t\t{\n\t\t\t\t\tfor ($j = $start; $j <= $i; $j++)\n\t\t\t\t\t{\n\t\t\t\t\t\t$string .= '%' . strtoupper($bytes[$j]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfor ($j = $start; $j <= $i; $j++)\n\t\t\t\t\t{\n\t\t\t\t\t\t$string .= chr(hexdec($bytes[$j]));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If we have any bytes left over they are invalid (i.e., we are\n\t\t// mid-way through a multi-byte sequence)\n\t\tif ($remaining)\n\t\t{\n\t\t\tfor ($j = $start; $j < $len; $j++)\n\t\t\t{\n\t\t\t\t$string .= '%' . strtoupper($bytes[$j]);\n\t\t\t}\n\t\t}\n\n\t\treturn $string;\n\t}\n\n\tprotected function scheme_normalization()\n\t{\n\t\tif (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo'])\n\t\t{\n\t\t\t$this->iuserinfo = null;\n\t\t}\n\t\tif (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost'])\n\t\t{\n\t\t\t$this->ihost = null;\n\t\t}\n\t\tif (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port'])\n\t\t{\n\t\t\t$this->port = null;\n\t\t}\n\t\tif (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath'])\n\t\t{\n\t\t\t$this->ipath = '';\n\t\t}\n\t\tif (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery'])\n\t\t{\n\t\t\t$this->iquery = null;\n\t\t}\n\t\tif (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment'])\n\t\t{\n\t\t\t$this->ifragment = null;\n\t\t}\n\t}\n\n\t/**\n\t * Check if the object represents a valid IRI. This needs to be done on each\n\t * call as some things change depending on another part of the IRI.\n\t *\n\t * @return bool\n\t */\n\tpublic function is_valid()\n\t{\n\t\t$isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null;\n\t\tif ($this->ipath !== '' &&\n\t\t\t(\n\t\t\t\t$isauthority && (\n\t\t\t\t\t$this->ipath[0] !== '/' ||\n\t\t\t\t\tsubstr($this->ipath, 0, 2) === '//'\n\t\t\t\t) ||\n\t\t\t\t(\n\t\t\t\t\t$this->scheme === null &&\n\t\t\t\t\t!$isauthority &&\n\t\t\t\t\tstrpos($this->ipath, ':') !== false &&\n\t\t\t\t\t(strpos($this->ipath, '/') === false ? true : strpos($this->ipath, ':') < strpos($this->ipath, '/'))\n\t\t\t\t)\n\t\t\t)\n\t\t)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Set the entire IRI. Returns true on success, false on failure (if there\n\t * are any invalid characters).\n\t *\n\t * @param string $iri\n\t * @return bool\n\t */\n\tpublic function set_iri($iri)\n\t{\n\t\tstatic $cache;\n\t\tif (!$cache)\n\t\t{\n\t\t\t$cache = array();\n\t\t}\n\n\t\tif ($iri === null)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\telseif (isset($cache[$iri]))\n\t\t{\n\t\t\tlist($this->scheme,\n\t\t\t\t $this->iuserinfo,\n\t\t\t\t $this->ihost,\n\t\t\t\t $this->port,\n\t\t\t\t $this->ipath,\n\t\t\t\t $this->iquery,\n\t\t\t\t $this->ifragment,\n\t\t\t\t $return) = $cache[$iri];\n\t\t\treturn $return;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$parsed = $this->parse_iri((string) $iri);\n\t\t\tif (!$parsed)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t$return = $this->set_scheme($parsed['scheme'])\n\t\t\t\t&& $this->set_authority($parsed['authority'])\n\t\t\t\t&& $this->set_path($parsed['path'])\n\t\t\t\t&& $this->set_query($parsed['query'])\n\t\t\t\t&& $this->set_fragment($parsed['fragment']);\n\n\t\t\t$cache[$iri] = array($this->scheme,\n\t\t\t\t\t\t\t\t $this->iuserinfo,\n\t\t\t\t\t\t\t\t $this->ihost,\n\t\t\t\t\t\t\t\t $this->port,\n\t\t\t\t\t\t\t\t $this->ipath,\n\t\t\t\t\t\t\t\t $this->iquery,\n\t\t\t\t\t\t\t\t $this->ifragment,\n\t\t\t\t\t\t\t\t $return);\n\t\t\treturn $return;\n\t\t}\n\t}\n\n\t/**\n\t * Set the scheme. Returns true on success, false on failure (if there are\n\t * any invalid characters).\n\t *\n\t * @param string $scheme\n\t * @return bool\n\t */\n\tpublic function set_scheme($scheme)\n\t{\n\t\tif ($scheme === null)\n\t\t{\n\t\t\t$this->scheme = null;\n\t\t}\n\t\telseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\\-.]*$/', $scheme))\n\t\t{\n\t\t\t$this->scheme = null;\n\t\t\treturn false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->scheme = strtolower($scheme);\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Set the authority. Returns true on success, false on failure (if there are\n\t * any invalid characters).\n\t *\n\t * @param string $authority\n\t * @return bool\n\t */\n\tpublic function set_authority($authority)\n\t{\n\t\tstatic $cache;\n\t\tif (!$cache)\n\t\t\t$cache = array();\n\n\t\tif ($authority === null)\n\t\t{\n\t\t\t$this->iuserinfo = null;\n\t\t\t$this->ihost = null;\n\t\t\t$this->port = null;\n\t\t\treturn true;\n\t\t}\n\t\telseif (isset($cache[$authority]))\n\t\t{\n\t\t\tlist($this->iuserinfo,\n\t\t\t\t $this->ihost,\n\t\t\t\t $this->port,\n\t\t\t\t $return) = $cache[$authority];\n\n\t\t\treturn $return;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$remaining = $authority;\n\t\t\tif (($iuserinfo_end = strrpos($remaining, '@')) !== false)\n\t\t\t{\n\t\t\t\t$iuserinfo = substr($remaining, 0, $iuserinfo_end);\n\t\t\t\t$remaining = substr($remaining, $iuserinfo_end + 1);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$iuserinfo = null;\n\t\t\t}\n\t\t\tif (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false)\n\t\t\t{\n\t\t\t\tif (($port = substr($remaining, $port_start + 1)) === false)\n\t\t\t\t{\n\t\t\t\t\t$port = null;\n\t\t\t\t}\n\t\t\t\t$remaining = substr($remaining, 0, $port_start);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$port = null;\n\t\t\t}\n\n\t\t\t$return = $this->set_userinfo($iuserinfo) &&\n\t\t\t\t\t  $this->set_host($remaining) &&\n\t\t\t\t\t  $this->set_port($port);\n\n\t\t\t$cache[$authority] = array($this->iuserinfo,\n\t\t\t\t\t\t\t\t\t   $this->ihost,\n\t\t\t\t\t\t\t\t\t   $this->port,\n\t\t\t\t\t\t\t\t\t   $return);\n\n\t\t\treturn $return;\n\t\t}\n\t}\n\n\t/**\n\t * Set the iuserinfo.\n\t *\n\t * @param string $iuserinfo\n\t * @return bool\n\t */\n\tpublic function set_userinfo($iuserinfo)\n\t{\n\t\tif ($iuserinfo === null)\n\t\t{\n\t\t\t$this->iuserinfo = null;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\\'()*+,;=:');\n\t\t\t$this->scheme_normalization();\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Set the ihost. Returns true on success, false on failure (if there are\n\t * any invalid characters).\n\t *\n\t * @param string $ihost\n\t * @return bool\n\t */\n\tpublic function set_host($ihost)\n\t{\n\t\tif ($ihost === null)\n\t\t{\n\t\t\t$this->ihost = null;\n\t\t\treturn true;\n\t\t}\n\t\telseif (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']')\n\t\t{\n\t\t\tif (SimplePie_Net_IPv6::check_ipv6(substr($ihost, 1, -1)))\n\t\t\t{\n\t\t\t\t$this->ihost = '[' . SimplePie_Net_IPv6::compress(substr($ihost, 1, -1)) . ']';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->ihost = null;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\\'()*+,;=');\n\n\t\t\t// Lowercase, but ignore pct-encoded sections (as they should\n\t\t\t// remain uppercase). This must be done after the previous step\n\t\t\t// as that can add unescaped characters.\n\t\t\t$position = 0;\n\t\t\t$strlen = strlen($ihost);\n\t\t\twhile (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen)\n\t\t\t{\n\t\t\t\tif ($ihost[$position] === '%')\n\t\t\t\t{\n\t\t\t\t\t$position += 3;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$ihost[$position] = strtolower($ihost[$position]);\n\t\t\t\t\t$position++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this->ihost = $ihost;\n\t\t}\n\n\t\t$this->scheme_normalization();\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Set the port. Returns true on success, false on failure (if there are\n\t * any invalid characters).\n\t *\n\t * @param string $port\n\t * @return bool\n\t */\n\tpublic function set_port($port)\n\t{\n\t\tif ($port === null)\n\t\t{\n\t\t\t$this->port = null;\n\t\t\treturn true;\n\t\t}\n\t\telseif (strspn($port, '0123456789') === strlen($port))\n\t\t{\n\t\t\t$this->port = (int) $port;\n\t\t\t$this->scheme_normalization();\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->port = null;\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Set the ipath.\n\t *\n\t * @param string $ipath\n\t * @return bool\n\t */\n\tpublic function set_path($ipath)\n\t{\n\t\tstatic $cache;\n\t\tif (!$cache)\n\t\t{\n\t\t\t$cache = array();\n\t\t}\n\n\t\t$ipath = (string) $ipath;\n\n\t\tif (isset($cache[$ipath]))\n\t\t{\n\t\t\t$this->ipath = $cache[$ipath][(int) ($this->scheme !== null)];\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\\'()*+,;=@:/');\n\t\t\t$removed = $this->remove_dot_segments($valid);\n\n\t\t\t$cache[$ipath] = array($valid, $removed);\n\t\t\t$this->ipath =  ($this->scheme !== null) ? $removed : $valid;\n\t\t}\n\n\t\t$this->scheme_normalization();\n\t\treturn true;\n\t}\n\n\t/**\n\t * Set the iquery.\n\t *\n\t * @param string $iquery\n\t * @return bool\n\t */\n\tpublic function set_query($iquery)\n\t{\n\t\tif ($iquery === null)\n\t\t{\n\t\t\t$this->iquery = null;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\\'()*+,;=:@/?', true);\n\t\t\t$this->scheme_normalization();\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Set the ifragment.\n\t *\n\t * @param string $ifragment\n\t * @return bool\n\t */\n\tpublic function set_fragment($ifragment)\n\t{\n\t\tif ($ifragment === null)\n\t\t{\n\t\t\t$this->ifragment = null;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\\'()*+,;=:@/?');\n\t\t\t$this->scheme_normalization();\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Convert an IRI to a URI (or parts thereof)\n\t *\n\t * @return string\n\t */\n\tpublic function to_uri($string)\n\t{\n\t\tstatic $non_ascii;\n\t\tif (!$non_ascii)\n\t\t{\n\t\t\t$non_ascii = implode('', range(\"\\x80\", \"\\xFF\"));\n\t\t}\n\n\t\t$position = 0;\n\t\t$strlen = strlen($string);\n\t\twhile (($position += strcspn($string, $non_ascii, $position)) < $strlen)\n\t\t{\n\t\t\t$string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1);\n\t\t\t$position += 3;\n\t\t\t$strlen += 2;\n\t\t}\n\n\t\treturn $string;\n\t}\n\n\t/**\n\t * Get the complete IRI\n\t *\n\t * @return string\n\t */\n\tpublic function get_iri()\n\t{\n\t\tif (!$this->is_valid())\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\t$iri = '';\n\t\tif ($this->scheme !== null)\n\t\t{\n\t\t\t$iri .= $this->scheme . ':';\n\t\t}\n\t\tif (($iauthority = $this->get_iauthority()) !== null)\n\t\t{\n\t\t\t$iri .= '//' . $iauthority;\n\t\t}\n\t\tif ($this->ipath !== '')\n\t\t{\n\t\t\t$iri .= $this->ipath;\n\t\t}\n\t\telseif (!empty($this->normalization[$this->scheme]['ipath']) && $iauthority !== null && $iauthority !== '')\n\t\t{\n\t\t\t$iri .= $this->normalization[$this->scheme]['ipath'];\n\t\t}\n\t\tif ($this->iquery !== null)\n\t\t{\n\t\t\t$iri .= '?' . $this->iquery;\n\t\t}\n\t\tif ($this->ifragment !== null)\n\t\t{\n\t\t\t$iri .= '#' . $this->ifragment;\n\t\t}\n\n\t\treturn $iri;\n\t}\n\n\t/**\n\t * Get the complete URI\n\t *\n\t * @return string\n\t */\n\tpublic function get_uri()\n\t{\n\t\treturn $this->to_uri($this->get_iri());\n\t}\n\n\t/**\n\t * Get the complete iauthority\n\t *\n\t * @return string\n\t */\n\tprotected function get_iauthority()\n\t{\n\t\tif ($this->iuserinfo !== null || $this->ihost !== null || $this->port !== null)\n\t\t{\n\t\t\t$iauthority = '';\n\t\t\tif ($this->iuserinfo !== null)\n\t\t\t{\n\t\t\t\t$iauthority .= $this->iuserinfo . '@';\n\t\t\t}\n\t\t\tif ($this->ihost !== null)\n\t\t\t{\n\t\t\t\t$iauthority .= $this->ihost;\n\t\t\t}\n\t\t\tif ($this->port !== null)\n\t\t\t{\n\t\t\t\t$iauthority .= ':' . $this->port;\n\t\t\t}\n\t\t\treturn $iauthority;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the complete authority\n\t *\n\t * @return string\n\t */\n\tprotected function get_authority()\n\t{\n\t\t$iauthority = $this->get_iauthority();\n\t\tif (is_string($iauthority))\n\t\t\treturn $this->to_uri($iauthority);\n\t\telse\n\t\t\treturn $iauthority;\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Item.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n\n/**\n * Manages all item-related data\n *\n * Used by {@see SimplePie::get_item()} and {@see SimplePie::get_items()}\n *\n * This class can be overloaded with {@see SimplePie::set_item_class()}\n *\n * @package SimplePie\n * @subpackage API\n */\nclass SimplePie_Item\n{\n\t/**\n\t * Parent feed\n\t *\n\t * @access private\n\t * @var SimplePie\n\t */\n\tvar $feed;\n\n\t/**\n\t * Raw data\n\t *\n\t * @access private\n\t * @var array\n\t */\n\tvar $data = array();\n\n\t/**\n\t * Registry object\n\t *\n\t * @see set_registry\n\t * @var SimplePie_Registry\n\t */\n\tprotected $registry;\n\n\t/**\n\t * Create a new item object\n\t *\n\t * This is usually used by {@see SimplePie::get_items} and\n\t * {@see SimplePie::get_item}. Avoid creating this manually.\n\t *\n\t * @param SimplePie $feed Parent feed\n\t * @param array $data Raw data\n\t */\n\tpublic function __construct($feed, $data)\n\t{\n\t\t$this->feed = $feed;\n\t\t$this->data = $data;\n\t}\n\n\t/**\n\t * Set the registry handler\n\t *\n\t * This is usually used by {@see SimplePie_Registry::create}\n\t *\n\t * @since 1.3\n\t * @param SimplePie_Registry $registry\n\t */\n\tpublic function set_registry(SimplePie_Registry $registry)\n\t{\n\t\t$this->registry = $registry;\n\t}\n\n\t/**\n\t * Get a string representation of the item\n\t *\n\t * @return string\n\t */\n\tpublic function __toString()\n\t{\n\t\treturn md5(serialize($this->data));\n\t}\n\n\t/**\n\t * Remove items that link back to this before destroying this object\n\t */\n\tpublic function __destruct()\n\t{\n\t\tif ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))\n\t\t{\n\t\t\tunset($this->feed);\n\t\t}\n\t}\n\n\t/**\n\t * Get data for an item-level element\n\t *\n\t * This method allows you to get access to ANY element/attribute that is a\n\t * sub-element of the item/entry tag.\n\t *\n\t * See {@see SimplePie::get_feed_tags()} for a description of the return value\n\t *\n\t * @since 1.0\n\t * @see http://simplepie.org/wiki/faq/supported_xml_namespaces\n\t * @param string $namespace The URL of the XML namespace of the elements you're trying to access\n\t * @param string $tag Tag name\n\t * @return array\n\t */\n\tpublic function get_item_tags($namespace, $tag)\n\t{\n\t\tif (isset($this->data['child'][$namespace][$tag]))\n\t\t{\n\t\t\treturn $this->data['child'][$namespace][$tag];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the base URL value from the parent feed\n\t *\n\t * Uses `<xml:base>`\n\t *\n\t * @param array $element\n\t * @return string\n\t */\n\tpublic function get_base($element = array())\n\t{\n\t\treturn $this->feed->get_base($element);\n\t}\n\n\t/**\n\t * Sanitize feed data\n\t *\n\t * @access private\n\t * @see SimplePie::sanitize()\n\t * @param string $data Data to sanitize\n\t * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants\n\t * @param string $base Base URL to resolve URLs against\n\t * @return string Sanitized data\n\t */\n\tpublic function sanitize($data, $type, $base = '')\n\t{\n\t\treturn $this->feed->sanitize($data, $type, $base);\n\t}\n\n\t/**\n\t * Get the parent feed\n\t *\n\t * Note: this may not work as you think for multifeeds!\n\t *\n\t * @link http://simplepie.org/faq/typical_multifeed_gotchas#missing_data_from_feed\n\t * @since 1.0\n\t * @return SimplePie\n\t */\n\tpublic function get_feed()\n\t{\n\t\treturn $this->feed;\n\t}\n\n\t/**\n\t * Get the unique identifier for the item\n\t *\n\t * This is usually used when writing code to check for new items in a feed.\n\t *\n\t * Uses `<atom:id>`, `<guid>`, `<dc:identifier>` or the `about` attribute\n\t * for RDF. If none of these are supplied (or `$hash` is true), creates an\n\t * MD5 hash based on the permalink and title. If either of those are not\n\t * supplied, creates a hash based on the full feed data.\n\t *\n\t * @since Beta 2\n\t * @param boolean $hash Should we force using a hash instead of the supplied ID?\n\t * @return string\n\t */\n\tpublic function get_id($hash = false)\n\t{\n\t\tif (!$hash)\n\t\t{\n\t\t\tif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))\n\t\t\t{\n\t\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))\n\t\t\t{\n\t\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))\n\t\t\t{\n\t\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))\n\t\t\t{\n\t\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))\n\t\t\t{\n\t\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\telseif (isset($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about']))\n\t\t\t{\n\t\t\t\treturn $this->sanitize($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\telseif (($return = $this->get_permalink()) !== null)\n\t\t\t{\n\t\t\t\treturn $return;\n\t\t\t}\n\t\t\telseif (($return = $this->get_title()) !== null)\n\t\t\t{\n\t\t\t\treturn $return;\n\t\t\t}\n\t\t}\n\t\tif ($this->get_permalink() !== null || $this->get_title() !== null)\n\t\t{\n\t\t\treturn md5($this->get_permalink() . $this->get_title());\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn md5(serialize($this->data));\n\t\t}\n\t}\n\n\t/**\n\t * Get the title of the item\n\t *\n\t * Uses `<atom:title>`, `<title>` or `<dc:title>`\n\t *\n\t * @since Beta 2 (previously called `get_item_title` since 0.8)\n\t * @return string|null\n\t */\n\tpublic function get_title()\n\t{\n\t\tif (!isset($this->data['title']))\n\t\t{\n\t\t\tif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))\n\t\t\t{\n\t\t\t\t$this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))\n\t\t\t{\n\t\t\t\t$this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))\n\t\t\t{\n\t\t\t\t$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))\n\t\t\t{\n\t\t\t\t$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))\n\t\t\t{\n\t\t\t\t$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))\n\t\t\t{\n\t\t\t\t$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))\n\t\t\t{\n\t\t\t\t$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->data['title'] = null;\n\t\t\t}\n\t\t}\n\t\treturn $this->data['title'];\n\t}\n\n\t/**\n\t * Get the content for the item\n\t *\n\t * Prefers summaries over full content , but will return full content if a\n\t * summary does not exist.\n\t *\n\t * To prefer full content instead, use {@see get_content}\n\t *\n\t * Uses `<atom:summary>`, `<description>`, `<dc:description>` or\n\t * `<itunes:subtitle>`\n\t *\n\t * @since 0.8\n\t * @param boolean $description_only Should we avoid falling back to the content?\n\t * @return string|null\n\t */\n\tpublic function get_description($description_only = false)\n\t{\n\t\tif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML);\n\t\t}\n\n\t\telseif (!$description_only)\n\t\t{\n\t\t\treturn $this->get_content(true);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the content for the item\n\t *\n\t * Prefers full content over summaries, but will return a summary if full\n\t * content does not exist.\n\t *\n\t * To prefer summaries instead, use {@see get_description}\n\t *\n\t * Uses `<atom:content>` or `<content:encoded>` (RSS 1.0 Content Module)\n\t *\n\t * @since 1.0\n\t * @param boolean $content_only Should we avoid falling back to the description?\n\t * @return string|null\n\t */\n\tpublic function get_content($content_only = false)\n\t{\n\t\tif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_content_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif (!$content_only)\n\t\t{\n\t\t\treturn $this->get_description(true);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get a category for the item\n\t *\n\t * @since Beta 3 (previously called `get_categories()` since Beta 2)\n\t * @param int $key The category that you want to return.  Remember that arrays begin with 0, not 1\n\t * @return SimplePie_Category|null\n\t */\n\tpublic function get_category($key = 0)\n\t{\n\t\t$categories = $this->get_categories();\n\t\tif (isset($categories[$key]))\n\t\t{\n\t\t\treturn $categories[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all categories for the item\n\t *\n\t * Uses `<atom:category>`, `<category>` or `<dc:subject>`\n\t *\n\t * @since Beta 3\n\t * @return array|null List of {@see SimplePie_Category} objects\n\t */\n\tpublic function get_categories()\n\t{\n\t\t$categories = array();\n\n\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)\n\t\t{\n\t\t\t$term = null;\n\t\t\t$scheme = null;\n\t\t\t$label = null;\n\t\t\tif (isset($category['attribs']['']['term']))\n\t\t\t{\n\t\t\t\t$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($category['attribs']['']['scheme']))\n\t\t\t{\n\t\t\t\t$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($category['attribs']['']['label']))\n\t\t\t{\n\t\t\t\t$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\t$categories[] = $this->registry->create('Category', array($term, $scheme, $label));\n\t\t}\n\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)\n\t\t{\n\t\t\t// This is really the label, but keep this as the term also for BC.\n\t\t\t// Label will also work on retrieving because that falls back to term.\n\t\t\t$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\tif (isset($category['attribs']['']['domain']))\n\t\t\t{\n\t\t\t\t$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$scheme = null;\n\t\t\t}\n\t\t\t$categories[] = $this->registry->create('Category', array($term, $scheme, null));\n\t\t}\n\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)\n\t\t{\n\t\t\t$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)\n\t\t{\n\t\t\t$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\n\t\tif (!empty($categories))\n\t\t{\n\t\t\treturn array_unique($categories);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get an author for the item\n\t *\n\t * @since Beta 2\n\t * @param int $key The author that you want to return.  Remember that arrays begin with 0, not 1\n\t * @return SimplePie_Author|null\n\t */\n\tpublic function get_author($key = 0)\n\t{\n\t\t$authors = $this->get_authors();\n\t\tif (isset($authors[$key]))\n\t\t{\n\t\t\treturn $authors[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get a contributor for the item\n\t *\n\t * @since 1.1\n\t * @param int $key The contrbutor that you want to return.  Remember that arrays begin with 0, not 1\n\t * @return SimplePie_Author|null\n\t */\n\tpublic function get_contributor($key = 0)\n\t{\n\t\t$contributors = $this->get_contributors();\n\t\tif (isset($contributors[$key]))\n\t\t{\n\t\t\treturn $contributors[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all contributors for the item\n\t *\n\t * Uses `<atom:contributor>`\n\t *\n\t * @since 1.1\n\t * @return array|null List of {@see SimplePie_Author} objects\n\t */\n\tpublic function get_contributors()\n\t{\n\t\t$contributors = array();\n\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)\n\t\t{\n\t\t\t$name = null;\n\t\t\t$uri = null;\n\t\t\t$email = null;\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))\n\t\t\t{\n\t\t\t\t$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))\n\t\t\t{\n\t\t\t\t$uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));\n\t\t\t}\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))\n\t\t\t{\n\t\t\t\t$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif ($name !== null || $email !== null || $uri !== null)\n\t\t\t{\n\t\t\t\t$contributors[] = $this->registry->create('Author', array($name, $uri, $email));\n\t\t\t}\n\t\t}\n\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)\n\t\t{\n\t\t\t$name = null;\n\t\t\t$url = null;\n\t\t\t$email = null;\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))\n\t\t\t{\n\t\t\t\t$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))\n\t\t\t{\n\t\t\t\t$url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));\n\t\t\t}\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))\n\t\t\t{\n\t\t\t\t$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif ($name !== null || $email !== null || $url !== null)\n\t\t\t{\n\t\t\t\t$contributors[] = $this->registry->create('Author', array($name, $url, $email));\n\t\t\t}\n\t\t}\n\n\t\tif (!empty($contributors))\n\t\t{\n\t\t\treturn array_unique($contributors);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all authors for the item\n\t *\n\t * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`\n\t *\n\t * @since Beta 2\n\t * @return array|null List of {@see SimplePie_Author} objects\n\t */\n\tpublic function get_authors()\n\t{\n\t\t$authors = array();\n\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)\n\t\t{\n\t\t\t$name = null;\n\t\t\t$uri = null;\n\t\t\t$email = null;\n\t\t\tif (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))\n\t\t\t{\n\t\t\t\t$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))\n\t\t\t{\n\t\t\t\t$uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));\n\t\t\t}\n\t\t\tif (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))\n\t\t\t{\n\t\t\t\t$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif ($name !== null || $email !== null || $uri !== null)\n\t\t\t{\n\t\t\t\t$authors[] = $this->registry->create('Author', array($name, $uri, $email));\n\t\t\t}\n\t\t}\n\t\tif ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))\n\t\t{\n\t\t\t$name = null;\n\t\t\t$url = null;\n\t\t\t$email = null;\n\t\t\tif (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))\n\t\t\t{\n\t\t\t\t$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))\n\t\t\t{\n\t\t\t\t$url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));\n\t\t\t}\n\t\t\tif (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))\n\t\t\t{\n\t\t\t\t$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif ($name !== null || $email !== null || $url !== null)\n\t\t\t{\n\t\t\t\t$authors[] = $this->registry->create('Author', array($name, $url, $email));\n\t\t\t}\n\t\t}\n\t\tif ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))\n\t\t{\n\t\t\t$authors[] = $this->registry->create('Author', array(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)));\n\t\t}\n\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)\n\t\t{\n\t\t\t$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)\n\t\t{\n\t\t\t$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)\n\t\t{\n\t\t\t$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\n\t\tif (!empty($authors))\n\t\t{\n\t\t\treturn array_unique($authors);\n\t\t}\n\t\telseif (($source = $this->get_source()) && ($authors = $source->get_authors()))\n\t\t{\n\t\t\treturn $authors;\n\t\t}\n\t\telseif ($authors = $this->feed->get_authors())\n\t\t{\n\t\t\treturn $authors;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the copyright info for the item\n\t *\n\t * Uses `<atom:rights>` or `<dc:rights>`\n\t *\n\t * @since 1.1\n\t * @return string\n\t */\n\tpublic function get_copyright()\n\t{\n\t\tif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the posting date/time for the item\n\t *\n\t * Uses `<atom:published>`, `<atom:updated>`, `<atom:issued>`,\n\t * `<atom:modified>`, `<pubDate>` or `<dc:date>`\n\t *\n\t * Note: obeys PHP's timezone setting. To get a UTC date/time, use\n\t * {@see get_gmdate}\n\t *\n\t * @since Beta 2 (previously called `get_item_date` since 0.8)\n\t *\n\t * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data)\n\t * @return int|string|null\n\t */\n\tpublic function get_date($date_format = 'j F Y, g:i a')\n\t{\n\t\tif (!isset($this->data['date']))\n\t\t{\n\t\t\tif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))\n\t\t\t{\n\t\t\t\t$this->data['date']['raw'] = $return[0]['data'];\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))\n\t\t\t{\n\t\t\t\t$this->data['date']['raw'] = $return[0]['data'];\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))\n\t\t\t{\n\t\t\t\t$this->data['date']['raw'] = $return[0]['data'];\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))\n\t\t\t{\n\t\t\t\t$this->data['date']['raw'] = $return[0]['data'];\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))\n\t\t\t{\n\t\t\t\t$this->data['date']['raw'] = $return[0]['data'];\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))\n\t\t\t{\n\t\t\t\t$this->data['date']['raw'] = $return[0]['data'];\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))\n\t\t\t{\n\t\t\t\t$this->data['date']['raw'] = $return[0]['data'];\n\t\t\t}\n\t\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))\n\t\t\t{\n\t\t\t\t$this->data['date']['raw'] = $return[0]['data'];\n\t\t\t}\n\n\t\t\tif (!empty($this->data['date']['raw']))\n\t\t\t{\n\t\t\t\t$parser = $this->registry->call('Parse_Date', 'get');\n\t\t\t\t$this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->data['date'] = null;\n\t\t\t}\n\t\t}\n\t\tif ($this->data['date'])\n\t\t{\n\t\t\t$date_format = (string) $date_format;\n\t\t\tswitch ($date_format)\n\t\t\t{\n\t\t\t\tcase '':\n\t\t\t\t\treturn $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);\n\n\t\t\t\tcase 'U':\n\t\t\t\t\treturn $this->data['date']['parsed'];\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn date($date_format, $this->data['date']['parsed']);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the update date/time for the item\n\t *\n\t * Uses `<atom:updated>`\n\t *\n\t * Note: obeys PHP's timezone setting. To get a UTC date/time, use\n\t * {@see get_gmdate}\n\t *\n\t * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data)\n\t * @return int|string|null\n\t */\n\tpublic function get_updated_date($date_format = 'j F Y, g:i a')\n\t{\n\t\tif (!isset($this->data['updated']))\n\t\t{\n\t\t\tif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))\n\t\t\t{\n\t\t\t\t$this->data['updated']['raw'] = $return[0]['data'];\n\t\t\t}\n\n\t\t\tif (!empty($this->data['updated']['raw']))\n\t\t\t{\n\t\t\t\t$parser = $this->registry->call('Parse_Date', 'get');\n\t\t\t\t$this->data['updated']['parsed'] = $parser->parse($this->data['date']['raw']);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->data['updated'] = null;\n\t\t\t}\n\t\t}\n\t\tif ($this->data['updated'])\n\t\t{\n\t\t\t$date_format = (string) $date_format;\n\t\t\tswitch ($date_format)\n\t\t\t{\n\t\t\t\tcase '':\n\t\t\t\t\treturn $this->sanitize($this->data['updated']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);\n\n\t\t\t\tcase 'U':\n\t\t\t\t\treturn $this->data['updated']['parsed'];\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn date($date_format, $this->data['updated']['parsed']);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the localized posting date/time for the item\n\t *\n\t * Returns the date formatted in the localized language. To display in\n\t * languages other than the server's default, you need to change the locale\n\t * with {@link http://php.net/setlocale setlocale()}. The available\n\t * localizations depend on which ones are installed on your web server.\n\t *\n\t * @since 1.0\n\t *\n\t * @param string $date_format Supports any PHP date format from {@see http://php.net/strftime} (empty for the raw data)\n\t * @return int|string|null\n\t */\n\tpublic function get_local_date($date_format = '%c')\n\t{\n\t\tif (!$date_format)\n\t\t{\n\t\t\treturn $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif (($date = $this->get_date('U')) !== null && $date !== false)\n\t\t{\n\t\t\treturn strftime($date_format, $date);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the posting date/time for the item (UTC time)\n\t *\n\t * @see get_date\n\t * @param string $date_format Supports any PHP date format from {@see http://php.net/date}\n\t * @return int|string|null\n\t */\n\tpublic function get_gmdate($date_format = 'j F Y, g:i a')\n\t{\n\t\t$date = $this->get_date('U');\n\t\tif ($date === null)\n\t\t{\n\t\t\treturn null;\n\t\t}\n\n\t\treturn gmdate($date_format, $date);\n\t}\n\n\t/**\n\t * Get the update date/time for the item (UTC time)\n\t *\n\t * @see get_updated_date\n\t * @param string $date_format Supports any PHP date format from {@see http://php.net/date}\n\t * @return int|string|null\n\t */\n\tpublic function get_updated_gmdate($date_format = 'j F Y, g:i a')\n\t{\n\t\t$date = $this->get_updated_date('U');\n\t\tif ($date === null)\n\t\t{\n\t\t\treturn null;\n\t\t}\n\n\t\treturn gmdate($date_format, $date);\n\t}\n\n\t/**\n\t * Get the permalink for the item\n\t *\n\t * Returns the first link available with a relationship of \"alternate\".\n\t * Identical to {@see get_link()} with key 0\n\t *\n\t * @see get_link\n\t * @since 0.8\n\t * @return string|null Permalink URL\n\t */\n\tpublic function get_permalink()\n\t{\n\t\t$link = $this->get_link();\n\t\t$enclosure = $this->get_enclosure(0);\n\t\tif ($link !== null)\n\t\t{\n\t\t\treturn $link;\n\t\t}\n\t\telseif ($enclosure !== null)\n\t\t{\n\t\t\treturn $enclosure->get_link();\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get a single link for the item\n\t *\n\t * @since Beta 3\n\t * @param int $key The link that you want to return.  Remember that arrays begin with 0, not 1\n\t * @param string $rel The relationship of the link to return\n\t * @return string|null Link URL\n\t */\n\tpublic function get_link($key = 0, $rel = 'alternate')\n\t{\n\t\t$links = $this->get_links($rel);\n\t\tif ($links[$key] !== null)\n\t\t{\n\t\t\treturn $links[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all links for the item\n\t *\n\t * Uses `<atom:link>`, `<link>` or `<guid>`\n\t *\n\t * @since Beta 2\n\t * @param string $rel The relationship of links to return\n\t * @return array|null Links found for the item (strings)\n\t */\n\tpublic function get_links($rel = 'alternate')\n\t{\n\t\tif (!isset($this->data['links']))\n\t\t{\n\t\t\t$this->data['links'] = array();\n\t\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)\n\t\t\t{\n\t\t\t\tif (isset($link['attribs']['']['href']))\n\t\t\t\t{\n\t\t\t\t\t$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';\n\t\t\t\t\t$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));\n\n\t\t\t\t}\n\t\t\t}\n\t\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)\n\t\t\t{\n\t\t\t\tif (isset($link['attribs']['']['href']))\n\t\t\t\t{\n\t\t\t\t\t$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';\n\t\t\t\t\t$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))\n\t\t\t{\n\t\t\t\t$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));\n\t\t\t}\n\t\t\tif ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))\n\t\t\t{\n\t\t\t\t$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));\n\t\t\t}\n\t\t\tif ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))\n\t\t\t{\n\t\t\t\t$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));\n\t\t\t}\n\t\t\tif ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))\n\t\t\t{\n\t\t\t\tif (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')\n\t\t\t\t{\n\t\t\t\t\t$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$keys = array_keys($this->data['links']);\n\t\t\tforeach ($keys as $key)\n\t\t\t{\n\t\t\t\tif ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))\n\t\t\t\t{\n\t\t\t\t\tif (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);\n\t\t\t\t\t\t$this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)\n\t\t\t\t{\n\t\t\t\t\t$this->data['links'][substr($key, 41)] =& $this->data['links'][$key];\n\t\t\t\t}\n\t\t\t\t$this->data['links'][$key] = array_unique($this->data['links'][$key]);\n\t\t\t}\n\t\t}\n\t\tif (isset($this->data['links'][$rel]))\n\t\t{\n\t\t\treturn $this->data['links'][$rel];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get an enclosure from the item\n\t *\n\t * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.\n\t *\n\t * @since Beta 2\n\t * @todo Add ability to prefer one type of content over another (in a media group).\n\t * @param int $key The enclosure that you want to return.  Remember that arrays begin with 0, not 1\n\t * @return SimplePie_Enclosure|null\n\t */\n\tpublic function get_enclosure($key = 0, $prefer = null)\n\t{\n\t\t$enclosures = $this->get_enclosures();\n\t\tif (isset($enclosures[$key]))\n\t\t{\n\t\t\treturn $enclosures[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all available enclosures (podcasts, etc.)\n\t *\n\t * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.\n\t *\n\t * At this point, we're pretty much assuming that all enclosures for an item\n\t * are the same content.  Anything else is too complicated to\n\t * properly support.\n\t *\n\t * @since Beta 2\n\t * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).\n\t * @todo If an element exists at a level, but it's value is empty, we should fall back to the value from the parent (if it exists).\n\t * @return array|null List of SimplePie_Enclosure items\n\t */\n\tpublic function get_enclosures()\n\t{\n\t\tif (!isset($this->data['enclosures']))\n\t\t{\n\t\t\t$this->data['enclosures'] = array();\n\n\t\t\t// Elements\n\t\t\t$captions_parent = null;\n\t\t\t$categories_parent = null;\n\t\t\t$copyrights_parent = null;\n\t\t\t$credits_parent = null;\n\t\t\t$description_parent = null;\n\t\t\t$duration_parent = null;\n\t\t\t$hashes_parent = null;\n\t\t\t$keywords_parent = null;\n\t\t\t$player_parent = null;\n\t\t\t$ratings_parent = null;\n\t\t\t$restrictions_parent = null;\n\t\t\t$thumbnails_parent = null;\n\t\t\t$title_parent = null;\n\n\t\t\t// Let's do the channel and item-level ones first, and just re-use them if we need to.\n\t\t\t$parent = $this->get_feed();\n\n\t\t\t// CAPTIONS\n\t\t\tif ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))\n\t\t\t{\n\t\t\t\tforeach ($captions as $caption)\n\t\t\t\t{\n\t\t\t\t\t$caption_type = null;\n\t\t\t\t\t$caption_lang = null;\n\t\t\t\t\t$caption_startTime = null;\n\t\t\t\t\t$caption_endTime = null;\n\t\t\t\t\t$caption_text = null;\n\t\t\t\t\tif (isset($caption['attribs']['']['type']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($caption['attribs']['']['lang']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($caption['attribs']['']['start']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($caption['attribs']['']['end']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($caption['data']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\t$captions_parent[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))\n\t\t\t{\n\t\t\t\tforeach ($captions as $caption)\n\t\t\t\t{\n\t\t\t\t\t$caption_type = null;\n\t\t\t\t\t$caption_lang = null;\n\t\t\t\t\t$caption_startTime = null;\n\t\t\t\t\t$caption_endTime = null;\n\t\t\t\t\t$caption_text = null;\n\t\t\t\t\tif (isset($caption['attribs']['']['type']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($caption['attribs']['']['lang']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($caption['attribs']['']['start']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($caption['attribs']['']['end']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($caption['data']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\t$captions_parent[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (is_array($captions_parent))\n\t\t\t{\n\t\t\t\t$captions_parent = array_values(array_unique($captions_parent));\n\t\t\t}\n\n\t\t\t// CATEGORIES\n\t\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)\n\t\t\t{\n\t\t\t\t$term = null;\n\t\t\t\t$scheme = null;\n\t\t\t\t$label = null;\n\t\t\t\tif (isset($category['data']))\n\t\t\t\t{\n\t\t\t\t\t$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t\tif (isset($category['attribs']['']['scheme']))\n\t\t\t\t{\n\t\t\t\t\t$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$scheme = 'http://search.yahoo.com/mrss/category_schema';\n\t\t\t\t}\n\t\t\t\tif (isset($category['attribs']['']['label']))\n\t\t\t\t{\n\t\t\t\t\t$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t\t$categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));\n\t\t\t}\n\t\t\tforeach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)\n\t\t\t{\n\t\t\t\t$term = null;\n\t\t\t\t$scheme = null;\n\t\t\t\t$label = null;\n\t\t\t\tif (isset($category['data']))\n\t\t\t\t{\n\t\t\t\t\t$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t\tif (isset($category['attribs']['']['scheme']))\n\t\t\t\t{\n\t\t\t\t\t$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$scheme = 'http://search.yahoo.com/mrss/category_schema';\n\t\t\t\t}\n\t\t\t\tif (isset($category['attribs']['']['label']))\n\t\t\t\t{\n\t\t\t\t\t$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t\t$categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));\n\t\t\t}\n\t\t\tforeach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)\n\t\t\t{\n\t\t\t\t$term = null;\n\t\t\t\t$scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';\n\t\t\t\t$label = null;\n\t\t\t\tif (isset($category['attribs']['']['text']))\n\t\t\t\t{\n\t\t\t\t\t$label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t\t$categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));\n\n\t\t\t\tif (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))\n\t\t\t\t{\n\t\t\t\t\tforeach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (isset($subcategory['attribs']['']['text']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (is_array($categories_parent))\n\t\t\t{\n\t\t\t\t$categories_parent = array_values(array_unique($categories_parent));\n\t\t\t}\n\n\t\t\t// COPYRIGHT\n\t\t\tif ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))\n\t\t\t{\n\t\t\t\t$copyright_url = null;\n\t\t\t\t$copyright_label = null;\n\t\t\t\tif (isset($copyright[0]['attribs']['']['url']))\n\t\t\t\t{\n\t\t\t\t\t$copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t\tif (isset($copyright[0]['data']))\n\t\t\t\t{\n\t\t\t\t\t$copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t\t$copyrights_parent = $this->registry->create('Copyright', array($copyright_url, $copyright_label));\n\t\t\t}\n\t\t\telseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))\n\t\t\t{\n\t\t\t\t$copyright_url = null;\n\t\t\t\t$copyright_label = null;\n\t\t\t\tif (isset($copyright[0]['attribs']['']['url']))\n\t\t\t\t{\n\t\t\t\t\t$copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t\tif (isset($copyright[0]['data']))\n\t\t\t\t{\n\t\t\t\t\t$copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t\t$copyrights_parent = $this->registry->create('Copyright', array($copyright_url, $copyright_label));\n\t\t\t}\n\n\t\t\t// CREDITS\n\t\t\tif ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))\n\t\t\t{\n\t\t\t\tforeach ($credits as $credit)\n\t\t\t\t{\n\t\t\t\t\t$credit_role = null;\n\t\t\t\t\t$credit_scheme = null;\n\t\t\t\t\t$credit_name = null;\n\t\t\t\t\tif (isset($credit['attribs']['']['role']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($credit['attribs']['']['scheme']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$credit_scheme = 'urn:ebu';\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($credit['data']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\t$credits_parent[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))\n\t\t\t{\n\t\t\t\tforeach ($credits as $credit)\n\t\t\t\t{\n\t\t\t\t\t$credit_role = null;\n\t\t\t\t\t$credit_scheme = null;\n\t\t\t\t\t$credit_name = null;\n\t\t\t\t\tif (isset($credit['attribs']['']['role']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($credit['attribs']['']['scheme']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$credit_scheme = 'urn:ebu';\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($credit['data']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\t$credits_parent[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (is_array($credits_parent))\n\t\t\t{\n\t\t\t\t$credits_parent = array_values(array_unique($credits_parent));\n\t\t\t}\n\n\t\t\t// DESCRIPTION\n\t\t\tif ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))\n\t\t\t{\n\t\t\t\tif (isset($description_parent[0]['data']))\n\t\t\t\t{\n\t\t\t\t\t$description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))\n\t\t\t{\n\t\t\t\tif (isset($description_parent[0]['data']))\n\t\t\t\t{\n\t\t\t\t\t$description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// DURATION\n\t\t\tif ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))\n\t\t\t{\n\t\t\t\t$seconds = null;\n\t\t\t\t$minutes = null;\n\t\t\t\t$hours = null;\n\t\t\t\tif (isset($duration_parent[0]['data']))\n\t\t\t\t{\n\t\t\t\t\t$temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));\n\t\t\t\t\tif (sizeof($temp) > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t$seconds = (int) array_pop($temp);\n\t\t\t\t\t}\n\t\t\t\t\tif (sizeof($temp) > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t$minutes = (int) array_pop($temp);\n\t\t\t\t\t\t$seconds += $minutes * 60;\n\t\t\t\t\t}\n\t\t\t\t\tif (sizeof($temp) > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t$hours = (int) array_pop($temp);\n\t\t\t\t\t\t$seconds += $hours * 3600;\n\t\t\t\t\t}\n\t\t\t\t\tunset($temp);\n\t\t\t\t\t$duration_parent = $seconds;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// HASHES\n\t\t\tif ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))\n\t\t\t{\n\t\t\t\tforeach ($hashes_iterator as $hash)\n\t\t\t\t{\n\t\t\t\t\t$value = null;\n\t\t\t\t\t$algo = null;\n\t\t\t\t\tif (isset($hash['data']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($hash['attribs']['']['algo']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$algo = 'md5';\n\t\t\t\t\t}\n\t\t\t\t\t$hashes_parent[] = $algo.':'.$value;\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))\n\t\t\t{\n\t\t\t\tforeach ($hashes_iterator as $hash)\n\t\t\t\t{\n\t\t\t\t\t$value = null;\n\t\t\t\t\t$algo = null;\n\t\t\t\t\tif (isset($hash['data']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($hash['attribs']['']['algo']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$algo = 'md5';\n\t\t\t\t\t}\n\t\t\t\t\t$hashes_parent[] = $algo.':'.$value;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (is_array($hashes_parent))\n\t\t\t{\n\t\t\t\t$hashes_parent = array_values(array_unique($hashes_parent));\n\t\t\t}\n\n\t\t\t// KEYWORDS\n\t\t\tif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))\n\t\t\t{\n\t\t\t\tif (isset($keywords[0]['data']))\n\t\t\t\t{\n\t\t\t\t\t$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));\n\t\t\t\t\tforeach ($temp as $word)\n\t\t\t\t\t{\n\t\t\t\t\t\t$keywords_parent[] = trim($word);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tunset($temp);\n\t\t\t}\n\t\t\telseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))\n\t\t\t{\n\t\t\t\tif (isset($keywords[0]['data']))\n\t\t\t\t{\n\t\t\t\t\t$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));\n\t\t\t\t\tforeach ($temp as $word)\n\t\t\t\t\t{\n\t\t\t\t\t\t$keywords_parent[] = trim($word);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tunset($temp);\n\t\t\t}\n\t\t\telseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))\n\t\t\t{\n\t\t\t\tif (isset($keywords[0]['data']))\n\t\t\t\t{\n\t\t\t\t\t$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));\n\t\t\t\t\tforeach ($temp as $word)\n\t\t\t\t\t{\n\t\t\t\t\t\t$keywords_parent[] = trim($word);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tunset($temp);\n\t\t\t}\n\t\t\telseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))\n\t\t\t{\n\t\t\t\tif (isset($keywords[0]['data']))\n\t\t\t\t{\n\t\t\t\t\t$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));\n\t\t\t\t\tforeach ($temp as $word)\n\t\t\t\t\t{\n\t\t\t\t\t\t$keywords_parent[] = trim($word);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tunset($temp);\n\t\t\t}\n\t\t\tif (is_array($keywords_parent))\n\t\t\t{\n\t\t\t\t$keywords_parent = array_values(array_unique($keywords_parent));\n\t\t\t}\n\n\t\t\t// PLAYER\n\t\t\tif ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))\n\t\t\t{\n\t\t\t\tif (isset($player_parent[0]['attribs']['']['url']))\n\t\t\t\t{\n\t\t\t\t\t$player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))\n\t\t\t{\n\t\t\t\tif (isset($player_parent[0]['attribs']['']['url']))\n\t\t\t\t{\n\t\t\t\t\t$player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// RATINGS\n\t\t\tif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))\n\t\t\t{\n\t\t\t\tforeach ($ratings as $rating)\n\t\t\t\t{\n\t\t\t\t\t$rating_scheme = null;\n\t\t\t\t\t$rating_value = null;\n\t\t\t\t\tif (isset($rating['attribs']['']['scheme']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$rating_scheme = 'urn:simple';\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($rating['data']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\t$ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))\n\t\t\t{\n\t\t\t\tforeach ($ratings as $rating)\n\t\t\t\t{\n\t\t\t\t\t$rating_scheme = 'urn:itunes';\n\t\t\t\t\t$rating_value = null;\n\t\t\t\t\tif (isset($rating['data']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\t$ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))\n\t\t\t{\n\t\t\t\tforeach ($ratings as $rating)\n\t\t\t\t{\n\t\t\t\t\t$rating_scheme = null;\n\t\t\t\t\t$rating_value = null;\n\t\t\t\t\tif (isset($rating['attribs']['']['scheme']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$rating_scheme = 'urn:simple';\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($rating['data']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\t$ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))\n\t\t\t{\n\t\t\t\tforeach ($ratings as $rating)\n\t\t\t\t{\n\t\t\t\t\t$rating_scheme = 'urn:itunes';\n\t\t\t\t\t$rating_value = null;\n\t\t\t\t\tif (isset($rating['data']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\t$ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (is_array($ratings_parent))\n\t\t\t{\n\t\t\t\t$ratings_parent = array_values(array_unique($ratings_parent));\n\t\t\t}\n\n\t\t\t// RESTRICTIONS\n\t\t\tif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))\n\t\t\t{\n\t\t\t\tforeach ($restrictions as $restriction)\n\t\t\t\t{\n\t\t\t\t\t$restriction_relationship = null;\n\t\t\t\t\t$restriction_type = null;\n\t\t\t\t\t$restriction_value = null;\n\t\t\t\t\tif (isset($restriction['attribs']['']['relationship']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($restriction['attribs']['']['type']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($restriction['data']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\t$restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))\n\t\t\t{\n\t\t\t\tforeach ($restrictions as $restriction)\n\t\t\t\t{\n\t\t\t\t\t$restriction_relationship = 'allow';\n\t\t\t\t\t$restriction_type = null;\n\t\t\t\t\t$restriction_value = 'itunes';\n\t\t\t\t\tif (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')\n\t\t\t\t\t{\n\t\t\t\t\t\t$restriction_relationship = 'deny';\n\t\t\t\t\t}\n\t\t\t\t\t$restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))\n\t\t\t{\n\t\t\t\tforeach ($restrictions as $restriction)\n\t\t\t\t{\n\t\t\t\t\t$restriction_relationship = null;\n\t\t\t\t\t$restriction_type = null;\n\t\t\t\t\t$restriction_value = null;\n\t\t\t\t\tif (isset($restriction['attribs']['']['relationship']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($restriction['attribs']['']['type']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($restriction['data']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\t$restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))\n\t\t\t{\n\t\t\t\tforeach ($restrictions as $restriction)\n\t\t\t\t{\n\t\t\t\t\t$restriction_relationship = 'allow';\n\t\t\t\t\t$restriction_type = null;\n\t\t\t\t\t$restriction_value = 'itunes';\n\t\t\t\t\tif (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')\n\t\t\t\t\t{\n\t\t\t\t\t\t$restriction_relationship = 'deny';\n\t\t\t\t\t}\n\t\t\t\t\t$restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (is_array($restrictions_parent))\n\t\t\t{\n\t\t\t\t$restrictions_parent = array_values(array_unique($restrictions_parent));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$restrictions_parent = array(new SimplePie_Restriction('allow', null, 'default'));\n\t\t\t}\n\n\t\t\t// THUMBNAILS\n\t\t\tif ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))\n\t\t\t{\n\t\t\t\tforeach ($thumbnails as $thumbnail)\n\t\t\t\t{\n\t\t\t\t\tif (isset($thumbnail['attribs']['']['url']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))\n\t\t\t{\n\t\t\t\tforeach ($thumbnails as $thumbnail)\n\t\t\t\t{\n\t\t\t\t\tif (isset($thumbnail['attribs']['']['url']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// TITLES\n\t\t\tif ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))\n\t\t\t{\n\t\t\t\tif (isset($title_parent[0]['data']))\n\t\t\t\t{\n\t\t\t\t\t$title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))\n\t\t\t{\n\t\t\t\tif (isset($title_parent[0]['data']))\n\t\t\t\t{\n\t\t\t\t\t$title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Clear the memory\n\t\t\tunset($parent);\n\n\t\t\t// Attributes\n\t\t\t$bitrate = null;\n\t\t\t$channels = null;\n\t\t\t$duration = null;\n\t\t\t$expression = null;\n\t\t\t$framerate = null;\n\t\t\t$height = null;\n\t\t\t$javascript = null;\n\t\t\t$lang = null;\n\t\t\t$length = null;\n\t\t\t$medium = null;\n\t\t\t$samplingrate = null;\n\t\t\t$type = null;\n\t\t\t$url = null;\n\t\t\t$width = null;\n\n\t\t\t// Elements\n\t\t\t$captions = null;\n\t\t\t$categories = null;\n\t\t\t$copyrights = null;\n\t\t\t$credits = null;\n\t\t\t$description = null;\n\t\t\t$hashes = null;\n\t\t\t$keywords = null;\n\t\t\t$player = null;\n\t\t\t$ratings = null;\n\t\t\t$restrictions = null;\n\t\t\t$thumbnails = null;\n\t\t\t$title = null;\n\n\t\t\t// If we have media:group tags, loop through them.\n\t\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)\n\t\t\t{\n\t\t\t\tif(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))\n\t\t\t\t{\n\t\t\t\t\t// If we have media:content tags, loop through them.\n\t\t\t\t\tforeach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (isset($content['attribs']['']['url']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Attributes\n\t\t\t\t\t\t\t$bitrate = null;\n\t\t\t\t\t\t\t$channels = null;\n\t\t\t\t\t\t\t$duration = null;\n\t\t\t\t\t\t\t$expression = null;\n\t\t\t\t\t\t\t$framerate = null;\n\t\t\t\t\t\t\t$height = null;\n\t\t\t\t\t\t\t$javascript = null;\n\t\t\t\t\t\t\t$lang = null;\n\t\t\t\t\t\t\t$length = null;\n\t\t\t\t\t\t\t$medium = null;\n\t\t\t\t\t\t\t$samplingrate = null;\n\t\t\t\t\t\t\t$type = null;\n\t\t\t\t\t\t\t$url = null;\n\t\t\t\t\t\t\t$width = null;\n\n\t\t\t\t\t\t\t// Elements\n\t\t\t\t\t\t\t$captions = null;\n\t\t\t\t\t\t\t$categories = null;\n\t\t\t\t\t\t\t$copyrights = null;\n\t\t\t\t\t\t\t$credits = null;\n\t\t\t\t\t\t\t$description = null;\n\t\t\t\t\t\t\t$hashes = null;\n\t\t\t\t\t\t\t$keywords = null;\n\t\t\t\t\t\t\t$player = null;\n\t\t\t\t\t\t\t$ratings = null;\n\t\t\t\t\t\t\t$restrictions = null;\n\t\t\t\t\t\t\t$thumbnails = null;\n\t\t\t\t\t\t\t$title = null;\n\n\t\t\t\t\t\t\t// Start checking the attributes of media:content\n\t\t\t\t\t\t\tif (isset($content['attribs']['']['bitrate']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (isset($content['attribs']['']['channels']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (isset($content['attribs']['']['duration']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$duration = $duration_parent;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (isset($content['attribs']['']['expression']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (isset($content['attribs']['']['framerate']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (isset($content['attribs']['']['height']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (isset($content['attribs']['']['lang']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (isset($content['attribs']['']['fileSize']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$length = ceil($content['attribs']['']['fileSize']);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (isset($content['attribs']['']['medium']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (isset($content['attribs']['']['samplingrate']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (isset($content['attribs']['']['type']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (isset($content['attribs']['']['width']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);\n\n\t\t\t\t\t\t\t// Checking the other optional media: elements. Priority: media:content, media:group, item, channel\n\n\t\t\t\t\t\t\t// CAPTIONS\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tforeach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$caption_type = null;\n\t\t\t\t\t\t\t\t\t$caption_lang = null;\n\t\t\t\t\t\t\t\t\t$caption_startTime = null;\n\t\t\t\t\t\t\t\t\t$caption_endTime = null;\n\t\t\t\t\t\t\t\t\t$caption_text = null;\n\t\t\t\t\t\t\t\t\tif (isset($caption['attribs']['']['type']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($caption['attribs']['']['lang']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($caption['attribs']['']['start']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($caption['attribs']['']['end']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($caption['data']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t$captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (is_array($captions))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$captions = array_values(array_unique($captions));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tforeach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$caption_type = null;\n\t\t\t\t\t\t\t\t\t$caption_lang = null;\n\t\t\t\t\t\t\t\t\t$caption_startTime = null;\n\t\t\t\t\t\t\t\t\t$caption_endTime = null;\n\t\t\t\t\t\t\t\t\t$caption_text = null;\n\t\t\t\t\t\t\t\t\tif (isset($caption['attribs']['']['type']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($caption['attribs']['']['lang']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($caption['attribs']['']['start']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($caption['attribs']['']['end']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($caption['data']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t$captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (is_array($captions))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$captions = array_values(array_unique($captions));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$captions = $captions_parent;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// CATEGORIES\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tforeach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$term = null;\n\t\t\t\t\t\t\t\t\t$scheme = null;\n\t\t\t\t\t\t\t\t\t$label = null;\n\t\t\t\t\t\t\t\t\tif (isset($category['data']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($category['attribs']['']['scheme']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$scheme = 'http://search.yahoo.com/mrss/category_schema';\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($category['attribs']['']['label']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t$categories[] = $this->registry->create('Category', array($term, $scheme, $label));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tforeach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$term = null;\n\t\t\t\t\t\t\t\t\t$scheme = null;\n\t\t\t\t\t\t\t\t\t$label = null;\n\t\t\t\t\t\t\t\t\tif (isset($category['data']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($category['attribs']['']['scheme']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$scheme = 'http://search.yahoo.com/mrss/category_schema';\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($category['attribs']['']['label']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t$categories[] = $this->registry->create('Category', array($term, $scheme, $label));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (is_array($categories) && is_array($categories_parent))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$categories = array_values(array_unique(array_merge($categories, $categories_parent)));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (is_array($categories))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$categories = array_values(array_unique($categories));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (is_array($categories_parent))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$categories = array_values(array_unique($categories_parent));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// COPYRIGHTS\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$copyright_url = null;\n\t\t\t\t\t\t\t\t$copyright_label = null;\n\t\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t$copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$copyright_url = null;\n\t\t\t\t\t\t\t\t$copyright_label = null;\n\t\t\t\t\t\t\t\tif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t$copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$copyrights = $copyrights_parent;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// CREDITS\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tforeach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$credit_role = null;\n\t\t\t\t\t\t\t\t\t$credit_scheme = null;\n\t\t\t\t\t\t\t\t\t$credit_name = null;\n\t\t\t\t\t\t\t\t\tif (isset($credit['attribs']['']['role']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($credit['attribs']['']['scheme']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$credit_scheme = 'urn:ebu';\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($credit['data']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t$credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (is_array($credits))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$credits = array_values(array_unique($credits));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tforeach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$credit_role = null;\n\t\t\t\t\t\t\t\t\t$credit_scheme = null;\n\t\t\t\t\t\t\t\t\t$credit_name = null;\n\t\t\t\t\t\t\t\t\tif (isset($credit['attribs']['']['role']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($credit['attribs']['']['scheme']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$credit_scheme = 'urn:ebu';\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($credit['data']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t$credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (is_array($credits))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$credits = array_values(array_unique($credits));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$credits = $credits_parent;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// DESCRIPTION\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$description = $description_parent;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// HASHES\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tforeach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$value = null;\n\t\t\t\t\t\t\t\t\t$algo = null;\n\t\t\t\t\t\t\t\t\tif (isset($hash['data']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($hash['attribs']['']['algo']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$algo = 'md5';\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t$hashes[] = $algo.':'.$value;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (is_array($hashes))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$hashes = array_values(array_unique($hashes));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tforeach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$value = null;\n\t\t\t\t\t\t\t\t\t$algo = null;\n\t\t\t\t\t\t\t\t\tif (isset($hash['data']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($hash['attribs']['']['algo']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$algo = 'md5';\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t$hashes[] = $algo.':'.$value;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (is_array($hashes))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$hashes = array_values(array_unique($hashes));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$hashes = $hashes_parent;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// KEYWORDS\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));\n\t\t\t\t\t\t\t\t\tforeach ($temp as $word)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$keywords[] = trim($word);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tunset($temp);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (is_array($keywords))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$keywords = array_values(array_unique($keywords));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));\n\t\t\t\t\t\t\t\t\tforeach ($temp as $word)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$keywords[] = trim($word);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tunset($temp);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (is_array($keywords))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$keywords = array_values(array_unique($keywords));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$keywords = $keywords_parent;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// PLAYER\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$player = $player_parent;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// RATINGS\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tforeach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$rating_scheme = null;\n\t\t\t\t\t\t\t\t\t$rating_value = null;\n\t\t\t\t\t\t\t\t\tif (isset($rating['attribs']['']['scheme']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$rating_scheme = 'urn:simple';\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($rating['data']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t$ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (is_array($ratings))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$ratings = array_values(array_unique($ratings));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tforeach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$rating_scheme = null;\n\t\t\t\t\t\t\t\t\t$rating_value = null;\n\t\t\t\t\t\t\t\t\tif (isset($rating['attribs']['']['scheme']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$rating_scheme = 'urn:simple';\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($rating['data']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t$ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (is_array($ratings))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$ratings = array_values(array_unique($ratings));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$ratings = $ratings_parent;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// RESTRICTIONS\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tforeach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$restriction_relationship = null;\n\t\t\t\t\t\t\t\t\t$restriction_type = null;\n\t\t\t\t\t\t\t\t\t$restriction_value = null;\n\t\t\t\t\t\t\t\t\tif (isset($restriction['attribs']['']['relationship']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($restriction['attribs']['']['type']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($restriction['data']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t$restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (is_array($restrictions))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$restrictions = array_values(array_unique($restrictions));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tforeach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$restriction_relationship = null;\n\t\t\t\t\t\t\t\t\t$restriction_type = null;\n\t\t\t\t\t\t\t\t\t$restriction_value = null;\n\t\t\t\t\t\t\t\t\tif (isset($restriction['attribs']['']['relationship']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($restriction['attribs']['']['type']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (isset($restriction['data']))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t$restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (is_array($restrictions))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$restrictions = array_values(array_unique($restrictions));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$restrictions = $restrictions_parent;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// THUMBNAILS\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tforeach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (is_array($thumbnails))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$thumbnails = array_values(array_unique($thumbnails));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tforeach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (is_array($thumbnails))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$thumbnails = array_values(array_unique($thumbnails));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$thumbnails = $thumbnails_parent;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// TITLES\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$title = $title_parent;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t$this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If we have standalone media:content tags, loop through them.\n\t\t\tif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))\n\t\t\t{\n\t\t\t\tforeach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)\n\t\t\t\t{\n\t\t\t\t\tif (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))\n\t\t\t\t\t{\n\t\t\t\t\t\t// Attributes\n\t\t\t\t\t\t$bitrate = null;\n\t\t\t\t\t\t$channels = null;\n\t\t\t\t\t\t$duration = null;\n\t\t\t\t\t\t$expression = null;\n\t\t\t\t\t\t$framerate = null;\n\t\t\t\t\t\t$height = null;\n\t\t\t\t\t\t$javascript = null;\n\t\t\t\t\t\t$lang = null;\n\t\t\t\t\t\t$length = null;\n\t\t\t\t\t\t$medium = null;\n\t\t\t\t\t\t$samplingrate = null;\n\t\t\t\t\t\t$type = null;\n\t\t\t\t\t\t$url = null;\n\t\t\t\t\t\t$width = null;\n\n\t\t\t\t\t\t// Elements\n\t\t\t\t\t\t$captions = null;\n\t\t\t\t\t\t$categories = null;\n\t\t\t\t\t\t$copyrights = null;\n\t\t\t\t\t\t$credits = null;\n\t\t\t\t\t\t$description = null;\n\t\t\t\t\t\t$hashes = null;\n\t\t\t\t\t\t$keywords = null;\n\t\t\t\t\t\t$player = null;\n\t\t\t\t\t\t$ratings = null;\n\t\t\t\t\t\t$restrictions = null;\n\t\t\t\t\t\t$thumbnails = null;\n\t\t\t\t\t\t$title = null;\n\n\t\t\t\t\t\t// Start checking the attributes of media:content\n\t\t\t\t\t\tif (isset($content['attribs']['']['bitrate']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isset($content['attribs']['']['channels']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isset($content['attribs']['']['duration']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$duration = $duration_parent;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isset($content['attribs']['']['expression']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isset($content['attribs']['']['framerate']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isset($content['attribs']['']['height']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isset($content['attribs']['']['lang']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isset($content['attribs']['']['fileSize']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$length = ceil($content['attribs']['']['fileSize']);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isset($content['attribs']['']['medium']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isset($content['attribs']['']['samplingrate']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isset($content['attribs']['']['type']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isset($content['attribs']['']['width']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isset($content['attribs']['']['url']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Checking the other optional media: elements. Priority: media:content, media:group, item, channel\n\n\t\t\t\t\t\t// CAPTIONS\n\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tforeach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$caption_type = null;\n\t\t\t\t\t\t\t\t$caption_lang = null;\n\t\t\t\t\t\t\t\t$caption_startTime = null;\n\t\t\t\t\t\t\t\t$caption_endTime = null;\n\t\t\t\t\t\t\t\t$caption_text = null;\n\t\t\t\t\t\t\t\tif (isset($caption['attribs']['']['type']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isset($caption['attribs']['']['lang']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isset($caption['attribs']['']['start']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isset($caption['attribs']['']['end']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isset($caption['data']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t$captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (is_array($captions))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$captions = array_values(array_unique($captions));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$captions = $captions_parent;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// CATEGORIES\n\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tforeach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$term = null;\n\t\t\t\t\t\t\t\t$scheme = null;\n\t\t\t\t\t\t\t\t$label = null;\n\t\t\t\t\t\t\t\tif (isset($category['data']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isset($category['attribs']['']['scheme']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$scheme = 'http://search.yahoo.com/mrss/category_schema';\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isset($category['attribs']['']['label']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t$categories[] = $this->registry->create('Category', array($term, $scheme, $label));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (is_array($categories) && is_array($categories_parent))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$categories = array_values(array_unique(array_merge($categories, $categories_parent)));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telseif (is_array($categories))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$categories = array_values(array_unique($categories));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telseif (is_array($categories_parent))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$categories = array_values(array_unique($categories_parent));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$categories = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// COPYRIGHTS\n\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$copyright_url = null;\n\t\t\t\t\t\t\t$copyright_label = null;\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$copyrights = $copyrights_parent;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// CREDITS\n\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tforeach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$credit_role = null;\n\t\t\t\t\t\t\t\t$credit_scheme = null;\n\t\t\t\t\t\t\t\t$credit_name = null;\n\t\t\t\t\t\t\t\tif (isset($credit['attribs']['']['role']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isset($credit['attribs']['']['scheme']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$credit_scheme = 'urn:ebu';\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isset($credit['data']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t$credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (is_array($credits))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$credits = array_values(array_unique($credits));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$credits = $credits_parent;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// DESCRIPTION\n\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$description = $description_parent;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// HASHES\n\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tforeach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$value = null;\n\t\t\t\t\t\t\t\t$algo = null;\n\t\t\t\t\t\t\t\tif (isset($hash['data']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isset($hash['attribs']['']['algo']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$algo = 'md5';\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t$hashes[] = $algo.':'.$value;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (is_array($hashes))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$hashes = array_values(array_unique($hashes));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$hashes = $hashes_parent;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// KEYWORDS\n\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));\n\t\t\t\t\t\t\t\tforeach ($temp as $word)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$keywords[] = trim($word);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tunset($temp);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (is_array($keywords))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$keywords = array_values(array_unique($keywords));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$keywords = $keywords_parent;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// PLAYER\n\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$player = $player_parent;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// RATINGS\n\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tforeach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$rating_scheme = null;\n\t\t\t\t\t\t\t\t$rating_value = null;\n\t\t\t\t\t\t\t\tif (isset($rating['attribs']['']['scheme']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$rating_scheme = 'urn:simple';\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isset($rating['data']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t$ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (is_array($ratings))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$ratings = array_values(array_unique($ratings));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$ratings = $ratings_parent;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// RESTRICTIONS\n\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tforeach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$restriction_relationship = null;\n\t\t\t\t\t\t\t\t$restriction_type = null;\n\t\t\t\t\t\t\t\t$restriction_value = null;\n\t\t\t\t\t\t\t\tif (isset($restriction['attribs']['']['relationship']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isset($restriction['attribs']['']['type']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (isset($restriction['data']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t$restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (is_array($restrictions))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$restrictions = array_values(array_unique($restrictions));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$restrictions = $restrictions_parent;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// THUMBNAILS\n\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tforeach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (is_array($thumbnails))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$thumbnails = array_values(array_unique($thumbnails));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$thumbnails = $thumbnails_parent;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// TITLES\n\t\t\t\t\t\tif (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$title = $title_parent;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)\n\t\t\t{\n\t\t\t\tif (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')\n\t\t\t\t{\n\t\t\t\t\t// Attributes\n\t\t\t\t\t$bitrate = null;\n\t\t\t\t\t$channels = null;\n\t\t\t\t\t$duration = null;\n\t\t\t\t\t$expression = null;\n\t\t\t\t\t$framerate = null;\n\t\t\t\t\t$height = null;\n\t\t\t\t\t$javascript = null;\n\t\t\t\t\t$lang = null;\n\t\t\t\t\t$length = null;\n\t\t\t\t\t$medium = null;\n\t\t\t\t\t$samplingrate = null;\n\t\t\t\t\t$type = null;\n\t\t\t\t\t$url = null;\n\t\t\t\t\t$width = null;\n\n\t\t\t\t\t$url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));\n\t\t\t\t\tif (isset($link['attribs']['']['type']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($link['attribs']['']['length']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$length = ceil($link['attribs']['']['length']);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor\n\t\t\t\t\t$this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tforeach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)\n\t\t\t{\n\t\t\t\tif (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')\n\t\t\t\t{\n\t\t\t\t\t// Attributes\n\t\t\t\t\t$bitrate = null;\n\t\t\t\t\t$channels = null;\n\t\t\t\t\t$duration = null;\n\t\t\t\t\t$expression = null;\n\t\t\t\t\t$framerate = null;\n\t\t\t\t\t$height = null;\n\t\t\t\t\t$javascript = null;\n\t\t\t\t\t$lang = null;\n\t\t\t\t\t$length = null;\n\t\t\t\t\t$medium = null;\n\t\t\t\t\t$samplingrate = null;\n\t\t\t\t\t$type = null;\n\t\t\t\t\t$url = null;\n\t\t\t\t\t$width = null;\n\n\t\t\t\t\t$url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));\n\t\t\t\t\tif (isset($link['attribs']['']['type']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($link['attribs']['']['length']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$length = ceil($link['attribs']['']['length']);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor\n\t\t\t\t\t$this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))\n\t\t\t{\n\t\t\t\tif (isset($enclosure[0]['attribs']['']['url']))\n\t\t\t\t{\n\t\t\t\t\t// Attributes\n\t\t\t\t\t$bitrate = null;\n\t\t\t\t\t$channels = null;\n\t\t\t\t\t$duration = null;\n\t\t\t\t\t$expression = null;\n\t\t\t\t\t$framerate = null;\n\t\t\t\t\t$height = null;\n\t\t\t\t\t$javascript = null;\n\t\t\t\t\t$lang = null;\n\t\t\t\t\t$length = null;\n\t\t\t\t\t$medium = null;\n\t\t\t\t\t$samplingrate = null;\n\t\t\t\t\t$type = null;\n\t\t\t\t\t$url = null;\n\t\t\t\t\t$width = null;\n\n\t\t\t\t\t$url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));\n\t\t\t\t\tif (isset($enclosure[0]['attribs']['']['type']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t\t\t}\n\t\t\t\t\tif (isset($enclosure[0]['attribs']['']['length']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$length = ceil($enclosure[0]['attribs']['']['length']);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor\n\t\t\t\t\t$this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (sizeof($this->data['enclosures']) === 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $restrictions_parent || $samplingrate || $thumbnails_parent || $title_parent || $width))\n\t\t\t{\n\t\t\t\t// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor\n\t\t\t\t$this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width));\n\t\t\t}\n\n\t\t\t$this->data['enclosures'] = array_values(array_unique($this->data['enclosures']));\n\t\t}\n\t\tif (!empty($this->data['enclosures']))\n\t\t{\n\t\t\treturn $this->data['enclosures'];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the latitude coordinates for the item\n\t *\n\t * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications\n\t *\n\t * Uses `<geo:lat>` or `<georss:point>`\n\t *\n\t * @since 1.0\n\t * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo\n\t * @link http://www.georss.org/ GeoRSS\n\t * @return string|null\n\t */\n\tpublic function get_latitude()\n\t{\n\t\tif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))\n\t\t{\n\t\t\treturn (float) $return[0]['data'];\n\t\t}\n\t\telseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\\.[0-9]+)) ((?:-)?[0-9]+(?:\\.[0-9]+))$/', trim($return[0]['data']), $match))\n\t\t{\n\t\t\treturn (float) $match[1];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the longitude coordinates for the item\n\t *\n\t * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications\n\t *\n\t * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`\n\t *\n\t * @since 1.0\n\t * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo\n\t * @link http://www.georss.org/ GeoRSS\n\t * @return string|null\n\t */\n\tpublic function get_longitude()\n\t{\n\t\tif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))\n\t\t{\n\t\t\treturn (float) $return[0]['data'];\n\t\t}\n\t\telseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))\n\t\t{\n\t\t\treturn (float) $return[0]['data'];\n\t\t}\n\t\telseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\\.[0-9]+)) ((?:-)?[0-9]+(?:\\.[0-9]+))$/', trim($return[0]['data']), $match))\n\t\t{\n\t\t\treturn (float) $match[2];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the `<atom:source>` for the item\n\t *\n\t * @since 1.1\n\t * @return SimplePie_Source|null\n\t */\n\tpublic function get_source()\n\t{\n\t\tif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))\n\t\t{\n\t\t\treturn $this->registry->create('Source', array($this, $return[0]));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Locator.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Used for feed auto-discovery\n *\n *\n * This class can be overloaded with {@see SimplePie::set_locator_class()}\n *\n * @package SimplePie\n */\nclass SimplePie_Locator\n{\n\tvar $useragent;\n\tvar $timeout;\n\tvar $file;\n\tvar $local = array();\n\tvar $elsewhere = array();\n\tvar $cached_entities = array();\n\tvar $http_base;\n\tvar $base;\n\tvar $base_location = 0;\n\tvar $checked_feeds = 0;\n\tvar $max_checked_feeds = 10;\n\tprotected $registry;\n\n\tpublic function __construct(SimplePie_File $file, $timeout = 10, $useragent = null, $max_checked_feeds = 10)\n\t{\n\t\t$this->file = $file;\n\t\t$this->useragent = $useragent;\n\t\t$this->timeout = $timeout;\n\t\t$this->max_checked_feeds = $max_checked_feeds;\n\n\t\tif (class_exists('DOMDocument'))\n\t\t{\n\t\t\t$this->dom = new DOMDocument();\n\n\t\t\tset_error_handler(array('SimplePie_Misc', 'silence_errors'));\n\t\t\t$this->dom->loadHTML($this->file->body);\n\t\t\trestore_error_handler();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->dom = null;\n\t\t}\n\t}\n\n\tpublic function set_registry(SimplePie_Registry $registry)\n\t{\n\t\t$this->registry = $registry;\n\t}\n\n\tpublic function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)\n\t{\n\t\tif ($this->is_feed($this->file))\n\t\t{\n\t\t\treturn $this->file;\n\t\t}\n\n\t\tif ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)\n\t\t{\n\t\t\t$sniffer = $this->registry->create('Content_Type_Sniffer', array($this->file));\n\t\t\tif ($sniffer->get_type() !== 'text/html')\n\t\t\t{\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tif ($type & ~SIMPLEPIE_LOCATOR_NONE)\n\t\t{\n\t\t\t$this->get_base();\n\t\t}\n\n\t\tif ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())\n\t\t{\n\t\t\treturn $working[0];\n\t\t}\n\n\t\tif ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())\n\t\t{\n\t\t\tif ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))\n\t\t\t{\n\t\t\t\treturn $working;\n\t\t\t}\n\n\t\t\tif ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))\n\t\t\t{\n\t\t\t\treturn $working;\n\t\t\t}\n\n\t\t\tif ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))\n\t\t\t{\n\t\t\t\treturn $working;\n\t\t\t}\n\n\t\t\tif ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))\n\t\t\t{\n\t\t\t\treturn $working;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic function is_feed($file)\n\t{\n\t\tif ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)\n\t\t{\n\t\t\t$sniffer = $this->registry->create('Content_Type_Sniffer', array($file));\n\t\t\t$sniffed = $sniffer->get_type();\n\t\t\tif (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\telseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic function get_base()\n\t{\n\t\tif ($this->dom === null)\n\t\t{\n\t\t\tthrow new SimplePie_Exception('DOMDocument not found, unable to use locator');\n\t\t}\n\t\t$this->http_base = $this->file->url;\n\t\t$this->base = $this->http_base;\n\t\t$elements = $this->dom->getElementsByTagName('base');\n\t\tforeach ($elements as $element)\n\t\t{\n\t\t\tif ($element->hasAttribute('href'))\n\t\t\t{\n\t\t\t\t$base = $this->registry->call('Misc', 'absolutize_url', array(trim($element->getAttribute('href')), $this->http_base));\n\t\t\t\tif ($base === false)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t$this->base = $base;\n\t\t\t\t$this->base_location = method_exists($element, 'getLineNo') ? $element->getLineNo() : 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic function autodiscovery()\n\t{\n\t\t$done = array();\n\t\t$feeds = array();\n\t\t$feeds = array_merge($feeds, $this->search_elements_by_tag('link', $done, $feeds));\n\t\t$feeds = array_merge($feeds, $this->search_elements_by_tag('a', $done, $feeds));\n\t\t$feeds = array_merge($feeds, $this->search_elements_by_tag('area', $done, $feeds));\n\n\t\tif (!empty($feeds))\n\t\t{\n\t\t\treturn array_values($feeds);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprotected function search_elements_by_tag($name, &$done, $feeds)\n\t{\n\t\tif ($this->dom === null)\n\t\t{\n\t\t\tthrow new SimplePie_Exception('DOMDocument not found, unable to use locator');\n\t\t}\n\n\t\t$links = $this->dom->getElementsByTagName($name);\n\t\tforeach ($links as $link)\n\t\t{\n\t\t\tif ($this->checked_feeds === $this->max_checked_feeds)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ($link->hasAttribute('href') && $link->hasAttribute('rel'))\n\t\t\t{\n\t\t\t\t$rel = array_unique($this->registry->call('Misc', 'space_seperated_tokens', array(strtolower($link->getAttribute('rel')))));\n\t\t\t\t$line = method_exists($link, 'getLineNo') ? $link->getLineNo() : 1;\n\n\t\t\t\tif ($this->base_location < $line)\n\t\t\t\t{\n\t\t\t\t\t$href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base));\n\t\t\t\t}\n\t\t\t\tif ($href === false)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !in_array('stylesheet', $rel) && $link->hasAttribute('type') && in_array(strtolower($this->registry->call('Misc', 'parse_mime', array($link->getAttribute('type')))), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))\n\t\t\t\t{\n\t\t\t\t\t$this->checked_feeds++;\n\t\t\t\t\t$headers = array(\n\t\t\t\t\t\t'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',\n\t\t\t\t\t);\n\t\t\t\t\t$feed = $this->registry->create('File', array($href, $this->timeout, 5, $headers, $this->useragent));\n\t\t\t\t\tif ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))\n\t\t\t\t\t{\n\t\t\t\t\t\t$feeds[$href] = $feed;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$done[] = $href;\n\t\t\t}\n\t\t}\n\n\t\treturn $feeds;\n\t}\n\n\tpublic function get_links()\n\t{\n\t\tif ($this->dom === null)\n\t\t{\n\t\t\tthrow new SimplePie_Exception('DOMDocument not found, unable to use locator');\n\t\t}\n\n\t\t$links = $this->dom->getElementsByTagName('a');\n\t\tforeach ($links as $link)\n\t\t{\n\t\t\tif ($link->hasAttribute('href'))\n\t\t\t{\n\t\t\t\t$href = trim($link->getAttribute('href'));\n\t\t\t\t$parsed = $this->registry->call('Misc', 'parse_url', array($href));\n\t\t\t\tif ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))\n\t\t\t\t{\n\t\t\t\t\tif ($this->base_location < $link->getLineNo())\n\t\t\t\t\t{\n\t\t\t\t\t\t$href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base));\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base));\n\t\t\t\t\t}\n\t\t\t\t\tif ($href === false)\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t$current = $this->registry->call('Misc', 'parse_url', array($this->file->url));\n\n\t\t\t\t\tif ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->local[] = $href;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->elsewhere[] = $href;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t$this->local = array_unique($this->local);\n\t\t$this->elsewhere = array_unique($this->elsewhere);\n\t\tif (!empty($this->local) || !empty($this->elsewhere))\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic function extension(&$array)\n\t{\n\t\tforeach ($array as $key => $value)\n\t\t{\n\t\t\tif ($this->checked_feeds === $this->max_checked_feeds)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))\n\t\t\t{\n\t\t\t\t$this->checked_feeds++;\n\n\t\t\t\t$headers = array(\n\t\t\t\t\t'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',\n\t\t\t\t);\n\t\t\t\t$feed = $this->registry->create('File', array($value, $this->timeout, 5, $headers, $this->useragent));\n\t\t\t\tif ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))\n\t\t\t\t{\n\t\t\t\t\treturn $feed;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tunset($array[$key]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic function body(&$array)\n\t{\n\t\tforeach ($array as $key => $value)\n\t\t{\n\t\t\tif ($this->checked_feeds === $this->max_checked_feeds)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (preg_match('/(rss|rdf|atom|xml)/i', $value))\n\t\t\t{\n\t\t\t\t$this->checked_feeds++;\n\t\t\t\t$headers = array(\n\t\t\t\t\t'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',\n\t\t\t\t);\n\t\t\t\t$feed = $this->registry->create('File', array($value, $this->timeout, 5, null, $this->useragent));\n\t\t\t\tif ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))\n\t\t\t\t{\n\t\t\t\t\treturn $feed;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tunset($array[$key]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n}\n\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Misc.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Miscellanous utilities\n *\n * @package SimplePie\n */\nclass SimplePie_Misc\n{\n\tpublic static function time_hms($seconds)\n\t{\n\t\t$time = '';\n\n\t\t$hours = floor($seconds / 3600);\n\t\t$remainder = $seconds % 3600;\n\t\tif ($hours > 0)\n\t\t{\n\t\t\t$time .= $hours.':';\n\t\t}\n\n\t\t$minutes = floor($remainder / 60);\n\t\t$seconds = $remainder % 60;\n\t\tif ($minutes < 10 && $hours > 0)\n\t\t{\n\t\t\t$minutes = '0' . $minutes;\n\t\t}\n\t\tif ($seconds < 10)\n\t\t{\n\t\t\t$seconds = '0' . $seconds;\n\t\t}\n\n\t\t$time .= $minutes.':';\n\t\t$time .= $seconds;\n\n\t\treturn $time;\n\t}\n\n\tpublic static function absolutize_url($relative, $base)\n\t{\n\t\t$iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);\n\t\tif ($iri === false)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\treturn $iri->get_uri();\n\t}\n\n\t/**\n\t * Get a HTML/XML element from a HTML string\n\t *\n\t * @deprecated Use DOMDocument instead (parsing HTML with regex is bad!)\n\t * @param string $realname Element name (including namespace prefix if applicable)\n\t * @param string $string HTML document\n\t * @return array\n\t */\n\tpublic static function get_element($realname, $string)\n\t{\n\t\t$return = array();\n\t\t$name = preg_quote($realname, '/');\n\t\tif (preg_match_all(\"/<($name)\" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . \"(>(.*)<\\/$name>|(\\/)?>)/siU\", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))\n\t\t{\n\t\t\tfor ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)\n\t\t\t{\n\t\t\t\t$return[$i]['tag'] = $realname;\n\t\t\t\t$return[$i]['full'] = $matches[$i][0][0];\n\t\t\t\t$return[$i]['offset'] = $matches[$i][0][1];\n\t\t\t\tif (strlen($matches[$i][3][0]) <= 2)\n\t\t\t\t{\n\t\t\t\t\t$return[$i]['self_closing'] = true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$return[$i]['self_closing'] = false;\n\t\t\t\t\t$return[$i]['content'] = $matches[$i][4][0];\n\t\t\t\t}\n\t\t\t\t$return[$i]['attribs'] = array();\n\t\t\t\tif (isset($matches[$i][2][0]) && preg_match_all('/[\\x09\\x0A\\x0B\\x0C\\x0D\\x20]+([^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x2F\\x3E][^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x2F\\x3D\\x3E]*)(?:[\\x09\\x0A\\x0B\\x0C\\x0D\\x20]*=[\\x09\\x0A\\x0B\\x0C\\x0D\\x20]*(?:\"([^\"]*)\"|\\'([^\\']*)\\'|([^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x22\\x27\\x3E][^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x3E]*)?))?/', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER))\n\t\t\t\t{\n\t\t\t\t\tfor ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (count($attribs[$j]) === 2)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$attribs[$j][2] = $attribs[$j][1];\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn $return;\n\t}\n\n\tpublic static function element_implode($element)\n\t{\n\t\t$full = \"<$element[tag]\";\n\t\tforeach ($element['attribs'] as $key => $value)\n\t\t{\n\t\t\t$key = strtolower($key);\n\t\t\t$full .= \" $key=\\\"\" . htmlspecialchars($value['data']) . '\"';\n\t\t}\n\t\tif ($element['self_closing'])\n\t\t{\n\t\t\t$full .= ' />';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$full .= \">$element[content]</$element[tag]>\";\n\t\t}\n\t\treturn $full;\n\t}\n\n\tpublic static function error($message, $level, $file, $line)\n\t{\n\t\tif ((ini_get('error_reporting') & $level) > 0)\n\t\t{\n\t\t\tswitch ($level)\n\t\t\t{\n\t\t\t\tcase E_USER_ERROR:\n\t\t\t\t\t$note = 'PHP Error';\n\t\t\t\t\tbreak;\n\t\t\t\tcase E_USER_WARNING:\n\t\t\t\t\t$note = 'PHP Warning';\n\t\t\t\t\tbreak;\n\t\t\t\tcase E_USER_NOTICE:\n\t\t\t\t\t$note = 'PHP Notice';\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t$note = 'Unknown Error';\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t$log_error = true;\n\t\t\tif (!function_exists('error_log'))\n\t\t\t{\n\t\t\t\t$log_error = false;\n\t\t\t}\n\n\t\t\t$log_file = @ini_get('error_log');\n\t\t\tif (!empty($log_file) && ('syslog' !== $log_file) && !@is_writable($log_file))\n\t\t\t{\n\t\t\t\t$log_error = false;\n\t\t\t}\n\n\t\t\tif ($log_error)\n\t\t\t{\n\t\t\t\t@error_log(\"$note: $message in $file on line $line\", 0);\n\t\t\t}\n\t\t}\n\n\t\treturn $message;\n\t}\n\n\tpublic static function fix_protocol($url, $http = 1)\n\t{\n\t\t$url = SimplePie_Misc::normalize_url($url);\n\t\t$parsed = SimplePie_Misc::parse_url($url);\n\t\tif ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')\n\t\t{\n\t\t\treturn SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);\n\t\t}\n\n\t\tif ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))\n\t\t{\n\t\t\treturn SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);\n\t\t}\n\n\t\tif ($http === 2 && $parsed['scheme'] !== '')\n\t\t{\n\t\t\treturn \"feed:$url\";\n\t\t}\n\t\telseif ($http === 3 && strtolower($parsed['scheme']) === 'http')\n\t\t{\n\t\t\treturn substr_replace($url, 'podcast', 0, 4);\n\t\t}\n\t\telseif ($http === 4 && strtolower($parsed['scheme']) === 'http')\n\t\t{\n\t\t\treturn substr_replace($url, 'itpc', 0, 4);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn $url;\n\t\t}\n\t}\n\n\tpublic static function parse_url($url)\n\t{\n\t\t$iri = new SimplePie_IRI($url);\n\t\treturn array(\n\t\t\t'scheme' => (string) $iri->scheme,\n\t\t\t'authority' => (string) $iri->authority,\n\t\t\t'path' => (string) $iri->path,\n\t\t\t'query' => (string) $iri->query,\n\t\t\t'fragment' => (string) $iri->fragment\n\t\t);\n\t}\n\n\tpublic static function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')\n\t{\n\t\t$iri = new SimplePie_IRI('');\n\t\t$iri->scheme = $scheme;\n\t\t$iri->authority = $authority;\n\t\t$iri->path = $path;\n\t\t$iri->query = $query;\n\t\t$iri->fragment = $fragment;\n\t\treturn $iri->get_uri();\n\t}\n\n\tpublic static function normalize_url($url)\n\t{\n\t\t$iri = new SimplePie_IRI($url);\n\t\treturn $iri->get_uri();\n\t}\n\n\tpublic static function percent_encoding_normalization($match)\n\t{\n\t\t$integer = hexdec($match[1]);\n\t\tif ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)\n\t\t{\n\t\t\treturn chr($integer);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn strtoupper($match[0]);\n\t\t}\n\t}\n\n\t/**\n\t * Converts a Windows-1252 encoded string to a UTF-8 encoded string\n\t *\n\t * @static\n\t * @param string $string Windows-1252 encoded string\n\t * @return string UTF-8 encoded string\n\t */\n\tpublic static function windows_1252_to_utf8($string)\n\t{\n\t\tstatic $convert_table = array(\"\\x80\" => \"\\xE2\\x82\\xAC\", \"\\x81\" => \"\\xEF\\xBF\\xBD\", \"\\x82\" => \"\\xE2\\x80\\x9A\", \"\\x83\" => \"\\xC6\\x92\", \"\\x84\" => \"\\xE2\\x80\\x9E\", \"\\x85\" => \"\\xE2\\x80\\xA6\", \"\\x86\" => \"\\xE2\\x80\\xA0\", \"\\x87\" => \"\\xE2\\x80\\xA1\", \"\\x88\" => \"\\xCB\\x86\", \"\\x89\" => \"\\xE2\\x80\\xB0\", \"\\x8A\" => \"\\xC5\\xA0\", \"\\x8B\" => \"\\xE2\\x80\\xB9\", \"\\x8C\" => \"\\xC5\\x92\", \"\\x8D\" => \"\\xEF\\xBF\\xBD\", \"\\x8E\" => \"\\xC5\\xBD\", \"\\x8F\" => \"\\xEF\\xBF\\xBD\", \"\\x90\" => \"\\xEF\\xBF\\xBD\", \"\\x91\" => \"\\xE2\\x80\\x98\", \"\\x92\" => \"\\xE2\\x80\\x99\", \"\\x93\" => \"\\xE2\\x80\\x9C\", \"\\x94\" => \"\\xE2\\x80\\x9D\", \"\\x95\" => \"\\xE2\\x80\\xA2\", \"\\x96\" => \"\\xE2\\x80\\x93\", \"\\x97\" => \"\\xE2\\x80\\x94\", \"\\x98\" => \"\\xCB\\x9C\", \"\\x99\" => \"\\xE2\\x84\\xA2\", \"\\x9A\" => \"\\xC5\\xA1\", \"\\x9B\" => \"\\xE2\\x80\\xBA\", \"\\x9C\" => \"\\xC5\\x93\", \"\\x9D\" => \"\\xEF\\xBF\\xBD\", \"\\x9E\" => \"\\xC5\\xBE\", \"\\x9F\" => \"\\xC5\\xB8\", \"\\xA0\" => \"\\xC2\\xA0\", \"\\xA1\" => \"\\xC2\\xA1\", \"\\xA2\" => \"\\xC2\\xA2\", \"\\xA3\" => \"\\xC2\\xA3\", \"\\xA4\" => \"\\xC2\\xA4\", \"\\xA5\" => \"\\xC2\\xA5\", \"\\xA6\" => \"\\xC2\\xA6\", \"\\xA7\" => \"\\xC2\\xA7\", \"\\xA8\" => \"\\xC2\\xA8\", \"\\xA9\" => \"\\xC2\\xA9\", \"\\xAA\" => \"\\xC2\\xAA\", \"\\xAB\" => \"\\xC2\\xAB\", \"\\xAC\" => \"\\xC2\\xAC\", \"\\xAD\" => \"\\xC2\\xAD\", \"\\xAE\" => \"\\xC2\\xAE\", \"\\xAF\" => \"\\xC2\\xAF\", \"\\xB0\" => \"\\xC2\\xB0\", \"\\xB1\" => \"\\xC2\\xB1\", \"\\xB2\" => \"\\xC2\\xB2\", \"\\xB3\" => \"\\xC2\\xB3\", \"\\xB4\" => \"\\xC2\\xB4\", \"\\xB5\" => \"\\xC2\\xB5\", \"\\xB6\" => \"\\xC2\\xB6\", \"\\xB7\" => \"\\xC2\\xB7\", \"\\xB8\" => \"\\xC2\\xB8\", \"\\xB9\" => \"\\xC2\\xB9\", \"\\xBA\" => \"\\xC2\\xBA\", \"\\xBB\" => \"\\xC2\\xBB\", \"\\xBC\" => \"\\xC2\\xBC\", \"\\xBD\" => \"\\xC2\\xBD\", \"\\xBE\" => \"\\xC2\\xBE\", \"\\xBF\" => \"\\xC2\\xBF\", \"\\xC0\" => \"\\xC3\\x80\", \"\\xC1\" => \"\\xC3\\x81\", \"\\xC2\" => \"\\xC3\\x82\", \"\\xC3\" => \"\\xC3\\x83\", \"\\xC4\" => \"\\xC3\\x84\", \"\\xC5\" => \"\\xC3\\x85\", \"\\xC6\" => \"\\xC3\\x86\", \"\\xC7\" => \"\\xC3\\x87\", \"\\xC8\" => \"\\xC3\\x88\", \"\\xC9\" => \"\\xC3\\x89\", \"\\xCA\" => \"\\xC3\\x8A\", \"\\xCB\" => \"\\xC3\\x8B\", \"\\xCC\" => \"\\xC3\\x8C\", \"\\xCD\" => \"\\xC3\\x8D\", \"\\xCE\" => \"\\xC3\\x8E\", \"\\xCF\" => \"\\xC3\\x8F\", \"\\xD0\" => \"\\xC3\\x90\", \"\\xD1\" => \"\\xC3\\x91\", \"\\xD2\" => \"\\xC3\\x92\", \"\\xD3\" => \"\\xC3\\x93\", \"\\xD4\" => \"\\xC3\\x94\", \"\\xD5\" => \"\\xC3\\x95\", \"\\xD6\" => \"\\xC3\\x96\", \"\\xD7\" => \"\\xC3\\x97\", \"\\xD8\" => \"\\xC3\\x98\", \"\\xD9\" => \"\\xC3\\x99\", \"\\xDA\" => \"\\xC3\\x9A\", \"\\xDB\" => \"\\xC3\\x9B\", \"\\xDC\" => \"\\xC3\\x9C\", \"\\xDD\" => \"\\xC3\\x9D\", \"\\xDE\" => \"\\xC3\\x9E\", \"\\xDF\" => \"\\xC3\\x9F\", \"\\xE0\" => \"\\xC3\\xA0\", \"\\xE1\" => \"\\xC3\\xA1\", \"\\xE2\" => \"\\xC3\\xA2\", \"\\xE3\" => \"\\xC3\\xA3\", \"\\xE4\" => \"\\xC3\\xA4\", \"\\xE5\" => \"\\xC3\\xA5\", \"\\xE6\" => \"\\xC3\\xA6\", \"\\xE7\" => \"\\xC3\\xA7\", \"\\xE8\" => \"\\xC3\\xA8\", \"\\xE9\" => \"\\xC3\\xA9\", \"\\xEA\" => \"\\xC3\\xAA\", \"\\xEB\" => \"\\xC3\\xAB\", \"\\xEC\" => \"\\xC3\\xAC\", \"\\xED\" => \"\\xC3\\xAD\", \"\\xEE\" => \"\\xC3\\xAE\", \"\\xEF\" => \"\\xC3\\xAF\", \"\\xF0\" => \"\\xC3\\xB0\", \"\\xF1\" => \"\\xC3\\xB1\", \"\\xF2\" => \"\\xC3\\xB2\", \"\\xF3\" => \"\\xC3\\xB3\", \"\\xF4\" => \"\\xC3\\xB4\", \"\\xF5\" => \"\\xC3\\xB5\", \"\\xF6\" => \"\\xC3\\xB6\", \"\\xF7\" => \"\\xC3\\xB7\", \"\\xF8\" => \"\\xC3\\xB8\", \"\\xF9\" => \"\\xC3\\xB9\", \"\\xFA\" => \"\\xC3\\xBA\", \"\\xFB\" => \"\\xC3\\xBB\", \"\\xFC\" => \"\\xC3\\xBC\", \"\\xFD\" => \"\\xC3\\xBD\", \"\\xFE\" => \"\\xC3\\xBE\", \"\\xFF\" => \"\\xC3\\xBF\");\n\n\t\treturn strtr($string, $convert_table);\n\t}\n\n\t/**\n\t * Change a string from one encoding to another\n\t *\n\t * @param string $data Raw data in $input encoding\n\t * @param string $input Encoding of $data\n\t * @param string $output Encoding you want\n\t * @return string|boolean False if we can't convert it\n\t */\n\tpublic static function change_encoding($data, $input, $output)\n\t{\n\t\t$input = SimplePie_Misc::encoding($input);\n\t\t$output = SimplePie_Misc::encoding($output);\n\n\t\t// We fail to fail on non US-ASCII bytes\n\t\tif ($input === 'US-ASCII')\n\t\t{\n\t\t\tstatic $non_ascii_octects = '';\n\t\t\tif (!$non_ascii_octects)\n\t\t\t{\n\t\t\t\tfor ($i = 0x80; $i <= 0xFF; $i++)\n\t\t\t\t{\n\t\t\t\t\t$non_ascii_octects .= chr($i);\n\t\t\t\t}\n\t\t\t}\n\t\t\t$data = substr($data, 0, strcspn($data, $non_ascii_octects));\n\t\t}\n\n\t\t// This is first, as behaviour of this is completely predictable\n\t\tif ($input === 'windows-1252' && $output === 'UTF-8')\n\t\t{\n\t\t\treturn SimplePie_Misc::windows_1252_to_utf8($data);\n\t\t}\n\t\t// This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).\n\t\telseif (function_exists('mb_convert_encoding') && ($return = SimplePie_Misc::change_encoding_mbstring($data, $input, $output)))\n\t\t{\n\t\t\treturn $return;\n \t\t}\n\t\t// This is last, as behaviour of this varies with OS userland and PHP version\n\t\telseif (function_exists('iconv') && ($return = SimplePie_Misc::change_encoding_iconv($data, $input, $output)))\n\t\t{\n\t\t\treturn $return;\n\t\t}\n\t\t// If we can't do anything, just fail\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprotected static function change_encoding_mbstring($data, $input, $output)\n\t{\n\t\tif ($input === 'windows-949')\n\t\t{\n\t\t\t$input = 'EUC-KR';\n\t\t}\n\t\tif ($output === 'windows-949')\n\t\t{\n\t\t\t$output = 'EUC-KR';\n\t\t}\n\t\tif ($input === 'Windows-31J')\n\t\t{\n\t\t\t$input = 'SJIS';\n\t\t}\n\t\tif ($output === 'Windows-31J')\n\t\t{\n\t\t\t$output = 'SJIS';\n\t\t}\n\n\t\t// Check that the encoding is supported\n\t\tif (@mb_convert_encoding(\"\\x80\", 'UTF-16BE', $input) === \"\\x00\\x80\")\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tif (!in_array($input, mb_list_encodings()))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\t// Let's do some conversion\n\t\tif ($return = @mb_convert_encoding($data, $output, $input))\n\t\t{\n\t\t\treturn $return;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprotected static function change_encoding_iconv($data, $input, $output)\n\t{\n\t\treturn @iconv($input, $output, $data);\n\t}\n\n\t/**\n\t * Normalize an encoding name\n\t *\n\t * This is automatically generated by create.php\n\t *\n\t * To generate it, run `php create.php` on the command line, and copy the\n\t * output to replace this function.\n\t *\n\t * @param string $charset Character set to standardise\n\t * @return string Standardised name\n\t */\n\tpublic static function encoding($charset)\n\t{\n\t\t// Normalization from UTS #22\n\t\tswitch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\\1', $charset)))\n\t\t{\n\t\t\tcase 'adobestandardencoding':\n\t\t\tcase 'csadobestandardencoding':\n\t\t\t\treturn 'Adobe-Standard-Encoding';\n\n\t\t\tcase 'adobesymbolencoding':\n\t\t\tcase 'cshppsmath':\n\t\t\t\treturn 'Adobe-Symbol-Encoding';\n\n\t\t\tcase 'ami1251':\n\t\t\tcase 'amiga1251':\n\t\t\t\treturn 'Amiga-1251';\n\n\t\t\tcase 'ansix31101983':\n\t\t\tcase 'csat5001983':\n\t\t\tcase 'csiso99naplps':\n\t\t\tcase 'isoir99':\n\t\t\tcase 'naplps':\n\t\t\t\treturn 'ANSI_X3.110-1983';\n\n\t\t\tcase 'arabic7':\n\t\t\tcase 'asmo449':\n\t\t\tcase 'csiso89asmo449':\n\t\t\tcase 'iso9036':\n\t\t\tcase 'isoir89':\n\t\t\t\treturn 'ASMO_449';\n\n\t\t\tcase 'big5':\n\t\t\tcase 'csbig5':\n\t\t\t\treturn 'Big5';\n\n\t\t\tcase 'big5hkscs':\n\t\t\t\treturn 'Big5-HKSCS';\n\n\t\t\tcase 'bocu1':\n\t\t\tcase 'csbocu1':\n\t\t\t\treturn 'BOCU-1';\n\n\t\t\tcase 'brf':\n\t\t\tcase 'csbrf':\n\t\t\t\treturn 'BRF';\n\n\t\t\tcase 'bs4730':\n\t\t\tcase 'csiso4unitedkingdom':\n\t\t\tcase 'gb':\n\t\t\tcase 'iso646gb':\n\t\t\tcase 'isoir4':\n\t\t\tcase 'uk':\n\t\t\t\treturn 'BS_4730';\n\n\t\t\tcase 'bsviewdata':\n\t\t\tcase 'csiso47bsviewdata':\n\t\t\tcase 'isoir47':\n\t\t\t\treturn 'BS_viewdata';\n\n\t\t\tcase 'cesu8':\n\t\t\tcase 'cscesu8':\n\t\t\t\treturn 'CESU-8';\n\n\t\t\tcase 'ca':\n\t\t\tcase 'csa71':\n\t\t\tcase 'csaz243419851':\n\t\t\tcase 'csiso121canadian1':\n\t\t\tcase 'iso646ca':\n\t\t\tcase 'isoir121':\n\t\t\t\treturn 'CSA_Z243.4-1985-1';\n\n\t\t\tcase 'csa72':\n\t\t\tcase 'csaz243419852':\n\t\t\tcase 'csiso122canadian2':\n\t\t\tcase 'iso646ca2':\n\t\t\tcase 'isoir122':\n\t\t\t\treturn 'CSA_Z243.4-1985-2';\n\n\t\t\tcase 'csaz24341985gr':\n\t\t\tcase 'csiso123csaz24341985gr':\n\t\t\tcase 'isoir123':\n\t\t\t\treturn 'CSA_Z243.4-1985-gr';\n\n\t\t\tcase 'csiso139csn369103':\n\t\t\tcase 'csn369103':\n\t\t\tcase 'isoir139':\n\t\t\t\treturn 'CSN_369103';\n\n\t\t\tcase 'csdecmcs':\n\t\t\tcase 'dec':\n\t\t\tcase 'decmcs':\n\t\t\t\treturn 'DEC-MCS';\n\n\t\t\tcase 'csiso21german':\n\t\t\tcase 'de':\n\t\t\tcase 'din66003':\n\t\t\tcase 'iso646de':\n\t\t\tcase 'isoir21':\n\t\t\t\treturn 'DIN_66003';\n\n\t\t\tcase 'csdkus':\n\t\t\tcase 'dkus':\n\t\t\t\treturn 'dk-us';\n\n\t\t\tcase 'csiso646danish':\n\t\t\tcase 'dk':\n\t\t\tcase 'ds2089':\n\t\t\tcase 'iso646dk':\n\t\t\t\treturn 'DS_2089';\n\n\t\t\tcase 'csibmebcdicatde':\n\t\t\tcase 'ebcdicatde':\n\t\t\t\treturn 'EBCDIC-AT-DE';\n\n\t\t\tcase 'csebcdicatdea':\n\t\t\tcase 'ebcdicatdea':\n\t\t\t\treturn 'EBCDIC-AT-DE-A';\n\n\t\t\tcase 'csebcdiccafr':\n\t\t\tcase 'ebcdiccafr':\n\t\t\t\treturn 'EBCDIC-CA-FR';\n\n\t\t\tcase 'csebcdicdkno':\n\t\t\tcase 'ebcdicdkno':\n\t\t\t\treturn 'EBCDIC-DK-NO';\n\n\t\t\tcase 'csebcdicdknoa':\n\t\t\tcase 'ebcdicdknoa':\n\t\t\t\treturn 'EBCDIC-DK-NO-A';\n\n\t\t\tcase 'csebcdices':\n\t\t\tcase 'ebcdices':\n\t\t\t\treturn 'EBCDIC-ES';\n\n\t\t\tcase 'csebcdicesa':\n\t\t\tcase 'ebcdicesa':\n\t\t\t\treturn 'EBCDIC-ES-A';\n\n\t\t\tcase 'csebcdicess':\n\t\t\tcase 'ebcdicess':\n\t\t\t\treturn 'EBCDIC-ES-S';\n\n\t\t\tcase 'csebcdicfise':\n\t\t\tcase 'ebcdicfise':\n\t\t\t\treturn 'EBCDIC-FI-SE';\n\n\t\t\tcase 'csebcdicfisea':\n\t\t\tcase 'ebcdicfisea':\n\t\t\t\treturn 'EBCDIC-FI-SE-A';\n\n\t\t\tcase 'csebcdicfr':\n\t\t\tcase 'ebcdicfr':\n\t\t\t\treturn 'EBCDIC-FR';\n\n\t\t\tcase 'csebcdicit':\n\t\t\tcase 'ebcdicit':\n\t\t\t\treturn 'EBCDIC-IT';\n\n\t\t\tcase 'csebcdicpt':\n\t\t\tcase 'ebcdicpt':\n\t\t\t\treturn 'EBCDIC-PT';\n\n\t\t\tcase 'csebcdicuk':\n\t\t\tcase 'ebcdicuk':\n\t\t\t\treturn 'EBCDIC-UK';\n\n\t\t\tcase 'csebcdicus':\n\t\t\tcase 'ebcdicus':\n\t\t\t\treturn 'EBCDIC-US';\n\n\t\t\tcase 'csiso111ecmacyrillic':\n\t\t\tcase 'ecmacyrillic':\n\t\t\tcase 'isoir111':\n\t\t\tcase 'koi8e':\n\t\t\t\treturn 'ECMA-cyrillic';\n\n\t\t\tcase 'csiso17spanish':\n\t\t\tcase 'es':\n\t\t\tcase 'iso646es':\n\t\t\tcase 'isoir17':\n\t\t\t\treturn 'ES';\n\n\t\t\tcase 'csiso85spanish2':\n\t\t\tcase 'es2':\n\t\t\tcase 'iso646es2':\n\t\t\tcase 'isoir85':\n\t\t\t\treturn 'ES2';\n\n\t\t\tcase 'cseucpkdfmtjapanese':\n\t\t\tcase 'eucjp':\n\t\t\tcase 'extendedunixcodepackedformatforjapanese':\n\t\t\t\treturn 'EUC-JP';\n\n\t\t\tcase 'cseucfixwidjapanese':\n\t\t\tcase 'extendedunixcodefixedwidthforjapanese':\n\t\t\t\treturn 'Extended_UNIX_Code_Fixed_Width_for_Japanese';\n\n\t\t\tcase 'gb18030':\n\t\t\t\treturn 'GB18030';\n\n\t\t\tcase 'chinese':\n\t\t\tcase 'cp936':\n\t\t\tcase 'csgb2312':\n\t\t\tcase 'csiso58gb231280':\n\t\t\tcase 'gb2312':\n\t\t\tcase 'gb231280':\n\t\t\tcase 'gbk':\n\t\t\tcase 'isoir58':\n\t\t\tcase 'ms936':\n\t\t\tcase 'windows936':\n\t\t\t\treturn 'GBK';\n\n\t\t\tcase 'cn':\n\t\t\tcase 'csiso57gb1988':\n\t\t\tcase 'gb198880':\n\t\t\tcase 'iso646cn':\n\t\t\tcase 'isoir57':\n\t\t\t\treturn 'GB_1988-80';\n\n\t\t\tcase 'csiso153gost1976874':\n\t\t\tcase 'gost1976874':\n\t\t\tcase 'isoir153':\n\t\t\tcase 'stsev35888':\n\t\t\t\treturn 'GOST_19768-74';\n\n\t\t\tcase 'csiso150':\n\t\t\tcase 'csiso150greekccitt':\n\t\t\tcase 'greekccitt':\n\t\t\tcase 'isoir150':\n\t\t\t\treturn 'greek-ccitt';\n\n\t\t\tcase 'csiso88greek7':\n\t\t\tcase 'greek7':\n\t\t\tcase 'isoir88':\n\t\t\t\treturn 'greek7';\n\n\t\t\tcase 'csiso18greek7old':\n\t\t\tcase 'greek7old':\n\t\t\tcase 'isoir18':\n\t\t\t\treturn 'greek7-old';\n\n\t\t\tcase 'cshpdesktop':\n\t\t\tcase 'hpdesktop':\n\t\t\t\treturn 'HP-DeskTop';\n\n\t\t\tcase 'cshplegal':\n\t\t\tcase 'hplegal':\n\t\t\t\treturn 'HP-Legal';\n\n\t\t\tcase 'cshpmath8':\n\t\t\tcase 'hpmath8':\n\t\t\t\treturn 'HP-Math8';\n\n\t\t\tcase 'cshppifont':\n\t\t\tcase 'hppifont':\n\t\t\t\treturn 'HP-Pi-font';\n\n\t\t\tcase 'cshproman8':\n\t\t\tcase 'hproman8':\n\t\t\tcase 'r8':\n\t\t\tcase 'roman8':\n\t\t\t\treturn 'hp-roman8';\n\n\t\t\tcase 'hzgb2312':\n\t\t\t\treturn 'HZ-GB-2312';\n\n\t\t\tcase 'csibmsymbols':\n\t\t\tcase 'ibmsymbols':\n\t\t\t\treturn 'IBM-Symbols';\n\n\t\t\tcase 'csibmthai':\n\t\t\tcase 'ibmthai':\n\t\t\t\treturn 'IBM-Thai';\n\n\t\t\tcase 'cp37':\n\t\t\tcase 'csibm37':\n\t\t\tcase 'ebcdiccpca':\n\t\t\tcase 'ebcdiccpnl':\n\t\t\tcase 'ebcdiccpus':\n\t\t\tcase 'ebcdiccpwt':\n\t\t\tcase 'ibm37':\n\t\t\t\treturn 'IBM037';\n\n\t\t\tcase 'cp38':\n\t\t\tcase 'csibm38':\n\t\t\tcase 'ebcdicint':\n\t\t\tcase 'ibm38':\n\t\t\t\treturn 'IBM038';\n\n\t\t\tcase 'cp273':\n\t\t\tcase 'csibm273':\n\t\t\tcase 'ibm273':\n\t\t\t\treturn 'IBM273';\n\n\t\t\tcase 'cp274':\n\t\t\tcase 'csibm274':\n\t\t\tcase 'ebcdicbe':\n\t\t\tcase 'ibm274':\n\t\t\t\treturn 'IBM274';\n\n\t\t\tcase 'cp275':\n\t\t\tcase 'csibm275':\n\t\t\tcase 'ebcdicbr':\n\t\t\tcase 'ibm275':\n\t\t\t\treturn 'IBM275';\n\n\t\t\tcase 'csibm277':\n\t\t\tcase 'ebcdiccpdk':\n\t\t\tcase 'ebcdiccpno':\n\t\t\tcase 'ibm277':\n\t\t\t\treturn 'IBM277';\n\n\t\t\tcase 'cp278':\n\t\t\tcase 'csibm278':\n\t\t\tcase 'ebcdiccpfi':\n\t\t\tcase 'ebcdiccpse':\n\t\t\tcase 'ibm278':\n\t\t\t\treturn 'IBM278';\n\n\t\t\tcase 'cp280':\n\t\t\tcase 'csibm280':\n\t\t\tcase 'ebcdiccpit':\n\t\t\tcase 'ibm280':\n\t\t\t\treturn 'IBM280';\n\n\t\t\tcase 'cp281':\n\t\t\tcase 'csibm281':\n\t\t\tcase 'ebcdicjpe':\n\t\t\tcase 'ibm281':\n\t\t\t\treturn 'IBM281';\n\n\t\t\tcase 'cp284':\n\t\t\tcase 'csibm284':\n\t\t\tcase 'ebcdiccpes':\n\t\t\tcase 'ibm284':\n\t\t\t\treturn 'IBM284';\n\n\t\t\tcase 'cp285':\n\t\t\tcase 'csibm285':\n\t\t\tcase 'ebcdiccpgb':\n\t\t\tcase 'ibm285':\n\t\t\t\treturn 'IBM285';\n\n\t\t\tcase 'cp290':\n\t\t\tcase 'csibm290':\n\t\t\tcase 'ebcdicjpkana':\n\t\t\tcase 'ibm290':\n\t\t\t\treturn 'IBM290';\n\n\t\t\tcase 'cp297':\n\t\t\tcase 'csibm297':\n\t\t\tcase 'ebcdiccpfr':\n\t\t\tcase 'ibm297':\n\t\t\t\treturn 'IBM297';\n\n\t\t\tcase 'cp420':\n\t\t\tcase 'csibm420':\n\t\t\tcase 'ebcdiccpar1':\n\t\t\tcase 'ibm420':\n\t\t\t\treturn 'IBM420';\n\n\t\t\tcase 'cp423':\n\t\t\tcase 'csibm423':\n\t\t\tcase 'ebcdiccpgr':\n\t\t\tcase 'ibm423':\n\t\t\t\treturn 'IBM423';\n\n\t\t\tcase 'cp424':\n\t\t\tcase 'csibm424':\n\t\t\tcase 'ebcdiccphe':\n\t\t\tcase 'ibm424':\n\t\t\t\treturn 'IBM424';\n\n\t\t\tcase '437':\n\t\t\tcase 'cp437':\n\t\t\tcase 'cspc8codepage437':\n\t\t\tcase 'ibm437':\n\t\t\t\treturn 'IBM437';\n\n\t\t\tcase 'cp500':\n\t\t\tcase 'csibm500':\n\t\t\tcase 'ebcdiccpbe':\n\t\t\tcase 'ebcdiccpch':\n\t\t\tcase 'ibm500':\n\t\t\t\treturn 'IBM500';\n\n\t\t\tcase 'cp775':\n\t\t\tcase 'cspc775baltic':\n\t\t\tcase 'ibm775':\n\t\t\t\treturn 'IBM775';\n\n\t\t\tcase '850':\n\t\t\tcase 'cp850':\n\t\t\tcase 'cspc850multilingual':\n\t\t\tcase 'ibm850':\n\t\t\t\treturn 'IBM850';\n\n\t\t\tcase '851':\n\t\t\tcase 'cp851':\n\t\t\tcase 'csibm851':\n\t\t\tcase 'ibm851':\n\t\t\t\treturn 'IBM851';\n\n\t\t\tcase '852':\n\t\t\tcase 'cp852':\n\t\t\tcase 'cspcp852':\n\t\t\tcase 'ibm852':\n\t\t\t\treturn 'IBM852';\n\n\t\t\tcase '855':\n\t\t\tcase 'cp855':\n\t\t\tcase 'csibm855':\n\t\t\tcase 'ibm855':\n\t\t\t\treturn 'IBM855';\n\n\t\t\tcase '857':\n\t\t\tcase 'cp857':\n\t\t\tcase 'csibm857':\n\t\t\tcase 'ibm857':\n\t\t\t\treturn 'IBM857';\n\n\t\t\tcase 'ccsid858':\n\t\t\tcase 'cp858':\n\t\t\tcase 'ibm858':\n\t\t\tcase 'pcmultilingual850euro':\n\t\t\t\treturn 'IBM00858';\n\n\t\t\tcase '860':\n\t\t\tcase 'cp860':\n\t\t\tcase 'csibm860':\n\t\t\tcase 'ibm860':\n\t\t\t\treturn 'IBM860';\n\n\t\t\tcase '861':\n\t\t\tcase 'cp861':\n\t\t\tcase 'cpis':\n\t\t\tcase 'csibm861':\n\t\t\tcase 'ibm861':\n\t\t\t\treturn 'IBM861';\n\n\t\t\tcase '862':\n\t\t\tcase 'cp862':\n\t\t\tcase 'cspc862latinhebrew':\n\t\t\tcase 'ibm862':\n\t\t\t\treturn 'IBM862';\n\n\t\t\tcase '863':\n\t\t\tcase 'cp863':\n\t\t\tcase 'csibm863':\n\t\t\tcase 'ibm863':\n\t\t\t\treturn 'IBM863';\n\n\t\t\tcase 'cp864':\n\t\t\tcase 'csibm864':\n\t\t\tcase 'ibm864':\n\t\t\t\treturn 'IBM864';\n\n\t\t\tcase '865':\n\t\t\tcase 'cp865':\n\t\t\tcase 'csibm865':\n\t\t\tcase 'ibm865':\n\t\t\t\treturn 'IBM865';\n\n\t\t\tcase '866':\n\t\t\tcase 'cp866':\n\t\t\tcase 'csibm866':\n\t\t\tcase 'ibm866':\n\t\t\t\treturn 'IBM866';\n\n\t\t\tcase 'cp868':\n\t\t\tcase 'cpar':\n\t\t\tcase 'csibm868':\n\t\t\tcase 'ibm868':\n\t\t\t\treturn 'IBM868';\n\n\t\t\tcase '869':\n\t\t\tcase 'cp869':\n\t\t\tcase 'cpgr':\n\t\t\tcase 'csibm869':\n\t\t\tcase 'ibm869':\n\t\t\t\treturn 'IBM869';\n\n\t\t\tcase 'cp870':\n\t\t\tcase 'csibm870':\n\t\t\tcase 'ebcdiccproece':\n\t\t\tcase 'ebcdiccpyu':\n\t\t\tcase 'ibm870':\n\t\t\t\treturn 'IBM870';\n\n\t\t\tcase 'cp871':\n\t\t\tcase 'csibm871':\n\t\t\tcase 'ebcdiccpis':\n\t\t\tcase 'ibm871':\n\t\t\t\treturn 'IBM871';\n\n\t\t\tcase 'cp880':\n\t\t\tcase 'csibm880':\n\t\t\tcase 'ebcdiccyrillic':\n\t\t\tcase 'ibm880':\n\t\t\t\treturn 'IBM880';\n\n\t\t\tcase 'cp891':\n\t\t\tcase 'csibm891':\n\t\t\tcase 'ibm891':\n\t\t\t\treturn 'IBM891';\n\n\t\t\tcase 'cp903':\n\t\t\tcase 'csibm903':\n\t\t\tcase 'ibm903':\n\t\t\t\treturn 'IBM903';\n\n\t\t\tcase '904':\n\t\t\tcase 'cp904':\n\t\t\tcase 'csibbm904':\n\t\t\tcase 'ibm904':\n\t\t\t\treturn 'IBM904';\n\n\t\t\tcase 'cp905':\n\t\t\tcase 'csibm905':\n\t\t\tcase 'ebcdiccptr':\n\t\t\tcase 'ibm905':\n\t\t\t\treturn 'IBM905';\n\n\t\t\tcase 'cp918':\n\t\t\tcase 'csibm918':\n\t\t\tcase 'ebcdiccpar2':\n\t\t\tcase 'ibm918':\n\t\t\t\treturn 'IBM918';\n\n\t\t\tcase 'ccsid924':\n\t\t\tcase 'cp924':\n\t\t\tcase 'ebcdiclatin9euro':\n\t\t\tcase 'ibm924':\n\t\t\t\treturn 'IBM00924';\n\n\t\t\tcase 'cp1026':\n\t\t\tcase 'csibm1026':\n\t\t\tcase 'ibm1026':\n\t\t\t\treturn 'IBM1026';\n\n\t\t\tcase 'ibm1047':\n\t\t\t\treturn 'IBM1047';\n\n\t\t\tcase 'ccsid1140':\n\t\t\tcase 'cp1140':\n\t\t\tcase 'ebcdicus37euro':\n\t\t\tcase 'ibm1140':\n\t\t\t\treturn 'IBM01140';\n\n\t\t\tcase 'ccsid1141':\n\t\t\tcase 'cp1141':\n\t\t\tcase 'ebcdicde273euro':\n\t\t\tcase 'ibm1141':\n\t\t\t\treturn 'IBM01141';\n\n\t\t\tcase 'ccsid1142':\n\t\t\tcase 'cp1142':\n\t\t\tcase 'ebcdicdk277euro':\n\t\t\tcase 'ebcdicno277euro':\n\t\t\tcase 'ibm1142':\n\t\t\t\treturn 'IBM01142';\n\n\t\t\tcase 'ccsid1143':\n\t\t\tcase 'cp1143':\n\t\t\tcase 'ebcdicfi278euro':\n\t\t\tcase 'ebcdicse278euro':\n\t\t\tcase 'ibm1143':\n\t\t\t\treturn 'IBM01143';\n\n\t\t\tcase 'ccsid1144':\n\t\t\tcase 'cp1144':\n\t\t\tcase 'ebcdicit280euro':\n\t\t\tcase 'ibm1144':\n\t\t\t\treturn 'IBM01144';\n\n\t\t\tcase 'ccsid1145':\n\t\t\tcase 'cp1145':\n\t\t\tcase 'ebcdices284euro':\n\t\t\tcase 'ibm1145':\n\t\t\t\treturn 'IBM01145';\n\n\t\t\tcase 'ccsid1146':\n\t\t\tcase 'cp1146':\n\t\t\tcase 'ebcdicgb285euro':\n\t\t\tcase 'ibm1146':\n\t\t\t\treturn 'IBM01146';\n\n\t\t\tcase 'ccsid1147':\n\t\t\tcase 'cp1147':\n\t\t\tcase 'ebcdicfr297euro':\n\t\t\tcase 'ibm1147':\n\t\t\t\treturn 'IBM01147';\n\n\t\t\tcase 'ccsid1148':\n\t\t\tcase 'cp1148':\n\t\t\tcase 'ebcdicinternational500euro':\n\t\t\tcase 'ibm1148':\n\t\t\t\treturn 'IBM01148';\n\n\t\t\tcase 'ccsid1149':\n\t\t\tcase 'cp1149':\n\t\t\tcase 'ebcdicis871euro':\n\t\t\tcase 'ibm1149':\n\t\t\t\treturn 'IBM01149';\n\n\t\t\tcase 'csiso143iecp271':\n\t\t\tcase 'iecp271':\n\t\t\tcase 'isoir143':\n\t\t\t\treturn 'IEC_P27-1';\n\n\t\t\tcase 'csiso49inis':\n\t\t\tcase 'inis':\n\t\t\tcase 'isoir49':\n\t\t\t\treturn 'INIS';\n\n\t\t\tcase 'csiso50inis8':\n\t\t\tcase 'inis8':\n\t\t\tcase 'isoir50':\n\t\t\t\treturn 'INIS-8';\n\n\t\t\tcase 'csiso51iniscyrillic':\n\t\t\tcase 'iniscyrillic':\n\t\t\tcase 'isoir51':\n\t\t\t\treturn 'INIS-cyrillic';\n\n\t\t\tcase 'csinvariant':\n\t\t\tcase 'invariant':\n\t\t\t\treturn 'INVARIANT';\n\n\t\t\tcase 'iso2022cn':\n\t\t\t\treturn 'ISO-2022-CN';\n\n\t\t\tcase 'iso2022cnext':\n\t\t\t\treturn 'ISO-2022-CN-EXT';\n\n\t\t\tcase 'csiso2022jp':\n\t\t\tcase 'iso2022jp':\n\t\t\t\treturn 'ISO-2022-JP';\n\n\t\t\tcase 'csiso2022jp2':\n\t\t\tcase 'iso2022jp2':\n\t\t\t\treturn 'ISO-2022-JP-2';\n\n\t\t\tcase 'csiso2022kr':\n\t\t\tcase 'iso2022kr':\n\t\t\t\treturn 'ISO-2022-KR';\n\n\t\t\tcase 'cswindows30latin1':\n\t\t\tcase 'iso88591windows30latin1':\n\t\t\t\treturn 'ISO-8859-1-Windows-3.0-Latin-1';\n\n\t\t\tcase 'cswindows31latin1':\n\t\t\tcase 'iso88591windows31latin1':\n\t\t\t\treturn 'ISO-8859-1-Windows-3.1-Latin-1';\n\n\t\t\tcase 'csisolatin2':\n\t\t\tcase 'iso88592':\n\t\t\tcase 'iso885921987':\n\t\t\tcase 'isoir101':\n\t\t\tcase 'l2':\n\t\t\tcase 'latin2':\n\t\t\t\treturn 'ISO-8859-2';\n\n\t\t\tcase 'cswindows31latin2':\n\t\t\tcase 'iso88592windowslatin2':\n\t\t\t\treturn 'ISO-8859-2-Windows-Latin-2';\n\n\t\t\tcase 'csisolatin3':\n\t\t\tcase 'iso88593':\n\t\t\tcase 'iso885931988':\n\t\t\tcase 'isoir109':\n\t\t\tcase 'l3':\n\t\t\tcase 'latin3':\n\t\t\t\treturn 'ISO-8859-3';\n\n\t\t\tcase 'csisolatin4':\n\t\t\tcase 'iso88594':\n\t\t\tcase 'iso885941988':\n\t\t\tcase 'isoir110':\n\t\t\tcase 'l4':\n\t\t\tcase 'latin4':\n\t\t\t\treturn 'ISO-8859-4';\n\n\t\t\tcase 'csisolatincyrillic':\n\t\t\tcase 'cyrillic':\n\t\t\tcase 'iso88595':\n\t\t\tcase 'iso885951988':\n\t\t\tcase 'isoir144':\n\t\t\t\treturn 'ISO-8859-5';\n\n\t\t\tcase 'arabic':\n\t\t\tcase 'asmo708':\n\t\t\tcase 'csisolatinarabic':\n\t\t\tcase 'ecma114':\n\t\t\tcase 'iso88596':\n\t\t\tcase 'iso885961987':\n\t\t\tcase 'isoir127':\n\t\t\t\treturn 'ISO-8859-6';\n\n\t\t\tcase 'csiso88596e':\n\t\t\tcase 'iso88596e':\n\t\t\t\treturn 'ISO-8859-6-E';\n\n\t\t\tcase 'csiso88596i':\n\t\t\tcase 'iso88596i':\n\t\t\t\treturn 'ISO-8859-6-I';\n\n\t\t\tcase 'csisolatingreek':\n\t\t\tcase 'ecma118':\n\t\t\tcase 'elot928':\n\t\t\tcase 'greek':\n\t\t\tcase 'greek8':\n\t\t\tcase 'iso88597':\n\t\t\tcase 'iso885971987':\n\t\t\tcase 'isoir126':\n\t\t\t\treturn 'ISO-8859-7';\n\n\t\t\tcase 'csisolatinhebrew':\n\t\t\tcase 'hebrew':\n\t\t\tcase 'iso88598':\n\t\t\tcase 'iso885981988':\n\t\t\tcase 'isoir138':\n\t\t\t\treturn 'ISO-8859-8';\n\n\t\t\tcase 'csiso88598e':\n\t\t\tcase 'iso88598e':\n\t\t\t\treturn 'ISO-8859-8-E';\n\n\t\t\tcase 'csiso88598i':\n\t\t\tcase 'iso88598i':\n\t\t\t\treturn 'ISO-8859-8-I';\n\n\t\t\tcase 'cswindows31latin5':\n\t\t\tcase 'iso88599windowslatin5':\n\t\t\t\treturn 'ISO-8859-9-Windows-Latin-5';\n\n\t\t\tcase 'csisolatin6':\n\t\t\tcase 'iso885910':\n\t\t\tcase 'iso8859101992':\n\t\t\tcase 'isoir157':\n\t\t\tcase 'l6':\n\t\t\tcase 'latin6':\n\t\t\t\treturn 'ISO-8859-10';\n\n\t\t\tcase 'iso885913':\n\t\t\t\treturn 'ISO-8859-13';\n\n\t\t\tcase 'iso885914':\n\t\t\tcase 'iso8859141998':\n\t\t\tcase 'isoceltic':\n\t\t\tcase 'isoir199':\n\t\t\tcase 'l8':\n\t\t\tcase 'latin8':\n\t\t\t\treturn 'ISO-8859-14';\n\n\t\t\tcase 'iso885915':\n\t\t\tcase 'latin9':\n\t\t\t\treturn 'ISO-8859-15';\n\n\t\t\tcase 'iso885916':\n\t\t\tcase 'iso8859162001':\n\t\t\tcase 'isoir226':\n\t\t\tcase 'l10':\n\t\t\tcase 'latin10':\n\t\t\t\treturn 'ISO-8859-16';\n\n\t\t\tcase 'iso10646j1':\n\t\t\t\treturn 'ISO-10646-J-1';\n\n\t\t\tcase 'csunicode':\n\t\t\tcase 'iso10646ucs2':\n\t\t\t\treturn 'ISO-10646-UCS-2';\n\n\t\t\tcase 'csucs4':\n\t\t\tcase 'iso10646ucs4':\n\t\t\t\treturn 'ISO-10646-UCS-4';\n\n\t\t\tcase 'csunicodeascii':\n\t\t\tcase 'iso10646ucsbasic':\n\t\t\t\treturn 'ISO-10646-UCS-Basic';\n\n\t\t\tcase 'csunicodelatin1':\n\t\t\tcase 'iso10646':\n\t\t\tcase 'iso10646unicodelatin1':\n\t\t\t\treturn 'ISO-10646-Unicode-Latin1';\n\n\t\t\tcase 'csiso10646utf1':\n\t\t\tcase 'iso10646utf1':\n\t\t\t\treturn 'ISO-10646-UTF-1';\n\n\t\t\tcase 'csiso115481':\n\t\t\tcase 'iso115481':\n\t\t\tcase 'isotr115481':\n\t\t\t\treturn 'ISO-11548-1';\n\n\t\t\tcase 'csiso90':\n\t\t\tcase 'isoir90':\n\t\t\t\treturn 'iso-ir-90';\n\n\t\t\tcase 'csunicodeibm1261':\n\t\t\tcase 'isounicodeibm1261':\n\t\t\t\treturn 'ISO-Unicode-IBM-1261';\n\n\t\t\tcase 'csunicodeibm1264':\n\t\t\tcase 'isounicodeibm1264':\n\t\t\t\treturn 'ISO-Unicode-IBM-1264';\n\n\t\t\tcase 'csunicodeibm1265':\n\t\t\tcase 'isounicodeibm1265':\n\t\t\t\treturn 'ISO-Unicode-IBM-1265';\n\n\t\t\tcase 'csunicodeibm1268':\n\t\t\tcase 'isounicodeibm1268':\n\t\t\t\treturn 'ISO-Unicode-IBM-1268';\n\n\t\t\tcase 'csunicodeibm1276':\n\t\t\tcase 'isounicodeibm1276':\n\t\t\t\treturn 'ISO-Unicode-IBM-1276';\n\n\t\t\tcase 'csiso646basic1983':\n\t\t\tcase 'iso646basic1983':\n\t\t\tcase 'ref':\n\t\t\t\treturn 'ISO_646.basic:1983';\n\n\t\t\tcase 'csiso2intlrefversion':\n\t\t\tcase 'irv':\n\t\t\tcase 'iso646irv1983':\n\t\t\tcase 'isoir2':\n\t\t\t\treturn 'ISO_646.irv:1983';\n\n\t\t\tcase 'csiso2033':\n\t\t\tcase 'e13b':\n\t\t\tcase 'iso20331983':\n\t\t\tcase 'isoir98':\n\t\t\t\treturn 'ISO_2033-1983';\n\n\t\t\tcase 'csiso5427cyrillic':\n\t\t\tcase 'iso5427':\n\t\t\tcase 'isoir37':\n\t\t\t\treturn 'ISO_5427';\n\n\t\t\tcase 'iso5427cyrillic1981':\n\t\t\tcase 'iso54271981':\n\t\t\tcase 'isoir54':\n\t\t\t\treturn 'ISO_5427:1981';\n\n\t\t\tcase 'csiso5428greek':\n\t\t\tcase 'iso54281980':\n\t\t\tcase 'isoir55':\n\t\t\t\treturn 'ISO_5428:1980';\n\n\t\t\tcase 'csiso6937add':\n\t\t\tcase 'iso6937225':\n\t\t\tcase 'isoir152':\n\t\t\t\treturn 'ISO_6937-2-25';\n\n\t\t\tcase 'csisotextcomm':\n\t\t\tcase 'iso69372add':\n\t\t\tcase 'isoir142':\n\t\t\t\treturn 'ISO_6937-2-add';\n\n\t\t\tcase 'csiso8859supp':\n\t\t\tcase 'iso8859supp':\n\t\t\tcase 'isoir154':\n\t\t\tcase 'latin125':\n\t\t\t\treturn 'ISO_8859-supp';\n\n\t\t\tcase 'csiso10367box':\n\t\t\tcase 'iso10367box':\n\t\t\tcase 'isoir155':\n\t\t\t\treturn 'ISO_10367-box';\n\n\t\t\tcase 'csiso15italian':\n\t\t\tcase 'iso646it':\n\t\t\tcase 'isoir15':\n\t\t\tcase 'it':\n\t\t\t\treturn 'IT';\n\n\t\t\tcase 'csiso13jisc6220jp':\n\t\t\tcase 'isoir13':\n\t\t\tcase 'jisc62201969':\n\t\t\tcase 'jisc62201969jp':\n\t\t\tcase 'katakana':\n\t\t\tcase 'x2017':\n\t\t\t\treturn 'JIS_C6220-1969-jp';\n\n\t\t\tcase 'csiso14jisc6220ro':\n\t\t\tcase 'iso646jp':\n\t\t\tcase 'isoir14':\n\t\t\tcase 'jisc62201969ro':\n\t\t\tcase 'jp':\n\t\t\t\treturn 'JIS_C6220-1969-ro';\n\n\t\t\tcase 'csiso42jisc62261978':\n\t\t\tcase 'isoir42':\n\t\t\tcase 'jisc62261978':\n\t\t\t\treturn 'JIS_C6226-1978';\n\n\t\t\tcase 'csiso87jisx208':\n\t\t\tcase 'isoir87':\n\t\t\tcase 'jisc62261983':\n\t\t\tcase 'jisx2081983':\n\t\t\tcase 'x208':\n\t\t\t\treturn 'JIS_C6226-1983';\n\n\t\t\tcase 'csiso91jisc62291984a':\n\t\t\tcase 'isoir91':\n\t\t\tcase 'jisc62291984a':\n\t\t\tcase 'jpocra':\n\t\t\t\treturn 'JIS_C6229-1984-a';\n\n\t\t\tcase 'csiso92jisc62991984b':\n\t\t\tcase 'iso646jpocrb':\n\t\t\tcase 'isoir92':\n\t\t\tcase 'jisc62291984b':\n\t\t\tcase 'jpocrb':\n\t\t\t\treturn 'JIS_C6229-1984-b';\n\n\t\t\tcase 'csiso93jis62291984badd':\n\t\t\tcase 'isoir93':\n\t\t\tcase 'jisc62291984badd':\n\t\t\tcase 'jpocrbadd':\n\t\t\t\treturn 'JIS_C6229-1984-b-add';\n\n\t\t\tcase 'csiso94jis62291984hand':\n\t\t\tcase 'isoir94':\n\t\t\tcase 'jisc62291984hand':\n\t\t\tcase 'jpocrhand':\n\t\t\t\treturn 'JIS_C6229-1984-hand';\n\n\t\t\tcase 'csiso95jis62291984handadd':\n\t\t\tcase 'isoir95':\n\t\t\tcase 'jisc62291984handadd':\n\t\t\tcase 'jpocrhandadd':\n\t\t\t\treturn 'JIS_C6229-1984-hand-add';\n\n\t\t\tcase 'csiso96jisc62291984kana':\n\t\t\tcase 'isoir96':\n\t\t\tcase 'jisc62291984kana':\n\t\t\t\treturn 'JIS_C6229-1984-kana';\n\n\t\t\tcase 'csjisencoding':\n\t\t\tcase 'jisencoding':\n\t\t\t\treturn 'JIS_Encoding';\n\n\t\t\tcase 'cshalfwidthkatakana':\n\t\t\tcase 'jisx201':\n\t\t\tcase 'x201':\n\t\t\t\treturn 'JIS_X0201';\n\n\t\t\tcase 'csiso159jisx2121990':\n\t\t\tcase 'isoir159':\n\t\t\tcase 'jisx2121990':\n\t\t\tcase 'x212':\n\t\t\t\treturn 'JIS_X0212-1990';\n\n\t\t\tcase 'csiso141jusib1002':\n\t\t\tcase 'iso646yu':\n\t\t\tcase 'isoir141':\n\t\t\tcase 'js':\n\t\t\tcase 'jusib1002':\n\t\t\tcase 'yu':\n\t\t\t\treturn 'JUS_I.B1.002';\n\n\t\t\tcase 'csiso147macedonian':\n\t\t\tcase 'isoir147':\n\t\t\tcase 'jusib1003mac':\n\t\t\tcase 'macedonian':\n\t\t\t\treturn 'JUS_I.B1.003-mac';\n\n\t\t\tcase 'csiso146serbian':\n\t\t\tcase 'isoir146':\n\t\t\tcase 'jusib1003serb':\n\t\t\tcase 'serbian':\n\t\t\t\treturn 'JUS_I.B1.003-serb';\n\n\t\t\tcase 'koi7switched':\n\t\t\t\treturn 'KOI7-switched';\n\n\t\t\tcase 'cskoi8r':\n\t\t\tcase 'koi8r':\n\t\t\t\treturn 'KOI8-R';\n\n\t\t\tcase 'koi8u':\n\t\t\t\treturn 'KOI8-U';\n\n\t\t\tcase 'csksc5636':\n\t\t\tcase 'iso646kr':\n\t\t\tcase 'ksc5636':\n\t\t\t\treturn 'KSC5636';\n\n\t\t\tcase 'cskz1048':\n\t\t\tcase 'kz1048':\n\t\t\tcase 'rk1048':\n\t\t\tcase 'strk10482002':\n\t\t\t\treturn 'KZ-1048';\n\n\t\t\tcase 'csiso19latingreek':\n\t\t\tcase 'isoir19':\n\t\t\tcase 'latingreek':\n\t\t\t\treturn 'latin-greek';\n\n\t\t\tcase 'csiso27latingreek1':\n\t\t\tcase 'isoir27':\n\t\t\tcase 'latingreek1':\n\t\t\t\treturn 'Latin-greek-1';\n\n\t\t\tcase 'csiso158lap':\n\t\t\tcase 'isoir158':\n\t\t\tcase 'lap':\n\t\t\tcase 'latinlap':\n\t\t\t\treturn 'latin-lap';\n\n\t\t\tcase 'csmacintosh':\n\t\t\tcase 'mac':\n\t\t\tcase 'macintosh':\n\t\t\t\treturn 'macintosh';\n\n\t\t\tcase 'csmicrosoftpublishing':\n\t\t\tcase 'microsoftpublishing':\n\t\t\t\treturn 'Microsoft-Publishing';\n\n\t\t\tcase 'csmnem':\n\t\t\tcase 'mnem':\n\t\t\t\treturn 'MNEM';\n\n\t\t\tcase 'csmnemonic':\n\t\t\tcase 'mnemonic':\n\t\t\t\treturn 'MNEMONIC';\n\n\t\t\tcase 'csiso86hungarian':\n\t\t\tcase 'hu':\n\t\t\tcase 'iso646hu':\n\t\t\tcase 'isoir86':\n\t\t\tcase 'msz77953':\n\t\t\t\treturn 'MSZ_7795.3';\n\n\t\t\tcase 'csnatsdano':\n\t\t\tcase 'isoir91':\n\t\t\tcase 'natsdano':\n\t\t\t\treturn 'NATS-DANO';\n\n\t\t\tcase 'csnatsdanoadd':\n\t\t\tcase 'isoir92':\n\t\t\tcase 'natsdanoadd':\n\t\t\t\treturn 'NATS-DANO-ADD';\n\n\t\t\tcase 'csnatssefi':\n\t\t\tcase 'isoir81':\n\t\t\tcase 'natssefi':\n\t\t\t\treturn 'NATS-SEFI';\n\n\t\t\tcase 'csnatssefiadd':\n\t\t\tcase 'isoir82':\n\t\t\tcase 'natssefiadd':\n\t\t\t\treturn 'NATS-SEFI-ADD';\n\n\t\t\tcase 'csiso151cuba':\n\t\t\tcase 'cuba':\n\t\t\tcase 'iso646cu':\n\t\t\tcase 'isoir151':\n\t\t\tcase 'ncnc1081':\n\t\t\t\treturn 'NC_NC00-10:81';\n\n\t\t\tcase 'csiso69french':\n\t\t\tcase 'fr':\n\t\t\tcase 'iso646fr':\n\t\t\tcase 'isoir69':\n\t\t\tcase 'nfz62010':\n\t\t\t\treturn 'NF_Z_62-010';\n\n\t\t\tcase 'csiso25french':\n\t\t\tcase 'iso646fr1':\n\t\t\tcase 'isoir25':\n\t\t\tcase 'nfz620101973':\n\t\t\t\treturn 'NF_Z_62-010_(1973)';\n\n\t\t\tcase 'csiso60danishnorwegian':\n\t\t\tcase 'csiso60norwegian1':\n\t\t\tcase 'iso646no':\n\t\t\tcase 'isoir60':\n\t\t\tcase 'no':\n\t\t\tcase 'ns45511':\n\t\t\t\treturn 'NS_4551-1';\n\n\t\t\tcase 'csiso61norwegian2':\n\t\t\tcase 'iso646no2':\n\t\t\tcase 'isoir61':\n\t\t\tcase 'no2':\n\t\t\tcase 'ns45512':\n\t\t\t\treturn 'NS_4551-2';\n\n\t\t\tcase 'osdebcdicdf3irv':\n\t\t\t\treturn 'OSD_EBCDIC_DF03_IRV';\n\n\t\t\tcase 'osdebcdicdf41':\n\t\t\t\treturn 'OSD_EBCDIC_DF04_1';\n\n\t\t\tcase 'osdebcdicdf415':\n\t\t\t\treturn 'OSD_EBCDIC_DF04_15';\n\n\t\t\tcase 'cspc8danishnorwegian':\n\t\t\tcase 'pc8danishnorwegian':\n\t\t\t\treturn 'PC8-Danish-Norwegian';\n\n\t\t\tcase 'cspc8turkish':\n\t\t\tcase 'pc8turkish':\n\t\t\t\treturn 'PC8-Turkish';\n\n\t\t\tcase 'csiso16portuguese':\n\t\t\tcase 'iso646pt':\n\t\t\tcase 'isoir16':\n\t\t\tcase 'pt':\n\t\t\t\treturn 'PT';\n\n\t\t\tcase 'csiso84portuguese2':\n\t\t\tcase 'iso646pt2':\n\t\t\tcase 'isoir84':\n\t\t\tcase 'pt2':\n\t\t\t\treturn 'PT2';\n\n\t\t\tcase 'cp154':\n\t\t\tcase 'csptcp154':\n\t\t\tcase 'cyrillicasian':\n\t\t\tcase 'pt154':\n\t\t\tcase 'ptcp154':\n\t\t\t\treturn 'PTCP154';\n\n\t\t\tcase 'scsu':\n\t\t\t\treturn 'SCSU';\n\n\t\t\tcase 'csiso10swedish':\n\t\t\tcase 'fi':\n\t\t\tcase 'iso646fi':\n\t\t\tcase 'iso646se':\n\t\t\tcase 'isoir10':\n\t\t\tcase 'se':\n\t\t\tcase 'sen850200b':\n\t\t\t\treturn 'SEN_850200_B';\n\n\t\t\tcase 'csiso11swedishfornames':\n\t\t\tcase 'iso646se2':\n\t\t\tcase 'isoir11':\n\t\t\tcase 'se2':\n\t\t\tcase 'sen850200c':\n\t\t\t\treturn 'SEN_850200_C';\n\n\t\t\tcase 'csiso102t617bit':\n\t\t\tcase 'isoir102':\n\t\t\tcase 't617bit':\n\t\t\t\treturn 'T.61-7bit';\n\n\t\t\tcase 'csiso103t618bit':\n\t\t\tcase 'isoir103':\n\t\t\tcase 't61':\n\t\t\tcase 't618bit':\n\t\t\t\treturn 'T.61-8bit';\n\n\t\t\tcase 'csiso128t101g2':\n\t\t\tcase 'isoir128':\n\t\t\tcase 't101g2':\n\t\t\t\treturn 'T.101-G2';\n\n\t\t\tcase 'cstscii':\n\t\t\tcase 'tscii':\n\t\t\t\treturn 'TSCII';\n\n\t\t\tcase 'csunicode11':\n\t\t\tcase 'unicode11':\n\t\t\t\treturn 'UNICODE-1-1';\n\n\t\t\tcase 'csunicode11utf7':\n\t\t\tcase 'unicode11utf7':\n\t\t\t\treturn 'UNICODE-1-1-UTF-7';\n\n\t\t\tcase 'csunknown8bit':\n\t\t\tcase 'unknown8bit':\n\t\t\t\treturn 'UNKNOWN-8BIT';\n\n\t\t\tcase 'ansix341968':\n\t\t\tcase 'ansix341986':\n\t\t\tcase 'ascii':\n\t\t\tcase 'cp367':\n\t\t\tcase 'csascii':\n\t\t\tcase 'ibm367':\n\t\t\tcase 'iso646irv1991':\n\t\t\tcase 'iso646us':\n\t\t\tcase 'isoir6':\n\t\t\tcase 'us':\n\t\t\tcase 'usascii':\n\t\t\t\treturn 'US-ASCII';\n\n\t\t\tcase 'csusdk':\n\t\t\tcase 'usdk':\n\t\t\t\treturn 'us-dk';\n\n\t\t\tcase 'utf7':\n\t\t\t\treturn 'UTF-7';\n\n\t\t\tcase 'utf8':\n\t\t\t\treturn 'UTF-8';\n\n\t\t\tcase 'utf16':\n\t\t\t\treturn 'UTF-16';\n\n\t\t\tcase 'utf16be':\n\t\t\t\treturn 'UTF-16BE';\n\n\t\t\tcase 'utf16le':\n\t\t\t\treturn 'UTF-16LE';\n\n\t\t\tcase 'utf32':\n\t\t\t\treturn 'UTF-32';\n\n\t\t\tcase 'utf32be':\n\t\t\t\treturn 'UTF-32BE';\n\n\t\t\tcase 'utf32le':\n\t\t\t\treturn 'UTF-32LE';\n\n\t\t\tcase 'csventurainternational':\n\t\t\tcase 'venturainternational':\n\t\t\t\treturn 'Ventura-International';\n\n\t\t\tcase 'csventuramath':\n\t\t\tcase 'venturamath':\n\t\t\t\treturn 'Ventura-Math';\n\n\t\t\tcase 'csventuraus':\n\t\t\tcase 'venturaus':\n\t\t\t\treturn 'Ventura-US';\n\n\t\t\tcase 'csiso70videotexsupp1':\n\t\t\tcase 'isoir70':\n\t\t\tcase 'videotexsuppl':\n\t\t\t\treturn 'videotex-suppl';\n\n\t\t\tcase 'csviqr':\n\t\t\tcase 'viqr':\n\t\t\t\treturn 'VIQR';\n\n\t\t\tcase 'csviscii':\n\t\t\tcase 'viscii':\n\t\t\t\treturn 'VISCII';\n\n\t\t\tcase 'csshiftjis':\n\t\t\tcase 'cswindows31j':\n\t\t\tcase 'mskanji':\n\t\t\tcase 'shiftjis':\n\t\t\tcase 'windows31j':\n\t\t\t\treturn 'Windows-31J';\n\n\t\t\tcase 'iso885911':\n\t\t\tcase 'tis620':\n\t\t\t\treturn 'windows-874';\n\n\t\t\tcase 'cseuckr':\n\t\t\tcase 'csksc56011987':\n\t\t\tcase 'euckr':\n\t\t\tcase 'isoir149':\n\t\t\tcase 'korean':\n\t\t\tcase 'ksc5601':\n\t\t\tcase 'ksc56011987':\n\t\t\tcase 'ksc56011989':\n\t\t\tcase 'windows949':\n\t\t\t\treturn 'windows-949';\n\n\t\t\tcase 'windows1250':\n\t\t\t\treturn 'windows-1250';\n\n\t\t\tcase 'windows1251':\n\t\t\t\treturn 'windows-1251';\n\n\t\t\tcase 'cp819':\n\t\t\tcase 'csisolatin1':\n\t\t\tcase 'ibm819':\n\t\t\tcase 'iso88591':\n\t\t\tcase 'iso885911987':\n\t\t\tcase 'isoir100':\n\t\t\tcase 'l1':\n\t\t\tcase 'latin1':\n\t\t\tcase 'windows1252':\n\t\t\t\treturn 'windows-1252';\n\n\t\t\tcase 'windows1253':\n\t\t\t\treturn 'windows-1253';\n\n\t\t\tcase 'csisolatin5':\n\t\t\tcase 'iso88599':\n\t\t\tcase 'iso885991989':\n\t\t\tcase 'isoir148':\n\t\t\tcase 'l5':\n\t\t\tcase 'latin5':\n\t\t\tcase 'windows1254':\n\t\t\t\treturn 'windows-1254';\n\n\t\t\tcase 'windows1255':\n\t\t\t\treturn 'windows-1255';\n\n\t\t\tcase 'windows1256':\n\t\t\t\treturn 'windows-1256';\n\n\t\t\tcase 'windows1257':\n\t\t\t\treturn 'windows-1257';\n\n\t\t\tcase 'windows1258':\n\t\t\t\treturn 'windows-1258';\n\n\t\t\tdefault:\n\t\t\t\treturn $charset;\n\t\t}\n\t}\n\n\tpublic static function get_curl_version()\n\t{\n\t\tif (is_array($curl = curl_version()))\n\t\t{\n\t\t\t$curl = $curl['version'];\n\t\t}\n\t\telseif (substr($curl, 0, 5) === 'curl/')\n\t\t{\n\t\t\t$curl = substr($curl, 5, strcspn($curl, \"\\x09\\x0A\\x0B\\x0C\\x0D\", 5));\n\t\t}\n\t\telseif (substr($curl, 0, 8) === 'libcurl/')\n\t\t{\n\t\t\t$curl = substr($curl, 8, strcspn($curl, \"\\x09\\x0A\\x0B\\x0C\\x0D\", 8));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$curl = 0;\n\t\t}\n\t\treturn $curl;\n\t}\n\n\t/**\n\t * Strip HTML comments\n\t *\n\t * @param string $data Data to strip comments from\n\t * @return string Comment stripped string\n\t */\n\tpublic static function strip_comments($data)\n\t{\n\t\t$output = '';\n\t\twhile (($start = strpos($data, '<!--')) !== false)\n\t\t{\n\t\t\t$output .= substr($data, 0, $start);\n\t\t\tif (($end = strpos($data, '-->', $start)) !== false)\n\t\t\t{\n\t\t\t\t$data = substr_replace($data, '', 0, $end + 3);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$data = '';\n\t\t\t}\n\t\t}\n\t\treturn $output . $data;\n\t}\n\n\tpublic static function parse_date($dt)\n\t{\n\t\t$parser = SimplePie_Parse_Date::get();\n\t\treturn $parser->parse($dt);\n\t}\n\n\t/**\n\t * Decode HTML entities\n\t *\n\t * @deprecated Use DOMDocument instead\n\t * @param string $data Input data\n\t * @return string Output data\n\t */\n\tpublic static function entities_decode($data)\n\t{\n\t\t$decoder = new SimplePie_Decode_HTML_Entities($data);\n\t\treturn $decoder->parse();\n\t}\n\n\t/**\n\t * Remove RFC822 comments\n\t *\n\t * @param string $data Data to strip comments from\n\t * @return string Comment stripped string\n\t */\n\tpublic static function uncomment_rfc822($string)\n\t{\n\t\t$string = (string) $string;\n\t\t$position = 0;\n\t\t$length = strlen($string);\n\t\t$depth = 0;\n\n\t\t$output = '';\n\n\t\twhile ($position < $length && ($pos = strpos($string, '(', $position)) !== false)\n\t\t{\n\t\t\t$output .= substr($string, $position, $pos - $position);\n\t\t\t$position = $pos + 1;\n\t\t\tif ($string[$pos - 1] !== '\\\\')\n\t\t\t{\n\t\t\t\t$depth++;\n\t\t\t\twhile ($depth && $position < $length)\n\t\t\t\t{\n\t\t\t\t\t$position += strcspn($string, '()', $position);\n\t\t\t\t\tif ($string[$position - 1] === '\\\\')\n\t\t\t\t\t{\n\t\t\t\t\t\t$position++;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telseif (isset($string[$position]))\n\t\t\t\t\t{\n\t\t\t\t\t\tswitch ($string[$position])\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase '(':\n\t\t\t\t\t\t\t\t$depth++;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase ')':\n\t\t\t\t\t\t\t\t$depth--;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$position++;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$output .= '(';\n\t\t\t}\n\t\t}\n\t\t$output .= substr($string, $position);\n\n\t\treturn $output;\n\t}\n\n\tpublic static function parse_mime($mime)\n\t{\n\t\tif (($pos = strpos($mime, ';')) === false)\n\t\t{\n\t\t\treturn trim($mime);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn trim(substr($mime, 0, $pos));\n\t\t}\n\t}\n\n\tpublic static function atom_03_construct_type($attribs)\n\t{\n\t\tif (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))\n\t\t{\n\t\t\t$mode = SIMPLEPIE_CONSTRUCT_BASE64;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$mode = SIMPLEPIE_CONSTRUCT_NONE;\n\t\t}\n\t\tif (isset($attribs['']['type']))\n\t\t{\n\t\t\tswitch (strtolower(trim($attribs['']['type'])))\n\t\t\t{\n\t\t\t\tcase 'text':\n\t\t\t\tcase 'text/plain':\n\t\t\t\t\treturn SIMPLEPIE_CONSTRUCT_TEXT | $mode;\n\n\t\t\t\tcase 'html':\n\t\t\t\tcase 'text/html':\n\t\t\t\t\treturn SIMPLEPIE_CONSTRUCT_HTML | $mode;\n\n\t\t\t\tcase 'xhtml':\n\t\t\t\tcase 'application/xhtml+xml':\n\t\t\t\t\treturn SIMPLEPIE_CONSTRUCT_XHTML | $mode;\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn SIMPLEPIE_CONSTRUCT_NONE | $mode;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn SIMPLEPIE_CONSTRUCT_TEXT | $mode;\n\t\t}\n\t}\n\n\tpublic static function atom_10_construct_type($attribs)\n\t{\n\t\tif (isset($attribs['']['type']))\n\t\t{\n\t\t\tswitch (strtolower(trim($attribs['']['type'])))\n\t\t\t{\n\t\t\t\tcase 'text':\n\t\t\t\t\treturn SIMPLEPIE_CONSTRUCT_TEXT;\n\n\t\t\t\tcase 'html':\n\t\t\t\t\treturn SIMPLEPIE_CONSTRUCT_HTML;\n\n\t\t\t\tcase 'xhtml':\n\t\t\t\t\treturn SIMPLEPIE_CONSTRUCT_XHTML;\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn SIMPLEPIE_CONSTRUCT_NONE;\n\t\t\t}\n\t\t}\n\t\treturn SIMPLEPIE_CONSTRUCT_TEXT;\n\t}\n\n\tpublic static function atom_10_content_construct_type($attribs)\n\t{\n\t\tif (isset($attribs['']['type']))\n\t\t{\n\t\t\t$type = strtolower(trim($attribs['']['type']));\n\t\t\tswitch ($type)\n\t\t\t{\n\t\t\t\tcase 'text':\n\t\t\t\t\treturn SIMPLEPIE_CONSTRUCT_TEXT;\n\n\t\t\t\tcase 'html':\n\t\t\t\t\treturn SIMPLEPIE_CONSTRUCT_HTML;\n\n\t\t\t\tcase 'xhtml':\n\t\t\t\t\treturn SIMPLEPIE_CONSTRUCT_XHTML;\n\t\t\t}\n\t\t\tif (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')\n\t\t\t{\n\t\t\t\treturn SIMPLEPIE_CONSTRUCT_NONE;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn SIMPLEPIE_CONSTRUCT_BASE64;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn SIMPLEPIE_CONSTRUCT_TEXT;\n\t\t}\n\t}\n\n\tpublic static function is_isegment_nz_nc($string)\n\t{\n\t\treturn (bool) preg_match('/^([A-Za-z0-9\\-._~\\x{A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}\\x{10000}-\\x{1FFFD}\\x{20000}-\\x{2FFFD}\\x{30000}-\\x{3FFFD}\\x{40000}-\\x{4FFFD}\\x{50000}-\\x{5FFFD}\\x{60000}-\\x{6FFFD}\\x{70000}-\\x{7FFFD}\\x{80000}-\\x{8FFFD}\\x{90000}-\\x{9FFFD}\\x{A0000}-\\x{AFFFD}\\x{B0000}-\\x{BFFFD}\\x{C0000}-\\x{CFFFD}\\x{D0000}-\\x{DFFFD}\\x{E1000}-\\x{EFFFD}!$&\\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string);\n\t}\n\n\tpublic static function space_seperated_tokens($string)\n\t{\n\t\t$space_characters = \"\\x20\\x09\\x0A\\x0B\\x0C\\x0D\";\n\t\t$string_length = strlen($string);\n\n\t\t$position = strspn($string, $space_characters);\n\t\t$tokens = array();\n\n\t\twhile ($position < $string_length)\n\t\t{\n\t\t\t$len = strcspn($string, $space_characters, $position);\n\t\t\t$tokens[] = substr($string, $position, $len);\n\t\t\t$position += $len;\n\t\t\t$position += strspn($string, $space_characters, $position);\n\t\t}\n\n\t\treturn $tokens;\n\t}\n\n\t/**\n\t * Converts a unicode codepoint to a UTF-8 character\n\t *\n\t * @static\n\t * @param int $codepoint Unicode codepoint\n\t * @return string UTF-8 character\n\t */\n\tpublic static function codepoint_to_utf8($codepoint)\n\t{\n\t\t$codepoint = (int) $codepoint;\n\t\tif ($codepoint < 0)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\telse if ($codepoint <= 0x7f)\n\t\t{\n\t\t\treturn chr($codepoint);\n\t\t}\n\t\telse if ($codepoint <= 0x7ff)\n\t\t{\n\t\t\treturn chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));\n\t\t}\n\t\telse if ($codepoint <= 0xffff)\n\t\t{\n\t\t\treturn chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));\n\t\t}\n\t\telse if ($codepoint <= 0x10ffff)\n\t\t{\n\t\t\treturn chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// U+FFFD REPLACEMENT CHARACTER\n\t\t\treturn \"\\xEF\\xBF\\xBD\";\n\t\t}\n\t}\n\n\t/**\n\t * Similar to parse_str()\n\t *\n\t * Returns an associative array of name/value pairs, where the value is an\n\t * array of values that have used the same name\n\t *\n\t * @static\n\t * @param string $str The input string.\n\t * @return array\n\t */\n\tpublic static function parse_str($str)\n\t{\n\t\t$return = array();\n\t\t$str = explode('&', $str);\n\n\t\tforeach ($str as $section)\n\t\t{\n\t\t\tif (strpos($section, '=') !== false)\n\t\t\t{\n\t\t\t\tlist($name, $value) = explode('=', $section, 2);\n\t\t\t\t$return[urldecode($name)][] = urldecode($value);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$return[urldecode($section)][] = null;\n\t\t\t}\n\t\t}\n\n\t\treturn $return;\n\t}\n\n\t/**\n\t * Detect XML encoding, as per XML 1.0 Appendix F.1\n\t *\n\t * @todo Add support for EBCDIC\n\t * @param string $data XML data\n\t * @param SimplePie_Registry $registry Class registry\n\t * @return array Possible encodings\n\t */\n\tpublic static function xml_encoding($data, $registry)\n\t{\n\t\t// UTF-32 Big Endian BOM\n\t\tif (substr($data, 0, 4) === \"\\x00\\x00\\xFE\\xFF\")\n\t\t{\n\t\t\t$encoding[] = 'UTF-32BE';\n\t\t}\n\t\t// UTF-32 Little Endian BOM\n\t\telseif (substr($data, 0, 4) === \"\\xFF\\xFE\\x00\\x00\")\n\t\t{\n\t\t\t$encoding[] = 'UTF-32LE';\n\t\t}\n\t\t// UTF-16 Big Endian BOM\n\t\telseif (substr($data, 0, 2) === \"\\xFE\\xFF\")\n\t\t{\n\t\t\t$encoding[] = 'UTF-16BE';\n\t\t}\n\t\t// UTF-16 Little Endian BOM\n\t\telseif (substr($data, 0, 2) === \"\\xFF\\xFE\")\n\t\t{\n\t\t\t$encoding[] = 'UTF-16LE';\n\t\t}\n\t\t// UTF-8 BOM\n\t\telseif (substr($data, 0, 3) === \"\\xEF\\xBB\\xBF\")\n\t\t{\n\t\t\t$encoding[] = 'UTF-8';\n\t\t}\n\t\t// UTF-32 Big Endian Without BOM\n\t\telseif (substr($data, 0, 20) === \"\\x00\\x00\\x00\\x3C\\x00\\x00\\x00\\x3F\\x00\\x00\\x00\\x78\\x00\\x00\\x00\\x6D\\x00\\x00\\x00\\x6C\")\n\t\t{\n\t\t\tif ($pos = strpos($data, \"\\x00\\x00\\x00\\x3F\\x00\\x00\\x00\\x3E\"))\n\t\t\t{\n\t\t\t\t$parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8')));\n\t\t\t\tif ($parser->parse())\n\t\t\t\t{\n\t\t\t\t\t$encoding[] = $parser->encoding;\n\t\t\t\t}\n\t\t\t}\n\t\t\t$encoding[] = 'UTF-32BE';\n\t\t}\n\t\t// UTF-32 Little Endian Without BOM\n\t\telseif (substr($data, 0, 20) === \"\\x3C\\x00\\x00\\x00\\x3F\\x00\\x00\\x00\\x78\\x00\\x00\\x00\\x6D\\x00\\x00\\x00\\x6C\\x00\\x00\\x00\")\n\t\t{\n\t\t\tif ($pos = strpos($data, \"\\x3F\\x00\\x00\\x00\\x3E\\x00\\x00\\x00\"))\n\t\t\t{\n\t\t\t\t$parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8')));\n\t\t\t\tif ($parser->parse())\n\t\t\t\t{\n\t\t\t\t\t$encoding[] = $parser->encoding;\n\t\t\t\t}\n\t\t\t}\n\t\t\t$encoding[] = 'UTF-32LE';\n\t\t}\n\t\t// UTF-16 Big Endian Without BOM\n\t\telseif (substr($data, 0, 10) === \"\\x00\\x3C\\x00\\x3F\\x00\\x78\\x00\\x6D\\x00\\x6C\")\n\t\t{\n\t\t\tif ($pos = strpos($data, \"\\x00\\x3F\\x00\\x3E\"))\n\t\t\t{\n\t\t\t\t$parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8')));\n\t\t\t\tif ($parser->parse())\n\t\t\t\t{\n\t\t\t\t\t$encoding[] = $parser->encoding;\n\t\t\t\t}\n\t\t\t}\n\t\t\t$encoding[] = 'UTF-16BE';\n\t\t}\n\t\t// UTF-16 Little Endian Without BOM\n\t\telseif (substr($data, 0, 10) === \"\\x3C\\x00\\x3F\\x00\\x78\\x00\\x6D\\x00\\x6C\\x00\")\n\t\t{\n\t\t\tif ($pos = strpos($data, \"\\x3F\\x00\\x3E\\x00\"))\n\t\t\t{\n\t\t\t\t$parser = $registry->create('XML_Declaration_Parser', array(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8')));\n\t\t\t\tif ($parser->parse())\n\t\t\t\t{\n\t\t\t\t\t$encoding[] = $parser->encoding;\n\t\t\t\t}\n\t\t\t}\n\t\t\t$encoding[] = 'UTF-16LE';\n\t\t}\n\t\t// US-ASCII (or superset)\n\t\telseif (substr($data, 0, 5) === \"\\x3C\\x3F\\x78\\x6D\\x6C\")\n\t\t{\n\t\t\tif ($pos = strpos($data, \"\\x3F\\x3E\"))\n\t\t\t{\n\t\t\t\t$parser = $registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5)));\n\t\t\t\tif ($parser->parse())\n\t\t\t\t{\n\t\t\t\t\t$encoding[] = $parser->encoding;\n\t\t\t\t}\n\t\t\t}\n\t\t\t$encoding[] = 'UTF-8';\n\t\t}\n\t\t// Fallback to UTF-8\n\t\telse\n\t\t{\n\t\t\t$encoding[] = 'UTF-8';\n\t\t}\n\t\treturn $encoding;\n\t}\n\n\tpublic static function output_javascript()\n\t{\n\t\tif (function_exists('ob_gzhandler'))\n\t\t{\n\t\t\tob_start('ob_gzhandler');\n\t\t}\n\t\theader('Content-type: text/javascript; charset: UTF-8');\n\t\theader('Cache-Control: must-revalidate');\n\t\theader('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days\n\t\t?>\nfunction embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {\n\tif (placeholder != '') {\n\t\tdocument.writeln('<embed type=\"'+type+'\" style=\"cursor:hand; cursor:pointer;\" href=\"'+link+'\" src=\"'+placeholder+'\" width=\"'+width+'\" height=\"'+height+'\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"'+loop+'\" scale=\"aspect\" bgcolor=\"'+bgcolor+'\" pluginspage=\"http://www.apple.com/quicktime/download/\"></embed>');\n\t}\n\telse {\n\t\tdocument.writeln('<embed type=\"'+type+'\" style=\"cursor:hand; cursor:pointer;\" src=\"'+link+'\" width=\"'+width+'\" height=\"'+height+'\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"'+loop+'\" scale=\"aspect\" bgcolor=\"'+bgcolor+'\" pluginspage=\"http://www.apple.com/quicktime/download/\"></embed>');\n\t}\n}\n\nfunction embed_flash(bgcolor, width, height, link, loop, type) {\n\tdocument.writeln('<embed src=\"'+link+'\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\" type=\"'+type+'\" quality=\"high\" width=\"'+width+'\" height=\"'+height+'\" bgcolor=\"'+bgcolor+'\" loop=\"'+loop+'\"></embed>');\n}\n\nfunction embed_flv(width, height, link, placeholder, loop, player) {\n\tdocument.writeln('<embed src=\"'+player+'\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" quality=\"high\" width=\"'+width+'\" height=\"'+height+'\" wmode=\"transparent\" flashvars=\"file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false\"></embed>');\n}\n\nfunction embed_wmedia(width, height, link) {\n\tdocument.writeln('<embed type=\"application/x-mplayer2\" src=\"'+link+'\" autosize=\"1\" width=\"'+width+'\" height=\"'+height+'\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>');\n}\n\t\t<?php\n\t}\n\n\t/**\n\t * Get the SimplePie build timestamp\n\t *\n\t * Uses the git index if it exists, otherwise uses the modification time\n\t * of the newest file.\n\t */\n\tpublic static function get_build()\n\t{\n\t\t$root = dirname(dirname(__FILE__));\n\t\tif (file_exists($root . '/.git/index'))\n\t\t{\n\t\t\treturn filemtime($root . '/.git/index');\n\t\t}\n\t\telseif (file_exists($root . '/SimplePie'))\n\t\t{\n\t\t\t$time = 0;\n\t\t\tforeach (glob($root . '/SimplePie/*.php') as $file)\n\t\t\t{\n\t\t\t\tif (($mtime = filemtime($file)) > $time)\n\t\t\t\t{\n\t\t\t\t\t$time = $mtime;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn $time;\n\t\t}\n\t\telseif (file_exists(dirname(__FILE__) . '/Core.php'))\n\t\t{\n\t\t\treturn filemtime(dirname(__FILE__) . '/Core.php');\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn filemtime(__FILE__);\n\t\t}\n\t}\n\n\t/**\n\t * Format debugging information\n\t */\n\tpublic static function debug(&$sp)\n\t{\n\t\t$info = 'SimplePie ' . SIMPLEPIE_VERSION . ' Build ' . SIMPLEPIE_BUILD . \"\\n\";\n\t\t$info .= 'PHP ' . PHP_VERSION . \"\\n\";\n\t\tif ($sp->error() !== null)\n\t\t{\n\t\t\t$info .= 'Error occurred: ' . $sp->error() . \"\\n\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$info .= \"No error found.\\n\";\n\t\t}\n\t\t$info .= \"Extensions:\\n\";\n\t\t$extensions = array('pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml');\n\t\tforeach ($extensions as $ext)\n\t\t{\n\t\t\tif (extension_loaded($ext))\n\t\t\t{\n\t\t\t\t$info .= \"    $ext loaded\\n\";\n\t\t\t\tswitch ($ext)\n\t\t\t\t{\n\t\t\t\t\tcase 'pcre':\n\t\t\t\t\t\t$info .= '      Version ' . PCRE_VERSION . \"\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'curl':\n\t\t\t\t\t\t$version = curl_version();\n\t\t\t\t\t\t$info .= '      Version ' . $version['version'] . \"\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'mbstring':\n\t\t\t\t\t\t$info .= '      Overloading: ' . mb_get_info('func_overload') . \"\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'iconv':\n\t\t\t\t\t\t$info .= '      Version ' . ICONV_VERSION . \"\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'xml':\n\t\t\t\t\t\t$info .= '      Version ' . LIBXML_DOTTED_VERSION . \"\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$info .= \"    $ext not loaded\\n\";\n\t\t\t}\n\t\t}\n\t\treturn $info;\n\t}\n\n\tpublic static function silence_errors($num, $str)\n\t{\n\t\t// No-op\n\t}\n}\n\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Net/IPv6.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n\n/**\n * Class to validate and to work with IPv6 addresses.\n *\n * @package SimplePie\n * @subpackage HTTP\n * @copyright 2003-2005 The PHP Group\n * @license http://www.opensource.org/licenses/bsd-license.php\n * @link http://pear.php.net/package/Net_IPv6\n * @author Alexander Merz <alexander.merz@web.de>\n * @author elfrink at introweb dot nl\n * @author Josh Peck <jmp at joshpeck dot org>\n * @author Geoffrey Sneddon <geoffers@gmail.com>\n */\nclass SimplePie_Net_IPv6\n{\n\t/**\n\t * Uncompresses an IPv6 address\n\t *\n\t * RFC 4291 allows you to compress concecutive zero pieces in an address to\n\t * '::'. This method expects a valid IPv6 address and expands the '::' to\n\t * the required number of zero pieces.\n\t *\n\t * Example:  FF01::101   ->  FF01:0:0:0:0:0:0:101\n\t *           ::1         ->  0:0:0:0:0:0:0:1\n\t *\n\t * @author Alexander Merz <alexander.merz@web.de>\n\t * @author elfrink at introweb dot nl\n\t * @author Josh Peck <jmp at joshpeck dot org>\n\t * @copyright 2003-2005 The PHP Group\n\t * @license http://www.opensource.org/licenses/bsd-license.php\n\t * @param string $ip An IPv6 address\n\t * @return string The uncompressed IPv6 address\n\t */\n\tpublic static function uncompress($ip)\n\t{\n\t\t$c1 = -1;\n\t\t$c2 = -1;\n\t\tif (substr_count($ip, '::') === 1)\n\t\t{\n\t\t\tlist($ip1, $ip2) = explode('::', $ip);\n\t\t\tif ($ip1 === '')\n\t\t\t{\n\t\t\t\t$c1 = -1;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$c1 = substr_count($ip1, ':');\n\t\t\t}\n\t\t\tif ($ip2 === '')\n\t\t\t{\n\t\t\t\t$c2 = -1;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$c2 = substr_count($ip2, ':');\n\t\t\t}\n\t\t\tif (strpos($ip2, '.') !== false)\n\t\t\t{\n\t\t\t\t$c2++;\n\t\t\t}\n\t\t\t// ::\n\t\t\tif ($c1 === -1 && $c2 === -1)\n\t\t\t{\n\t\t\t\t$ip = '0:0:0:0:0:0:0:0';\n\t\t\t}\n\t\t\t// ::xxx\n\t\t\telse if ($c1 === -1)\n\t\t\t{\n\t\t\t\t$fill = str_repeat('0:', 7 - $c2);\n\t\t\t\t$ip = str_replace('::', $fill, $ip);\n\t\t\t}\n\t\t\t// xxx::\n\t\t\telse if ($c2 === -1)\n\t\t\t{\n\t\t\t\t$fill = str_repeat(':0', 7 - $c1);\n\t\t\t\t$ip = str_replace('::', $fill, $ip);\n\t\t\t}\n\t\t\t// xxx::xxx\n\t\t\telse\n\t\t\t{\n\t\t\t\t$fill = ':' . str_repeat('0:', 6 - $c2 - $c1);\n\t\t\t\t$ip = str_replace('::', $fill, $ip);\n\t\t\t}\n\t\t}\n\t\treturn $ip;\n\t}\n\n\t/**\n\t * Compresses an IPv6 address\n\t *\n\t * RFC 4291 allows you to compress concecutive zero pieces in an address to\n\t * '::'. This method expects a valid IPv6 address and compresses consecutive\n\t * zero pieces to '::'.\n\t *\n\t * Example:  FF01:0:0:0:0:0:0:101   ->  FF01::101\n\t *           0:0:0:0:0:0:0:1        ->  ::1\n\t *\n\t * @see uncompress()\n\t * @param string $ip An IPv6 address\n\t * @return string The compressed IPv6 address\n\t */\n\tpublic static function compress($ip)\n\t{\n\t\t// Prepare the IP to be compressed\n\t\t$ip = self::uncompress($ip);\n\t\t$ip_parts = self::split_v6_v4($ip);\n\n\t\t// Replace all leading zeros\n\t\t$ip_parts[0] = preg_replace('/(^|:)0+([0-9])/', '\\1\\2', $ip_parts[0]);\n\n\t\t// Find bunches of zeros\n\t\tif (preg_match_all('/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE))\n\t\t{\n\t\t\t$max = 0;\n\t\t\t$pos = null;\n\t\t\tforeach ($matches[0] as $match)\n\t\t\t{\n\t\t\t\tif (strlen($match[0]) > $max)\n\t\t\t\t{\n\t\t\t\t\t$max = strlen($match[0]);\n\t\t\t\t\t$pos = $match[1];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$ip_parts[0] = substr_replace($ip_parts[0], '::', $pos, $max);\n\t\t}\n\n\t\tif ($ip_parts[1] !== '')\n\t\t{\n\t\t\treturn implode(':', $ip_parts);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn $ip_parts[0];\n\t\t}\n\t}\n\n\t/**\n\t * Splits an IPv6 address into the IPv6 and IPv4 representation parts\n\t *\n\t * RFC 4291 allows you to represent the last two parts of an IPv6 address\n\t * using the standard IPv4 representation\n\t *\n\t * Example:  0:0:0:0:0:0:13.1.68.3\n\t *           0:0:0:0:0:FFFF:129.144.52.38\n\t *\n\t * @param string $ip An IPv6 address\n\t * @return array [0] contains the IPv6 represented part, and [1] the IPv4 represented part\n\t */\n\tprivate static function split_v6_v4($ip)\n\t{\n\t\tif (strpos($ip, '.') !== false)\n\t\t{\n\t\t\t$pos = strrpos($ip, ':');\n\t\t\t$ipv6_part = substr($ip, 0, $pos);\n\t\t\t$ipv4_part = substr($ip, $pos + 1);\n\t\t\treturn array($ipv6_part, $ipv4_part);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn array($ip, '');\n\t\t}\n\t}\n\n\t/**\n\t * Checks an IPv6 address\n\t *\n\t * Checks if the given IP is a valid IPv6 address\n\t *\n\t * @param string $ip An IPv6 address\n\t * @return bool true if $ip is a valid IPv6 address\n\t */\n\tpublic static function check_ipv6($ip)\n\t{\n\t\t$ip = self::uncompress($ip);\n\t\tlist($ipv6, $ipv4) = self::split_v6_v4($ip);\n\t\t$ipv6 = explode(':', $ipv6);\n\t\t$ipv4 = explode('.', $ipv4);\n\t\tif (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4)\n\t\t{\n\t\t\tforeach ($ipv6 as $ipv6_part)\n\t\t\t{\n\t\t\t\t// The section can't be empty\n\t\t\t\tif ($ipv6_part === '')\n\t\t\t\t\treturn false;\n\n\t\t\t\t// Nor can it be over four characters\n\t\t\t\tif (strlen($ipv6_part) > 4)\n\t\t\t\t\treturn false;\n\n\t\t\t\t// Remove leading zeros (this is safe because of the above)\n\t\t\t\t$ipv6_part = ltrim($ipv6_part, '0');\n\t\t\t\tif ($ipv6_part === '')\n\t\t\t\t\t$ipv6_part = '0';\n\n\t\t\t\t// Check the value is valid\n\t\t\t\t$value = hexdec($ipv6_part);\n\t\t\t\tif (dechex($value) !== strtolower($ipv6_part) || $value < 0 || $value > 0xFFFF)\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (count($ipv4) === 4)\n\t\t\t{\n\t\t\t\tforeach ($ipv4 as $ipv4_part)\n\t\t\t\t{\n\t\t\t\t\t$value = (int) $ipv4_part;\n\t\t\t\t\tif ((string) $value !== $ipv4_part || $value < 0 || $value > 0xFF)\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Checks if the given IP is a valid IPv6 address\n\t *\n\t * @codeCoverageIgnore\n\t * @deprecated Use {@see SimplePie_Net_IPv6::check_ipv6()} instead\n\t * @see check_ipv6\n\t * @param string $ip An IPv6 address\n\t * @return bool true if $ip is a valid IPv6 address\n\t */\n\tpublic static function checkIPv6($ip)\n\t{\n\t\treturn self::check_ipv6($ip);\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Parse/Date.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n\n/**\n * Date Parser\n *\n * @package SimplePie\n * @subpackage Parsing\n */\nclass SimplePie_Parse_Date\n{\n\t/**\n\t * Input data\n\t *\n\t * @access protected\n\t * @var string\n\t */\n\tvar $date;\n\n\t/**\n\t * List of days, calendar day name => ordinal day number in the week\n\t *\n\t * @access protected\n\t * @var array\n\t */\n\tvar $day = array(\n\t\t// English\n\t\t'mon' => 1,\n\t\t'monday' => 1,\n\t\t'tue' => 2,\n\t\t'tuesday' => 2,\n\t\t'wed' => 3,\n\t\t'wednesday' => 3,\n\t\t'thu' => 4,\n\t\t'thursday' => 4,\n\t\t'fri' => 5,\n\t\t'friday' => 5,\n\t\t'sat' => 6,\n\t\t'saturday' => 6,\n\t\t'sun' => 7,\n\t\t'sunday' => 7,\n\t\t// Dutch\n\t\t'maandag' => 1,\n\t\t'dinsdag' => 2,\n\t\t'woensdag' => 3,\n\t\t'donderdag' => 4,\n\t\t'vrijdag' => 5,\n\t\t'zaterdag' => 6,\n\t\t'zondag' => 7,\n\t\t// French\n\t\t'lundi' => 1,\n\t\t'mardi' => 2,\n\t\t'mercredi' => 3,\n\t\t'jeudi' => 4,\n\t\t'vendredi' => 5,\n\t\t'samedi' => 6,\n\t\t'dimanche' => 7,\n\t\t// German\n\t\t'montag' => 1,\n\t\t'dienstag' => 2,\n\t\t'mittwoch' => 3,\n\t\t'donnerstag' => 4,\n\t\t'freitag' => 5,\n\t\t'samstag' => 6,\n\t\t'sonnabend' => 6,\n\t\t'sonntag' => 7,\n\t\t// Italian\n\t\t'lunedì' => 1,\n\t\t'martedì' => 2,\n\t\t'mercoledì' => 3,\n\t\t'giovedì' => 4,\n\t\t'venerdì' => 5,\n\t\t'sabato' => 6,\n\t\t'domenica' => 7,\n\t\t// Spanish\n\t\t'lunes' => 1,\n\t\t'martes' => 2,\n\t\t'miércoles' => 3,\n\t\t'jueves' => 4,\n\t\t'viernes' => 5,\n\t\t'sábado' => 6,\n\t\t'domingo' => 7,\n\t\t// Finnish\n\t\t'maanantai' => 1,\n\t\t'tiistai' => 2,\n\t\t'keskiviikko' => 3,\n\t\t'torstai' => 4,\n\t\t'perjantai' => 5,\n\t\t'lauantai' => 6,\n\t\t'sunnuntai' => 7,\n\t\t// Hungarian\n\t\t'hétfő' => 1,\n\t\t'kedd' => 2,\n\t\t'szerda' => 3,\n\t\t'csütörtok' => 4,\n\t\t'péntek' => 5,\n\t\t'szombat' => 6,\n\t\t'vasárnap' => 7,\n\t\t// Greek\n\t\t'Δευ' => 1,\n\t\t'Τρι' => 2,\n\t\t'Τετ' => 3,\n\t\t'Πεμ' => 4,\n\t\t'Παρ' => 5,\n\t\t'Σαβ' => 6,\n\t\t'Κυρ' => 7,\n\t);\n\n\t/**\n\t * List of months, calendar month name => calendar month number\n\t *\n\t * @access protected\n\t * @var array\n\t */\n\tvar $month = array(\n\t\t// English\n\t\t'jan' => 1,\n\t\t'january' => 1,\n\t\t'feb' => 2,\n\t\t'february' => 2,\n\t\t'mar' => 3,\n\t\t'march' => 3,\n\t\t'apr' => 4,\n\t\t'april' => 4,\n\t\t'may' => 5,\n\t\t// No long form of May\n\t\t'jun' => 6,\n\t\t'june' => 6,\n\t\t'jul' => 7,\n\t\t'july' => 7,\n\t\t'aug' => 8,\n\t\t'august' => 8,\n\t\t'sep' => 9,\n\t\t'september' => 8,\n\t\t'oct' => 10,\n\t\t'october' => 10,\n\t\t'nov' => 11,\n\t\t'november' => 11,\n\t\t'dec' => 12,\n\t\t'december' => 12,\n\t\t// Dutch\n\t\t'januari' => 1,\n\t\t'februari' => 2,\n\t\t'maart' => 3,\n\t\t'april' => 4,\n\t\t'mei' => 5,\n\t\t'juni' => 6,\n\t\t'juli' => 7,\n\t\t'augustus' => 8,\n\t\t'september' => 9,\n\t\t'oktober' => 10,\n\t\t'november' => 11,\n\t\t'december' => 12,\n\t\t// French\n\t\t'janvier' => 1,\n\t\t'février' => 2,\n\t\t'mars' => 3,\n\t\t'avril' => 4,\n\t\t'mai' => 5,\n\t\t'juin' => 6,\n\t\t'juillet' => 7,\n\t\t'août' => 8,\n\t\t'septembre' => 9,\n\t\t'octobre' => 10,\n\t\t'novembre' => 11,\n\t\t'décembre' => 12,\n\t\t// German\n\t\t'januar' => 1,\n\t\t'februar' => 2,\n\t\t'märz' => 3,\n\t\t'april' => 4,\n\t\t'mai' => 5,\n\t\t'juni' => 6,\n\t\t'juli' => 7,\n\t\t'august' => 8,\n\t\t'september' => 9,\n\t\t'oktober' => 10,\n\t\t'november' => 11,\n\t\t'dezember' => 12,\n\t\t// Italian\n\t\t'gennaio' => 1,\n\t\t'febbraio' => 2,\n\t\t'marzo' => 3,\n\t\t'aprile' => 4,\n\t\t'maggio' => 5,\n\t\t'giugno' => 6,\n\t\t'luglio' => 7,\n\t\t'agosto' => 8,\n\t\t'settembre' => 9,\n\t\t'ottobre' => 10,\n\t\t'novembre' => 11,\n\t\t'dicembre' => 12,\n\t\t// Spanish\n\t\t'enero' => 1,\n\t\t'febrero' => 2,\n\t\t'marzo' => 3,\n\t\t'abril' => 4,\n\t\t'mayo' => 5,\n\t\t'junio' => 6,\n\t\t'julio' => 7,\n\t\t'agosto' => 8,\n\t\t'septiembre' => 9,\n\t\t'setiembre' => 9,\n\t\t'octubre' => 10,\n\t\t'noviembre' => 11,\n\t\t'diciembre' => 12,\n\t\t// Finnish\n\t\t'tammikuu' => 1,\n\t\t'helmikuu' => 2,\n\t\t'maaliskuu' => 3,\n\t\t'huhtikuu' => 4,\n\t\t'toukokuu' => 5,\n\t\t'kesäkuu' => 6,\n\t\t'heinäkuu' => 7,\n\t\t'elokuu' => 8,\n\t\t'suuskuu' => 9,\n\t\t'lokakuu' => 10,\n\t\t'marras' => 11,\n\t\t'joulukuu' => 12,\n\t\t// Hungarian\n\t\t'január' => 1,\n\t\t'február' => 2,\n\t\t'március' => 3,\n\t\t'április' => 4,\n\t\t'május' => 5,\n\t\t'június' => 6,\n\t\t'július' => 7,\n\t\t'augusztus' => 8,\n\t\t'szeptember' => 9,\n\t\t'október' => 10,\n\t\t'november' => 11,\n\t\t'december' => 12,\n\t\t// Greek\n\t\t'Ιαν' => 1,\n\t\t'Φεβ' => 2,\n\t\t'Μάώ' => 3,\n\t\t'Μαώ' => 3,\n\t\t'Απρ' => 4,\n\t\t'Μάι' => 5,\n\t\t'Μαϊ' => 5,\n\t\t'Μαι' => 5,\n\t\t'Ιούν' => 6,\n\t\t'Ιον' => 6,\n\t\t'Ιούλ' => 7,\n\t\t'Ιολ' => 7,\n\t\t'Αύγ' => 8,\n\t\t'Αυγ' => 8,\n\t\t'Σεπ' => 9,\n\t\t'Οκτ' => 10,\n\t\t'Νοέ' => 11,\n\t\t'Δεκ' => 12,\n\t);\n\n\t/**\n\t * List of timezones, abbreviation => offset from UTC\n\t *\n\t * @access protected\n\t * @var array\n\t */\n\tvar $timezone = array(\n\t\t'ACDT' => 37800,\n\t\t'ACIT' => 28800,\n\t\t'ACST' => 34200,\n\t\t'ACT' => -18000,\n\t\t'ACWDT' => 35100,\n\t\t'ACWST' => 31500,\n\t\t'AEDT' => 39600,\n\t\t'AEST' => 36000,\n\t\t'AFT' => 16200,\n\t\t'AKDT' => -28800,\n\t\t'AKST' => -32400,\n\t\t'AMDT' => 18000,\n\t\t'AMT' => -14400,\n\t\t'ANAST' => 46800,\n\t\t'ANAT' => 43200,\n\t\t'ART' => -10800,\n\t\t'AZOST' => -3600,\n\t\t'AZST' => 18000,\n\t\t'AZT' => 14400,\n\t\t'BIOT' => 21600,\n\t\t'BIT' => -43200,\n\t\t'BOT' => -14400,\n\t\t'BRST' => -7200,\n\t\t'BRT' => -10800,\n\t\t'BST' => 3600,\n\t\t'BTT' => 21600,\n\t\t'CAST' => 18000,\n\t\t'CAT' => 7200,\n\t\t'CCT' => 23400,\n\t\t'CDT' => -18000,\n\t\t'CEDT' => 7200,\n\t\t'CET' => 3600,\n\t\t'CGST' => -7200,\n\t\t'CGT' => -10800,\n\t\t'CHADT' => 49500,\n\t\t'CHAST' => 45900,\n\t\t'CIST' => -28800,\n\t\t'CKT' => -36000,\n\t\t'CLDT' => -10800,\n\t\t'CLST' => -14400,\n\t\t'COT' => -18000,\n\t\t'CST' => -21600,\n\t\t'CVT' => -3600,\n\t\t'CXT' => 25200,\n\t\t'DAVT' => 25200,\n\t\t'DTAT' => 36000,\n\t\t'EADT' => -18000,\n\t\t'EAST' => -21600,\n\t\t'EAT' => 10800,\n\t\t'ECT' => -18000,\n\t\t'EDT' => -14400,\n\t\t'EEST' => 10800,\n\t\t'EET' => 7200,\n\t\t'EGT' => -3600,\n\t\t'EKST' => 21600,\n\t\t'EST' => -18000,\n\t\t'FJT' => 43200,\n\t\t'FKDT' => -10800,\n\t\t'FKST' => -14400,\n\t\t'FNT' => -7200,\n\t\t'GALT' => -21600,\n\t\t'GEDT' => 14400,\n\t\t'GEST' => 10800,\n\t\t'GFT' => -10800,\n\t\t'GILT' => 43200,\n\t\t'GIT' => -32400,\n\t\t'GST' => 14400,\n\t\t'GST' => -7200,\n\t\t'GYT' => -14400,\n\t\t'HAA' => -10800,\n\t\t'HAC' => -18000,\n\t\t'HADT' => -32400,\n\t\t'HAE' => -14400,\n\t\t'HAP' => -25200,\n\t\t'HAR' => -21600,\n\t\t'HAST' => -36000,\n\t\t'HAT' => -9000,\n\t\t'HAY' => -28800,\n\t\t'HKST' => 28800,\n\t\t'HMT' => 18000,\n\t\t'HNA' => -14400,\n\t\t'HNC' => -21600,\n\t\t'HNE' => -18000,\n\t\t'HNP' => -28800,\n\t\t'HNR' => -25200,\n\t\t'HNT' => -12600,\n\t\t'HNY' => -32400,\n\t\t'IRDT' => 16200,\n\t\t'IRKST' => 32400,\n\t\t'IRKT' => 28800,\n\t\t'IRST' => 12600,\n\t\t'JFDT' => -10800,\n\t\t'JFST' => -14400,\n\t\t'JST' => 32400,\n\t\t'KGST' => 21600,\n\t\t'KGT' => 18000,\n\t\t'KOST' => 39600,\n\t\t'KOVST' => 28800,\n\t\t'KOVT' => 25200,\n\t\t'KRAST' => 28800,\n\t\t'KRAT' => 25200,\n\t\t'KST' => 32400,\n\t\t'LHDT' => 39600,\n\t\t'LHST' => 37800,\n\t\t'LINT' => 50400,\n\t\t'LKT' => 21600,\n\t\t'MAGST' => 43200,\n\t\t'MAGT' => 39600,\n\t\t'MAWT' => 21600,\n\t\t'MDT' => -21600,\n\t\t'MESZ' => 7200,\n\t\t'MEZ' => 3600,\n\t\t'MHT' => 43200,\n\t\t'MIT' => -34200,\n\t\t'MNST' => 32400,\n\t\t'MSDT' => 14400,\n\t\t'MSST' => 10800,\n\t\t'MST' => -25200,\n\t\t'MUT' => 14400,\n\t\t'MVT' => 18000,\n\t\t'MYT' => 28800,\n\t\t'NCT' => 39600,\n\t\t'NDT' => -9000,\n\t\t'NFT' => 41400,\n\t\t'NMIT' => 36000,\n\t\t'NOVST' => 25200,\n\t\t'NOVT' => 21600,\n\t\t'NPT' => 20700,\n\t\t'NRT' => 43200,\n\t\t'NST' => -12600,\n\t\t'NUT' => -39600,\n\t\t'NZDT' => 46800,\n\t\t'NZST' => 43200,\n\t\t'OMSST' => 25200,\n\t\t'OMST' => 21600,\n\t\t'PDT' => -25200,\n\t\t'PET' => -18000,\n\t\t'PETST' => 46800,\n\t\t'PETT' => 43200,\n\t\t'PGT' => 36000,\n\t\t'PHOT' => 46800,\n\t\t'PHT' => 28800,\n\t\t'PKT' => 18000,\n\t\t'PMDT' => -7200,\n\t\t'PMST' => -10800,\n\t\t'PONT' => 39600,\n\t\t'PST' => -28800,\n\t\t'PWT' => 32400,\n\t\t'PYST' => -10800,\n\t\t'PYT' => -14400,\n\t\t'RET' => 14400,\n\t\t'ROTT' => -10800,\n\t\t'SAMST' => 18000,\n\t\t'SAMT' => 14400,\n\t\t'SAST' => 7200,\n\t\t'SBT' => 39600,\n\t\t'SCDT' => 46800,\n\t\t'SCST' => 43200,\n\t\t'SCT' => 14400,\n\t\t'SEST' => 3600,\n\t\t'SGT' => 28800,\n\t\t'SIT' => 28800,\n\t\t'SRT' => -10800,\n\t\t'SST' => -39600,\n\t\t'SYST' => 10800,\n\t\t'SYT' => 7200,\n\t\t'TFT' => 18000,\n\t\t'THAT' => -36000,\n\t\t'TJT' => 18000,\n\t\t'TKT' => -36000,\n\t\t'TMT' => 18000,\n\t\t'TOT' => 46800,\n\t\t'TPT' => 32400,\n\t\t'TRUT' => 36000,\n\t\t'TVT' => 43200,\n\t\t'TWT' => 28800,\n\t\t'UYST' => -7200,\n\t\t'UYT' => -10800,\n\t\t'UZT' => 18000,\n\t\t'VET' => -14400,\n\t\t'VLAST' => 39600,\n\t\t'VLAT' => 36000,\n\t\t'VOST' => 21600,\n\t\t'VUT' => 39600,\n\t\t'WAST' => 7200,\n\t\t'WAT' => 3600,\n\t\t'WDT' => 32400,\n\t\t'WEST' => 3600,\n\t\t'WFT' => 43200,\n\t\t'WIB' => 25200,\n\t\t'WIT' => 32400,\n\t\t'WITA' => 28800,\n\t\t'WKST' => 18000,\n\t\t'WST' => 28800,\n\t\t'YAKST' => 36000,\n\t\t'YAKT' => 32400,\n\t\t'YAPT' => 36000,\n\t\t'YEKST' => 21600,\n\t\t'YEKT' => 18000,\n\t);\n\n\t/**\n\t * Cached PCRE for SimplePie_Parse_Date::$day\n\t *\n\t * @access protected\n\t * @var string\n\t */\n\tvar $day_pcre;\n\n\t/**\n\t * Cached PCRE for SimplePie_Parse_Date::$month\n\t *\n\t * @access protected\n\t * @var string\n\t */\n\tvar $month_pcre;\n\n\t/**\n\t * Array of user-added callback methods\n\t *\n\t * @access private\n\t * @var array\n\t */\n\tvar $built_in = array();\n\n\t/**\n\t * Array of user-added callback methods\n\t *\n\t * @access private\n\t * @var array\n\t */\n\tvar $user = array();\n\n\t/**\n\t * Create new SimplePie_Parse_Date object, and set self::day_pcre,\n\t * self::month_pcre, and self::built_in\n\t *\n\t * @access private\n\t */\n\tpublic function __construct()\n\t{\n\t\t$this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';\n\t\t$this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';\n\n\t\tstatic $cache;\n\t\tif (!isset($cache[get_class($this)]))\n\t\t{\n\t\t\t$all_methods = get_class_methods($this);\n\n\t\t\tforeach ($all_methods as $method)\n\t\t\t{\n\t\t\t\tif (strtolower(substr($method, 0, 5)) === 'date_')\n\t\t\t\t{\n\t\t\t\t\t$cache[get_class($this)][] = $method;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tforeach ($cache[get_class($this)] as $method)\n\t\t{\n\t\t\t$this->built_in[] = $method;\n\t\t}\n\t}\n\n\t/**\n\t * Get the object\n\t *\n\t * @access public\n\t */\n\tpublic static function get()\n\t{\n\t\tstatic $object;\n\t\tif (!$object)\n\t\t{\n\t\t\t$object = new SimplePie_Parse_Date;\n\t\t}\n\t\treturn $object;\n\t}\n\n\t/**\n\t * Parse a date\n\t *\n\t * @final\n\t * @access public\n\t * @param string $date Date to parse\n\t * @return int Timestamp corresponding to date string, or false on failure\n\t */\n\tpublic function parse($date)\n\t{\n\t\tforeach ($this->user as $method)\n\t\t{\n\t\t\tif (($returned = call_user_func($method, $date)) !== false)\n\t\t\t{\n\t\t\t\treturn $returned;\n\t\t\t}\n\t\t}\n\n\t\tforeach ($this->built_in as $method)\n\t\t{\n\t\t\tif (($returned = call_user_func(array($this, $method), $date)) !== false)\n\t\t\t{\n\t\t\t\treturn $returned;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Add a callback method to parse a date\n\t *\n\t * @final\n\t * @access public\n\t * @param callback $callback\n\t */\n\tpublic function add_callback($callback)\n\t{\n\t\tif (is_callable($callback))\n\t\t{\n\t\t\t$this->user[] = $callback;\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttrigger_error('User-supplied function must be a valid callback', E_USER_WARNING);\n\t\t}\n\t}\n\n\t/**\n\t * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as\n\t * well as allowing any of upper or lower case \"T\", horizontal tabs, or\n\t * spaces to be used as the time seperator (including more than one))\n\t *\n\t * @access protected\n\t * @return int Timestamp\n\t */\n\tpublic function date_w3cdtf($date)\n\t{\n\t\tstatic $pcre;\n\t\tif (!$pcre)\n\t\t{\n\t\t\t$year = '([0-9]{4})';\n\t\t\t$month = $day = $hour = $minute = $second = '([0-9]{2})';\n\t\t\t$decimal = '([0-9]*)';\n\t\t\t$zone = '(?:(Z)|([+\\-])([0-9]{1,2}):?([0-9]{1,2}))';\n\t\t\t$pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\\x09\\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';\n\t\t}\n\t\tif (preg_match($pcre, $date, $match))\n\t\t{\n\t\t\t/*\n\t\t\tCapturing subpatterns:\n\t\t\t1: Year\n\t\t\t2: Month\n\t\t\t3: Day\n\t\t\t4: Hour\n\t\t\t5: Minute\n\t\t\t6: Second\n\t\t\t7: Decimal fraction of a second\n\t\t\t8: Zulu\n\t\t\t9: Timezone ±\n\t\t\t10: Timezone hours\n\t\t\t11: Timezone minutes\n\t\t\t*/\n\n\t\t\t// Fill in empty matches\n\t\t\tfor ($i = count($match); $i <= 3; $i++)\n\t\t\t{\n\t\t\t\t$match[$i] = '1';\n\t\t\t}\n\n\t\t\tfor ($i = count($match); $i <= 7; $i++)\n\t\t\t{\n\t\t\t\t$match[$i] = '0';\n\t\t\t}\n\n\t\t\t// Numeric timezone\n\t\t\tif (isset($match[9]) && $match[9] !== '')\n\t\t\t{\n\t\t\t\t$timezone = $match[10] * 3600;\n\t\t\t\t$timezone += $match[11] * 60;\n\t\t\t\tif ($match[9] === '-')\n\t\t\t\t{\n\t\t\t\t\t$timezone = 0 - $timezone;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$timezone = 0;\n\t\t\t}\n\n\t\t\t// Convert the number of seconds to an integer, taking decimals into account\n\t\t\t$second = round($match[6] + $match[7] / pow(10, strlen($match[7])));\n\n\t\t\treturn gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Remove RFC822 comments\n\t *\n\t * @access protected\n\t * @param string $data Data to strip comments from\n\t * @return string Comment stripped string\n\t */\n\tpublic function remove_rfc2822_comments($string)\n\t{\n\t\t$string = (string) $string;\n\t\t$position = 0;\n\t\t$length = strlen($string);\n\t\t$depth = 0;\n\n\t\t$output = '';\n\n\t\twhile ($position < $length && ($pos = strpos($string, '(', $position)) !== false)\n\t\t{\n\t\t\t$output .= substr($string, $position, $pos - $position);\n\t\t\t$position = $pos + 1;\n\t\t\tif ($string[$pos - 1] !== '\\\\')\n\t\t\t{\n\t\t\t\t$depth++;\n\t\t\t\twhile ($depth && $position < $length)\n\t\t\t\t{\n\t\t\t\t\t$position += strcspn($string, '()', $position);\n\t\t\t\t\tif ($string[$position - 1] === '\\\\')\n\t\t\t\t\t{\n\t\t\t\t\t\t$position++;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\telseif (isset($string[$position]))\n\t\t\t\t\t{\n\t\t\t\t\t\tswitch ($string[$position])\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase '(':\n\t\t\t\t\t\t\t\t$depth++;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase ')':\n\t\t\t\t\t\t\t\t$depth--;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$position++;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$output .= '(';\n\t\t\t}\n\t\t}\n\t\t$output .= substr($string, $position);\n\n\t\treturn $output;\n\t}\n\n\t/**\n\t * Parse RFC2822's date format\n\t *\n\t * @access protected\n\t * @return int Timestamp\n\t */\n\tpublic function date_rfc2822($date)\n\t{\n\t\tstatic $pcre;\n\t\tif (!$pcre)\n\t\t{\n\t\t\t$wsp = '[\\x09\\x20]';\n\t\t\t$fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\\x0D\\x0A' . $wsp . '+)+)';\n\t\t\t$optional_fws = $fws . '?';\n\t\t\t$day_name = $this->day_pcre;\n\t\t\t$month = $this->month_pcre;\n\t\t\t$day = '([0-9]{1,2})';\n\t\t\t$hour = $minute = $second = '([0-9]{2})';\n\t\t\t$year = '([0-9]{2,4})';\n\t\t\t$num_zone = '([+\\-])([0-9]{2})([0-9]{2})';\n\t\t\t$character_zone = '([A-Z]{1,5})';\n\t\t\t$zone = '(?:' . $num_zone . '|' . $character_zone . ')';\n\t\t\t$pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i';\n\t\t}\n\t\tif (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))\n\t\t{\n\t\t\t/*\n\t\t\tCapturing subpatterns:\n\t\t\t1: Day name\n\t\t\t2: Day\n\t\t\t3: Month\n\t\t\t4: Year\n\t\t\t5: Hour\n\t\t\t6: Minute\n\t\t\t7: Second\n\t\t\t8: Timezone ±\n\t\t\t9: Timezone hours\n\t\t\t10: Timezone minutes\n\t\t\t11: Alphabetic timezone\n\t\t\t*/\n\n\t\t\t// Find the month number\n\t\t\t$month = $this->month[strtolower($match[3])];\n\n\t\t\t// Numeric timezone\n\t\t\tif ($match[8] !== '')\n\t\t\t{\n\t\t\t\t$timezone = $match[9] * 3600;\n\t\t\t\t$timezone += $match[10] * 60;\n\t\t\t\tif ($match[8] === '-')\n\t\t\t\t{\n\t\t\t\t\t$timezone = 0 - $timezone;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Character timezone\n\t\t\telseif (isset($this->timezone[strtoupper($match[11])]))\n\t\t\t{\n\t\t\t\t$timezone = $this->timezone[strtoupper($match[11])];\n\t\t\t}\n\t\t\t// Assume everything else to be -0000\n\t\t\telse\n\t\t\t{\n\t\t\t\t$timezone = 0;\n\t\t\t}\n\n\t\t\t// Deal with 2/3 digit years\n\t\t\tif ($match[4] < 50)\n\t\t\t{\n\t\t\t\t$match[4] += 2000;\n\t\t\t}\n\t\t\telseif ($match[4] < 1000)\n\t\t\t{\n\t\t\t\t$match[4] += 1900;\n\t\t\t}\n\n\t\t\t// Second is optional, if it is empty set it to zero\n\t\t\tif ($match[7] !== '')\n\t\t\t{\n\t\t\t\t$second = $match[7];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$second = 0;\n\t\t\t}\n\n\t\t\treturn gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Parse RFC850's date format\n\t *\n\t * @access protected\n\t * @return int Timestamp\n\t */\n\tpublic function date_rfc850($date)\n\t{\n\t\tstatic $pcre;\n\t\tif (!$pcre)\n\t\t{\n\t\t\t$space = '[\\x09\\x20]+';\n\t\t\t$day_name = $this->day_pcre;\n\t\t\t$month = $this->month_pcre;\n\t\t\t$day = '([0-9]{1,2})';\n\t\t\t$year = $hour = $minute = $second = '([0-9]{2})';\n\t\t\t$zone = '([A-Z]{1,5})';\n\t\t\t$pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';\n\t\t}\n\t\tif (preg_match($pcre, $date, $match))\n\t\t{\n\t\t\t/*\n\t\t\tCapturing subpatterns:\n\t\t\t1: Day name\n\t\t\t2: Day\n\t\t\t3: Month\n\t\t\t4: Year\n\t\t\t5: Hour\n\t\t\t6: Minute\n\t\t\t7: Second\n\t\t\t8: Timezone\n\t\t\t*/\n\n\t\t\t// Month\n\t\t\t$month = $this->month[strtolower($match[3])];\n\n\t\t\t// Character timezone\n\t\t\tif (isset($this->timezone[strtoupper($match[8])]))\n\t\t\t{\n\t\t\t\t$timezone = $this->timezone[strtoupper($match[8])];\n\t\t\t}\n\t\t\t// Assume everything else to be -0000\n\t\t\telse\n\t\t\t{\n\t\t\t\t$timezone = 0;\n\t\t\t}\n\n\t\t\t// Deal with 2 digit year\n\t\t\tif ($match[4] < 50)\n\t\t\t{\n\t\t\t\t$match[4] += 2000;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$match[4] += 1900;\n\t\t\t}\n\n\t\t\treturn gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Parse C99's asctime()'s date format\n\t *\n\t * @access protected\n\t * @return int Timestamp\n\t */\n\tpublic function date_asctime($date)\n\t{\n\t\tstatic $pcre;\n\t\tif (!$pcre)\n\t\t{\n\t\t\t$space = '[\\x09\\x20]+';\n\t\t\t$wday_name = $this->day_pcre;\n\t\t\t$mon_name = $this->month_pcre;\n\t\t\t$day = '([0-9]{1,2})';\n\t\t\t$hour = $sec = $min = '([0-9]{2})';\n\t\t\t$year = '([0-9]{4})';\n\t\t\t$terminator = '\\x0A?\\x00?';\n\t\t\t$pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';\n\t\t}\n\t\tif (preg_match($pcre, $date, $match))\n\t\t{\n\t\t\t/*\n\t\t\tCapturing subpatterns:\n\t\t\t1: Day name\n\t\t\t2: Month\n\t\t\t3: Day\n\t\t\t4: Hour\n\t\t\t5: Minute\n\t\t\t6: Second\n\t\t\t7: Year\n\t\t\t*/\n\n\t\t\t$month = $this->month[strtolower($match[2])];\n\t\t\treturn gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Parse dates using strtotime()\n\t *\n\t * @access protected\n\t * @return int Timestamp\n\t */\n\tpublic function date_strtotime($date)\n\t{\n\t\t$strtotime = strtotime($date);\n\t\tif ($strtotime === -1 || $strtotime === false)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn $strtotime;\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Parser.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Parses XML into something sane\n *\n *\n * This class can be overloaded with {@see SimplePie::set_parser_class()}\n *\n * @package SimplePie\n * @subpackage Parsing\n */\nclass SimplePie_Parser\n{\n\tvar $error_code;\n\tvar $error_string;\n\tvar $current_line;\n\tvar $current_column;\n\tvar $current_byte;\n\tvar $separator = ' ';\n\tvar $namespace = array('');\n\tvar $element = array('');\n\tvar $xml_base = array('');\n\tvar $xml_base_explicit = array(false);\n\tvar $xml_lang = array('');\n\tvar $data = array();\n\tvar $datas = array(array());\n\tvar $current_xhtml_construct = -1;\n\tvar $encoding;\n\tprotected $registry;\n\n\tpublic function set_registry(SimplePie_Registry $registry)\n\t{\n\t\t$this->registry = $registry;\n\t}\n\n\tpublic function parse(&$data, $encoding)\n\t{\n\t\t// Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character\n\t\tif (strtoupper($encoding) === 'US-ASCII')\n\t\t{\n\t\t\t$this->encoding = 'UTF-8';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->encoding = $encoding;\n\t\t}\n\n\t\t// Strip BOM:\n\t\t// UTF-32 Big Endian BOM\n\t\tif (substr($data, 0, 4) === \"\\x00\\x00\\xFE\\xFF\")\n\t\t{\n\t\t\t$data = substr($data, 4);\n\t\t}\n\t\t// UTF-32 Little Endian BOM\n\t\telseif (substr($data, 0, 4) === \"\\xFF\\xFE\\x00\\x00\")\n\t\t{\n\t\t\t$data = substr($data, 4);\n\t\t}\n\t\t// UTF-16 Big Endian BOM\n\t\telseif (substr($data, 0, 2) === \"\\xFE\\xFF\")\n\t\t{\n\t\t\t$data = substr($data, 2);\n\t\t}\n\t\t// UTF-16 Little Endian BOM\n\t\telseif (substr($data, 0, 2) === \"\\xFF\\xFE\")\n\t\t{\n\t\t\t$data = substr($data, 2);\n\t\t}\n\t\t// UTF-8 BOM\n\t\telseif (substr($data, 0, 3) === \"\\xEF\\xBB\\xBF\")\n\t\t{\n\t\t\t$data = substr($data, 3);\n\t\t}\n\n\t\tif (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), \"\\x09\\x0A\\x0D\\x20\") && ($pos = strpos($data, '?>')) !== false)\n\t\t{\n\t\t\t$declaration = $this->registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5)));\n\t\t\tif ($declaration->parse())\n\t\t\t{\n\t\t\t\t$data = substr($data, $pos + 2);\n\t\t\t\t$data = '<?xml version=\"' . $declaration->version . '\" encoding=\"' . $encoding . '\" standalone=\"' . (($declaration->standalone) ? 'yes' : 'no') . '\"?>' . $data;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->error_string = 'SimplePie bug! Please report this!';\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t$return = true;\n\n\t\tstatic $xml_is_sane = null;\n\t\tif ($xml_is_sane === null)\n\t\t{\n\t\t\t$parser_check = xml_parser_create();\n\t\t\txml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);\n\t\t\txml_parser_free($parser_check);\n\t\t\t$xml_is_sane = isset($values[0]['value']);\n\t\t}\n\n\t\t// Create the parser\n\t\tif ($xml_is_sane)\n\t\t{\n\t\t\t$xml = xml_parser_create_ns($this->encoding, $this->separator);\n\t\t\txml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);\n\t\t\txml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);\n\t\t\txml_set_object($xml, $this);\n\t\t\txml_set_character_data_handler($xml, 'cdata');\n\t\t\txml_set_element_handler($xml, 'tag_open', 'tag_close');\n\n\t\t\t// Parse!\n\t\t\tif (!xml_parse($xml, $data, true))\n\t\t\t{\n\t\t\t\t$this->error_code = xml_get_error_code($xml);\n\t\t\t\t$this->error_string = xml_error_string($this->error_code);\n\t\t\t\t$return = false;\n\t\t\t}\n\t\t\t$this->current_line = xml_get_current_line_number($xml);\n\t\t\t$this->current_column = xml_get_current_column_number($xml);\n\t\t\t$this->current_byte = xml_get_current_byte_index($xml);\n\t\t\txml_parser_free($xml);\n\t\t\treturn $return;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlibxml_clear_errors();\n\t\t\t$xml = new XMLReader();\n\t\t\t$xml->xml($data);\n\t\t\twhile (@$xml->read())\n\t\t\t{\n\t\t\t\tswitch ($xml->nodeType)\n\t\t\t\t{\n\n\t\t\t\t\tcase constant('XMLReader::END_ELEMENT'):\n\t\t\t\t\t\tif ($xml->namespaceURI !== '')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$tagName = $xml->namespaceURI . $this->separator . $xml->localName;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$tagName = $xml->localName;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$this->tag_close(null, $tagName);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase constant('XMLReader::ELEMENT'):\n\t\t\t\t\t\t$empty = $xml->isEmptyElement;\n\t\t\t\t\t\tif ($xml->namespaceURI !== '')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$tagName = $xml->namespaceURI . $this->separator . $xml->localName;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$tagName = $xml->localName;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$attributes = array();\n\t\t\t\t\t\twhile ($xml->moveToNextAttribute())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ($xml->namespaceURI !== '')\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$attrName = $xml->namespaceURI . $this->separator . $xml->localName;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$attrName = $xml->localName;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$attributes[$attrName] = $xml->value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$this->tag_open(null, $tagName, $attributes);\n\t\t\t\t\t\tif ($empty)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->tag_close(null, $tagName);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase constant('XMLReader::TEXT'):\n\n\t\t\t\t\tcase constant('XMLReader::CDATA'):\n\t\t\t\t\t\t$this->cdata(null, $xml->value);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ($error = libxml_get_last_error())\n\t\t\t{\n\t\t\t\t$this->error_code = $error->code;\n\t\t\t\t$this->error_string = $error->message;\n\t\t\t\t$this->current_line = $error->line;\n\t\t\t\t$this->current_column = $error->column;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic function get_error_code()\n\t{\n\t\treturn $this->error_code;\n\t}\n\n\tpublic function get_error_string()\n\t{\n\t\treturn $this->error_string;\n\t}\n\n\tpublic function get_current_line()\n\t{\n\t\treturn $this->current_line;\n\t}\n\n\tpublic function get_current_column()\n\t{\n\t\treturn $this->current_column;\n\t}\n\n\tpublic function get_current_byte()\n\t{\n\t\treturn $this->current_byte;\n\t}\n\n\tpublic function get_data()\n\t{\n\t\treturn $this->data;\n\t}\n\n\tpublic function tag_open($parser, $tag, $attributes)\n\t{\n\t\tlist($this->namespace[], $this->element[]) = $this->split_ns($tag);\n\n\t\t$attribs = array();\n\t\tforeach ($attributes as $name => $value)\n\t\t{\n\t\t\tlist($attrib_namespace, $attribute) = $this->split_ns($name);\n\t\t\t$attribs[$attrib_namespace][$attribute] = $value;\n\t\t}\n\n\t\tif (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))\n\t\t{\n\t\t\t$base = $this->registry->call('Misc', 'absolutize_url', array($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base)));\n\t\t\tif ($base !== false)\n\t\t\t{\n\t\t\t\t$this->xml_base[] = $base;\n\t\t\t\t$this->xml_base_explicit[] = true;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->xml_base[] = end($this->xml_base);\n\t\t\t$this->xml_base_explicit[] = end($this->xml_base_explicit);\n\t\t}\n\n\t\tif (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))\n\t\t{\n\t\t\t$this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->xml_lang[] = end($this->xml_lang);\n\t\t}\n\n\t\tif ($this->current_xhtml_construct >= 0)\n\t\t{\n\t\t\t$this->current_xhtml_construct++;\n\t\t\tif (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)\n\t\t\t{\n\t\t\t\t$this->data['data'] .= '<' . end($this->element);\n\t\t\t\tif (isset($attribs['']))\n\t\t\t\t{\n\t\t\t\t\tforeach ($attribs[''] as $name => $value)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->data['data'] .= ' ' . $name . '=\"' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '\"';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$this->data['data'] .= '>';\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->datas[] =& $this->data;\n\t\t\t$this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];\n\t\t\t$this->data = array('data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang));\n\t\t\tif ((end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] === 'xml')\n\t\t\t|| (end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] === 'xhtml')\n\t\t\t|| (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_20 && in_array(end($this->element), array('title')))\n\t\t\t|| (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_090 && in_array(end($this->element), array('title')))\n\t\t\t|| (end($this->namespace) === SIMPLEPIE_NAMESPACE_RSS_10 && in_array(end($this->element), array('title'))))\n\t\t\t{\n\t\t\t\t$this->current_xhtml_construct = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic function cdata($parser, $cdata)\n\t{\n\t\tif ($this->current_xhtml_construct >= 0)\n\t\t{\n\t\t\t$this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->data['data'] .= $cdata;\n\t\t}\n\t}\n\n\tpublic function tag_close($parser, $tag)\n\t{\n\t\tif ($this->current_xhtml_construct >= 0)\n\t\t{\n\t\t\t$this->current_xhtml_construct--;\n\t\t\tif (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param')))\n\t\t\t{\n\t\t\t\t$this->data['data'] .= '</' . end($this->element) . '>';\n\t\t\t}\n\t\t}\n\t\tif ($this->current_xhtml_construct === -1)\n\t\t{\n\t\t\t$this->data =& $this->datas[count($this->datas) - 1];\n\t\t\tarray_pop($this->datas);\n\t\t}\n\n\t\tarray_pop($this->element);\n\t\tarray_pop($this->namespace);\n\t\tarray_pop($this->xml_base);\n\t\tarray_pop($this->xml_base_explicit);\n\t\tarray_pop($this->xml_lang);\n\t}\n\n\tpublic function split_ns($string)\n\t{\n\t\tstatic $cache = array();\n\t\tif (!isset($cache[$string]))\n\t\t{\n\t\t\tif ($pos = strpos($string, $this->separator))\n\t\t\t{\n\t\t\t\tstatic $separator_length;\n\t\t\t\tif (!$separator_length)\n\t\t\t\t{\n\t\t\t\t\t$separator_length = strlen($this->separator);\n\t\t\t\t}\n\t\t\t\t$namespace = substr($string, 0, $pos);\n\t\t\t\t$local_name = substr($string, $pos + $separator_length);\n\t\t\t\tif (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)\n\t\t\t\t{\n\t\t\t\t\t$namespace = SIMPLEPIE_NAMESPACE_ITUNES;\n\t\t\t\t}\n\n\t\t\t\t// Normalize the Media RSS namespaces\n\t\t\t\tif ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG ||\n\t\t\t\t\t$namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2 ||\n\t\t\t\t\t$namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3 ||\n\t\t\t\t\t$namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4 ||\n\t\t\t\t\t$namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5 )\n\t\t\t\t{\n\t\t\t\t\t$namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;\n\t\t\t\t}\n\t\t\t\t$cache[$string] = array($namespace, $local_name);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$cache[$string] = array('', $string);\n\t\t\t}\n\t\t}\n\t\treturn $cache[$string];\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Rating.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Handles `<media:rating>` or `<itunes:explicit>` tags as defined in Media RSS and iTunes RSS respectively\n *\n * Used by {@see SimplePie_Enclosure::get_rating()} and {@see SimplePie_Enclosure::get_ratings()}\n *\n * This class can be overloaded with {@see SimplePie::set_rating_class()}\n *\n * @package SimplePie\n * @subpackage API\n */\nclass SimplePie_Rating\n{\n\t/**\n\t * Rating scheme\n\t *\n\t * @var string\n\t * @see get_scheme()\n\t */\n\tvar $scheme;\n\n\t/**\n\t * Rating value\n\t *\n\t * @var string\n\t * @see get_value()\n\t */\n\tvar $value;\n\n\t/**\n\t * Constructor, used to input the data\n\t *\n\t * For documentation on all the parameters, see the corresponding\n\t * properties and their accessors\n\t */\n\tpublic function __construct($scheme = null, $value = null)\n\t{\n\t\t$this->scheme = $scheme;\n\t\t$this->value = $value;\n\t}\n\n\t/**\n\t * String-ified version\n\t *\n\t * @return string\n\t */\n\tpublic function __toString()\n\t{\n\t\t// There is no $this->data here\n\t\treturn md5(serialize($this));\n\t}\n\n\t/**\n\t * Get the organizational scheme for the rating\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_scheme()\n\t{\n\t\tif ($this->scheme !== null)\n\t\t{\n\t\t\treturn $this->scheme;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the value of the rating\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_value()\n\t{\n\t\tif ($this->value !== null)\n\t\t{\n\t\t\treturn $this->value;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Registry.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Handles creating objects and calling methods\n *\n * Access this via {@see SimplePie::get_registry()}\n *\n * @package SimplePie\n */\nclass SimplePie_Registry\n{\n\t/**\n\t * Default class mapping\n\t *\n\t * Overriding classes *must* subclass these.\n\t *\n\t * @var array\n\t */\n\tprotected $default = array(\n\t\t'Cache' => 'SimplePie_Cache',\n\t\t'Locator' => 'SimplePie_Locator',\n\t\t'Parser' => 'SimplePie_Parser',\n\t\t'File' => 'SimplePie_File',\n\t\t'Sanitize' => 'SimplePie_Sanitize',\n\t\t'Item' => 'SimplePie_Item',\n\t\t'Author' => 'SimplePie_Author',\n\t\t'Category' => 'SimplePie_Category',\n\t\t'Enclosure' => 'SimplePie_Enclosure',\n\t\t'Caption' => 'SimplePie_Caption',\n\t\t'Copyright' => 'SimplePie_Copyright',\n\t\t'Credit' => 'SimplePie_Credit',\n\t\t'Rating' => 'SimplePie_Rating',\n\t\t'Restriction' => 'SimplePie_Restriction',\n\t\t'Content_Type_Sniffer' => 'SimplePie_Content_Type_Sniffer',\n\t\t'Source' => 'SimplePie_Source',\n\t\t'Misc' => 'SimplePie_Misc',\n\t\t'XML_Declaration_Parser' => 'SimplePie_XML_Declaration_Parser',\n\t\t'Parse_Date' => 'SimplePie_Parse_Date',\n\t);\n\n\t/**\n\t * Class mapping\n\t *\n\t * @see register()\n\t * @var array\n\t */\n\tprotected $classes = array();\n\n\t/**\n\t * Legacy classes\n\t *\n\t * @see register()\n\t * @var array\n\t */\n\tprotected $legacy = array();\n\n\t/**\n\t * Constructor\n\t *\n\t * No-op\n\t */\n\tpublic function __construct() { }\n\n\t/**\n\t * Register a class\n\t *\n\t * @param string $type See {@see $default} for names\n\t * @param string $class Class name, must subclass the corresponding default\n\t * @param bool $legacy Whether to enable legacy support for this class\n\t * @return bool Successfulness\n\t */\n\tpublic function register($type, $class, $legacy = false)\n\t{\n\t\tif (!is_subclass_of($class, $this->default[$type]))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\t$this->classes[$type] = $class;\n\n\t\tif ($legacy)\n\t\t{\n\t\t\t$this->legacy[] = $class;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Get the class registered for a type\n\t *\n\t * Where possible, use {@see create()} or {@see call()} instead\n\t *\n\t * @param string $type\n\t * @return string|null\n\t */\n\tpublic function get_class($type)\n\t{\n\t\tif (!empty($this->classes[$type]))\n\t\t{\n\t\t\treturn $this->classes[$type];\n\t\t}\n\t\tif (!empty($this->default[$type]))\n\t\t{\n\t\t\treturn $this->default[$type];\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Create a new instance of a given type\n\t *\n\t * @param string $type\n\t * @param array $parameters Parameters to pass to the constructor\n\t * @return object Instance of class\n\t */\n\tpublic function &create($type, $parameters = array())\n\t{\n\t\t$class = $this->get_class($type);\n\n\t\tif (in_array($class, $this->legacy))\n\t\t{\n\t\t\tswitch ($type)\n\t\t\t{\n\t\t\t\tcase 'locator':\n\t\t\t\t\t// Legacy: file, timeout, useragent, file_class, max_checked_feeds, content_type_sniffer_class\n\t\t\t\t\t// Specified: file, timeout, useragent, max_checked_feeds\n\t\t\t\t\t$replacement = array($this->get_class('file'), $parameters[3], $this->get_class('content_type_sniffer'));\n\t\t\t\t\tarray_splice($parameters, 3, 1, $replacement);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!method_exists($class, '__construct'))\n\t\t{\n\t\t\t$instance = new $class;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$reflector = new ReflectionClass($class);\n\t\t\t$instance = $reflector->newInstanceArgs($parameters);\n\t\t}\n\n\t\tif (method_exists($instance, 'set_registry'))\n\t\t{\n\t\t\t$instance->set_registry($this);\n\t\t}\n\t\treturn $instance;\n\t}\n\n\t/**\n\t * Call a static method for a type\n\t *\n\t * @param string $type\n\t * @param string $method\n\t * @param array $parameters\n\t * @return mixed\n\t */\n\tpublic function &call($type, $method, $parameters = array())\n\t{\n\t\t$class = $this->get_class($type);\n\n\t\tif (in_array($class, $this->legacy))\n\t\t{\n\t\t\tswitch ($type)\n\t\t\t{\n\t\t\t\tcase 'Cache':\n\t\t\t\t\t// For backwards compatibility with old non-static\n\t\t\t\t\t// Cache::create() methods\n\t\t\t\t\tif ($method === 'get_handler')\n\t\t\t\t\t{\n\t\t\t\t\t\t$result = @call_user_func_array(array($class, 'create'), $parameters);\n\t\t\t\t\t\treturn $result;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t$result = call_user_func_array(array($class, $method), $parameters);\n\t\treturn $result;\n\t}\n}"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Restriction.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Handles `<media:restriction>` as defined in Media RSS\n *\n * Used by {@see SimplePie_Enclosure::get_restriction()} and {@see SimplePie_Enclosure::get_restrictions()}\n *\n * This class can be overloaded with {@see SimplePie::set_restriction_class()}\n *\n * @package SimplePie\n * @subpackage API\n */\nclass SimplePie_Restriction\n{\n\t/**\n\t * Relationship ('allow'/'deny')\n\t *\n\t * @var string\n\t * @see get_relationship()\n\t */\n\tvar $relationship;\n\n\t/**\n\t * Type of restriction\n\t *\n\t * @var string\n\t * @see get_type()\n\t */\n\tvar $type;\n\n\t/**\n\t * Restricted values\n\t *\n\t * @var string\n\t * @see get_value()\n\t */\n\tvar $value;\n\n\t/**\n\t * Constructor, used to input the data\n\t *\n\t * For documentation on all the parameters, see the corresponding\n\t * properties and their accessors\n\t */\n\tpublic function __construct($relationship = null, $type = null, $value = null)\n\t{\n\t\t$this->relationship = $relationship;\n\t\t$this->type = $type;\n\t\t$this->value = $value;\n\t}\n\n\t/**\n\t * String-ified version\n\t *\n\t * @return string\n\t */\n\tpublic function __toString()\n\t{\n\t\t// There is no $this->data here\n\t\treturn md5(serialize($this));\n\t}\n\n\t/**\n\t * Get the relationship\n\t *\n\t * @return string|null Either 'allow' or 'deny'\n\t */\n\tpublic function get_relationship()\n\t{\n\t\tif ($this->relationship !== null)\n\t\t{\n\t\t\treturn $this->relationship;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the type\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_type()\n\t{\n\t\tif ($this->type !== null)\n\t\t{\n\t\t\treturn $this->type;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the list of restricted things\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_value()\n\t{\n\t\tif ($this->value !== null)\n\t\t{\n\t\t\treturn $this->value;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Sanitize.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Used for data cleanup and post-processing\n *\n *\n * This class can be overloaded with {@see SimplePie::set_sanitize_class()}\n *\n * @package SimplePie\n * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags\n */\nclass SimplePie_Sanitize\n{\n\t// Private vars\n\tvar $base;\n\n\t// Options\n\tvar $remove_div = true;\n\tvar $image_handler = '';\n\tvar $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');\n\tvar $encode_instead_of_strip = false;\n\tvar $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');\n\tvar $strip_comments = false;\n\tvar $output_encoding = 'UTF-8';\n\tvar $enable_cache = true;\n\tvar $cache_location = './cache';\n\tvar $cache_name_function = 'md5';\n\tvar $timeout = 10;\n\tvar $useragent = '';\n\tvar $force_fsockopen = false;\n\tvar $replace_url_attributes = null;\n\n\tpublic function __construct()\n\t{\n\t\t// Set defaults\n\t\t$this->set_url_replacements(null);\n\t}\n\n\tpublic function remove_div($enable = true)\n\t{\n\t\t$this->remove_div = (bool) $enable;\n\t}\n\n\tpublic function set_image_handler($page = false)\n\t{\n\t\tif ($page)\n\t\t{\n\t\t\t$this->image_handler = (string) $page;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->image_handler = false;\n\t\t}\n\t}\n\n\tpublic function set_registry(SimplePie_Registry $registry)\n\t{\n\t\t$this->registry = $registry;\n\t}\n\n\tpublic function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')\n\t{\n\t\tif (isset($enable_cache))\n\t\t{\n\t\t\t$this->enable_cache = (bool) $enable_cache;\n\t\t}\n\n\t\tif ($cache_location)\n\t\t{\n\t\t\t$this->cache_location = (string) $cache_location;\n\t\t}\n\n\t\tif ($cache_name_function)\n\t\t{\n\t\t\t$this->cache_name_function = (string) $cache_name_function;\n\t\t}\n\t}\n\n\tpublic function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)\n\t{\n\t\tif ($timeout)\n\t\t{\n\t\t\t$this->timeout = (string) $timeout;\n\t\t}\n\n\t\tif ($useragent)\n\t\t{\n\t\t\t$this->useragent = (string) $useragent;\n\t\t}\n\n\t\tif ($force_fsockopen)\n\t\t{\n\t\t\t$this->force_fsockopen = (string) $force_fsockopen;\n\t\t}\n\t}\n\n\tpublic function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))\n\t{\n\t\tif ($tags)\n\t\t{\n\t\t\tif (is_array($tags))\n\t\t\t{\n\t\t\t\t$this->strip_htmltags = $tags;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->strip_htmltags = explode(',', $tags);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->strip_htmltags = false;\n\t\t}\n\t}\n\n\tpublic function encode_instead_of_strip($encode = false)\n\t{\n\t\t$this->encode_instead_of_strip = (bool) $encode;\n\t}\n\n\tpublic function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))\n\t{\n\t\tif ($attribs)\n\t\t{\n\t\t\tif (is_array($attribs))\n\t\t\t{\n\t\t\t\t$this->strip_attributes = $attribs;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->strip_attributes = explode(',', $attribs);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->strip_attributes = false;\n\t\t}\n\t}\n\n\tpublic function strip_comments($strip = false)\n\t{\n\t\t$this->strip_comments = (bool) $strip;\n\t}\n\n\tpublic function set_output_encoding($encoding = 'UTF-8')\n\t{\n\t\t$this->output_encoding = (string) $encoding;\n\t}\n\n\t/**\n\t * Set element/attribute key/value pairs of HTML attributes\n\t * containing URLs that need to be resolved relative to the feed\n\t *\n\t * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,\n\t * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,\n\t * |q|@cite\n\t *\n\t * @since 1.0\n\t * @param array|null $element_attribute Element/attribute key/value pairs, null for default\n\t */\n\tpublic function set_url_replacements($element_attribute = null)\n\t{\n\t\tif ($element_attribute === null)\n\t\t{\n\t\t\t$element_attribute = array(\n\t\t\t\t'a' => 'href',\n\t\t\t\t'area' => 'href',\n\t\t\t\t'blockquote' => 'cite',\n\t\t\t\t'del' => 'cite',\n\t\t\t\t'form' => 'action',\n\t\t\t\t'img' => array(\n\t\t\t\t\t'longdesc',\n\t\t\t\t\t'src'\n\t\t\t\t),\n\t\t\t\t'input' => 'src',\n\t\t\t\t'ins' => 'cite',\n\t\t\t\t'q' => 'cite'\n\t\t\t);\n\t\t}\n\t\t$this->replace_url_attributes = (array) $element_attribute;\n\t}\n\n\tpublic function sanitize($data, $type, $base = '')\n\t{\n\t\t$data = trim($data);\n\t\tif ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)\n\t\t{\n\t\t\tif ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)\n\t\t\t{\n\t\t\t\tif (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\\/[A-Za-z][^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x2F\\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data))\n\t\t\t\t{\n\t\t\t\t\t$type |= SIMPLEPIE_CONSTRUCT_HTML;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$type |= SIMPLEPIE_CONSTRUCT_TEXT;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ($type & SIMPLEPIE_CONSTRUCT_BASE64)\n\t\t\t{\n\t\t\t\t$data = base64_decode($data);\n\t\t\t}\n\n\t\t\tif ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))\n\t\t\t{\n\n\t\t\t\t$document = new DOMDocument();\n\t\t\t\t$document->encoding = 'UTF-8';\n\t\t\t\t$data = $this->preprocess($data, $type);\n\n\t\t\t\tset_error_handler(array('SimplePie_Misc', 'silence_errors'));\n\t\t\t\t$document->loadHTML($data);\n\t\t\t\trestore_error_handler();\n\n\t\t\t\t// Strip comments\n\t\t\t\tif ($this->strip_comments)\n\t\t\t\t{\n\t\t\t\t\t$xpath = new DOMXPath($document);\n\t\t\t\t\t$comments = $xpath->query('//comment()');\n\n\t\t\t\t\tforeach ($comments as $comment)\n\t\t\t\t\t{\n\t\t\t\t\t\t$comment->parentNode->removeChild($comment);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Strip out HTML tags and attributes that might cause various security problems.\n\t\t\t\t// Based on recommendations by Mark Pilgrim at:\n\t\t\t\t// http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely\n\t\t\t\tif ($this->strip_htmltags)\n\t\t\t\t{\n\t\t\t\t\tforeach ($this->strip_htmltags as $tag)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->strip_tag($tag, $document, $type);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ($this->strip_attributes)\n\t\t\t\t{\n\t\t\t\t\tforeach ($this->strip_attributes as $attrib)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->strip_attr($attrib, $document);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Replace relative URLs\n\t\t\t\t$this->base = $base;\n\t\t\t\tforeach ($this->replace_url_attributes as $element => $attributes)\n\t\t\t\t{\n\t\t\t\t\t$this->replace_urls($document, $element, $attributes);\n\t\t\t\t}\n\n\t\t\t\t// If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.\n\t\t\t\tif (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)\n\t\t\t\t{\n\t\t\t\t\t$images = $document->getElementsByTagName('img');\n\t\t\t\t\tforeach ($images as $img)\n\t\t\t\t\t{\n\t\t\t\t\t\tif ($img->hasAttribute('src'))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$image_url = call_user_func($this->cache_name_function, $img->getAttribute('src'));\n\t\t\t\t\t\t\t$cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, $image_url, 'spi'));\n\n\t\t\t\t\t\t\tif ($cache->load())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$img->setAttribute('src', $this->image_handler . $image_url);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$file = $this->registry->create('File', array($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen));\n\t\t\t\t\t\t\t\t$headers = $file->headers;\n\n\t\t\t\t\t\t\t\tif ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t$img->setAttribute('src', $this->image_handler . $image_url);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttrigger_error(\"$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.\", E_USER_WARNING);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Remove the DOCTYPE\n\t\t\t\t// Seems to cause segfaulting if we don't do this\n\t\t\t\tif ($document->firstChild instanceof DOMDocumentType)\n\t\t\t\t{\n\t\t\t\t\t$document->removeChild($document->firstChild);\n\t\t\t\t}\n\n\t\t\t\t// Move everything from the body to the root\n\t\t\t\t$real_body = $document->getElementsByTagName('body')->item(0)->childNodes->item(0);\n\t\t\t\t$document->replaceChild($real_body, $document->firstChild);\n\n\t\t\t\t// Finally, convert to a HTML string\n\t\t\t\t$data = trim($document->saveHTML());\n\n\t\t\t\tif ($this->remove_div)\n\t\t\t\t{\n\t\t\t\t\t$data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);\n\t\t\t\t\t$data = preg_replace('/<\\/div>$/', '', $data);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ($type & SIMPLEPIE_CONSTRUCT_IRI)\n\t\t\t{\n\t\t\t\t$absolute = $this->registry->call('Misc', 'absolutize_url', array($data, $base));\n\t\t\t\tif ($absolute !== false)\n\t\t\t\t{\n\t\t\t\t\t$data = $absolute;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))\n\t\t\t{\n\t\t\t\t$data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');\n\t\t\t}\n\n\t\t\tif ($this->output_encoding !== 'UTF-8')\n\t\t\t{\n\t\t\t\t$data = $this->registry->call('Misc', 'change_encoding', array($data, 'UTF-8', $this->output_encoding));\n\t\t\t}\n\t\t}\n\t\treturn $data;\n\t}\n\n\tprotected function preprocess($html, $type)\n\t{\n\t\t$ret = '';\n\t\tif ($type & ~SIMPLEPIE_CONSTRUCT_XHTML)\n\t\t{\n\t\t\t// Atom XHTML constructs are wrapped with a div by default\n\t\t\t// Note: No protection if $html contains a stray </div>!\n\t\t\t$html = '<div>' . $html . '</div>';\n\t\t\t$ret .= '<!DOCTYPE html>';\n\t\t\t$content_type = 'text/html';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$ret .= '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">';\n\t\t\t$content_type = 'application/xhtml+xml';\n\t\t}\n\n\t\t$ret .= '<html><head>';\n\t\t$ret .= '<meta http-equiv=\"Content-Type\" content=\"' . $content_type . '; charset=utf-8\" />';\n\t\t$ret .= '</head><body>' . $html . '</body></html>';\n\t\treturn $ret;\n\t}\n\n\tpublic function replace_urls($document, $tag, $attributes)\n\t{\n\t\tif (!is_array($attributes))\n\t\t{\n\t\t\t$attributes = array($attributes);\n\t\t}\n\n\t\tif (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))\n\t\t{\n\t\t\t$elements = $document->getElementsByTagName($tag);\n\t\t\tforeach ($elements as $element)\n\t\t\t{\n\t\t\t\tforeach ($attributes as $attribute)\n\t\t\t\t{\n\t\t\t\t\tif ($element->hasAttribute($attribute))\n\t\t\t\t\t{\n\t\t\t\t\t\t$value = $this->registry->call('Misc', 'absolutize_url', array($element->getAttribute($attribute), $this->base));\n\t\t\t\t\t\tif ($value !== false)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$element->setAttribute($attribute, $value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic function do_strip_htmltags($match)\n\t{\n\t\tif ($this->encode_instead_of_strip)\n\t\t{\n\t\t\tif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))\n\t\t\t{\n\t\t\t\t$match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');\n\t\t\t\t$match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');\n\t\t\t\treturn \"&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');\n\t\t\t}\n\t\t}\n\t\telseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))\n\t\t{\n\t\t\treturn $match[4];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn '';\n\t\t}\n\t}\n\n\tprotected function strip_tag($tag, $document, $type)\n\t{\n\t\t$xpath = new DOMXPath($document);\n\t\t$elements = $xpath->query('body//' . $tag);\n\t\tif ($this->encode_instead_of_strip)\n\t\t{\n\t\t\tforeach ($elements as $element)\n\t\t\t{\n\t\t\t\t$fragment = $document->createDocumentFragment();\n\n\t\t\t\t// For elements which aren't script or style, include the tag itself\n\t\t\t\tif (!in_array($tag, array('script', 'style')))\n\t\t\t\t{\n\t\t\t\t\t$text = '<' . $tag;\n\t\t\t\t\tif ($element->hasAttributes())\n\t\t\t\t\t{\n\t\t\t\t\t\t$attrs = array();\n\t\t\t\t\t\tforeach ($element->attributes as $name => $attr)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$value = $attr->value;\n\n\t\t\t\t\t\t\t// In XHTML, empty values should never exist, so we repeat the value\n\t\t\t\t\t\t\tif (empty($value) && ($type & SIMPLEPIE_CONSTRUCT_XHTML))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$value = $name;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// For HTML, empty is fine\n\t\t\t\t\t\t\telseif (empty($value) && ($type & SIMPLEPIE_CONSTRUCT_HTML))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$attrs[] = $name;\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Standard attribute text\n\t\t\t\t\t\t\t$attrs[] = $name . '=\"' . $attr->value . '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$text .= ' ' . implode(' ', $attrs);\n\t\t\t\t\t}\n\t\t\t\t\t$text .= '>';\n\t\t\t\t\t$fragment->appendChild(new DOMText($text));\n\t\t\t\t}\n\n\t\t\t\t$number = $element->childNodes->length;\n\t\t\t\tfor ($i = $number; $i > 0; $i--)\n\t\t\t\t{\n\t\t\t\t\t$child = $element->childNodes->item(0);\n\t\t\t\t\t$fragment->appendChild($child);\n\t\t\t\t}\n\n\t\t\t\tif (!in_array($tag, array('script', 'style')))\n\t\t\t\t{\n\t\t\t\t\t$fragment->appendChild(new DOMText('</' . $tag . '>'));\n\t\t\t\t}\n\n\t\t\t\t$element->parentNode->replaceChild($fragment, $element);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\telseif (in_array($tag, array('script', 'style')))\n\t\t{\n\t\t\tforeach ($elements as $element)\n\t\t\t{\n\t\t\t\t$element->parentNode->removeChild($element);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tforeach ($elements as $element)\n\t\t\t{\n\t\t\t\t$fragment = $document->createDocumentFragment();\n\t\t\t\t$number = $element->childNodes->length;\n\t\t\t\tfor ($i = $number; $i > 0; $i--)\n\t\t\t\t{\n\t\t\t\t\t$child = $element->childNodes->item(0);\n\t\t\t\t\t$fragment->appendChild($child);\n\t\t\t\t}\n\n\t\t\t\t$element->parentNode->replaceChild($fragment, $element);\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected function strip_attr($attrib, $document)\n\t{\n\t\t$xpath = new DOMXPath($document);\n\t\t$elements = $xpath->query('//*[@' . $attrib . ']');\n\n\t\tforeach ($elements as $element)\n\t\t{\n\t\t\t$element->removeAttribute($attrib);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/Source.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * Handles `<atom:source>`\n *\n * Used by {@see SimplePie_Item::get_source()}\n *\n * This class can be overloaded with {@see SimplePie::set_source_class()}\n *\n * @package SimplePie\n * @subpackage API\n */\nclass SimplePie_Source\n{\n\tvar $item;\n\tvar $data = array();\n\tprotected $registry;\n\n\tpublic function __construct($item, $data)\n\t{\n\t\t$this->item = $item;\n\t\t$this->data = $data;\n\t}\n\n\tpublic function set_registry(SimplePie_Registry $registry)\n\t{\n\t\t$this->registry = $registry;\n\t}\n\n\tpublic function __toString()\n\t{\n\t\treturn md5(serialize($this->data));\n\t}\n\n\tpublic function get_source_tags($namespace, $tag)\n\t{\n\t\tif (isset($this->data['child'][$namespace][$tag]))\n\t\t{\n\t\t\treturn $this->data['child'][$namespace][$tag];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_base($element = array())\n\t{\n\t\treturn $this->item->get_base($element);\n\t}\n\n\tpublic function sanitize($data, $type, $base = '')\n\t{\n\t\treturn $this->item->sanitize($data, $type, $base);\n\t}\n\n\tpublic function get_item()\n\t{\n\t\treturn $this->item;\n\t}\n\n\tpublic function get_title()\n\t{\n\t\tif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_category($key = 0)\n\t{\n\t\t$categories = $this->get_categories();\n\t\tif (isset($categories[$key]))\n\t\t{\n\t\t\treturn $categories[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_categories()\n\t{\n\t\t$categories = array();\n\n\t\tforeach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)\n\t\t{\n\t\t\t$term = null;\n\t\t\t$scheme = null;\n\t\t\t$label = null;\n\t\t\tif (isset($category['attribs']['']['term']))\n\t\t\t{\n\t\t\t\t$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($category['attribs']['']['scheme']))\n\t\t\t{\n\t\t\t\t$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($category['attribs']['']['label']))\n\t\t\t{\n\t\t\t\t$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\t$categories[] = $this->registry->create('Category', array($term, $scheme, $label));\n\t\t}\n\t\tforeach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)\n\t\t{\n\t\t\t// This is really the label, but keep this as the term also for BC.\n\t\t\t// Label will also work on retrieving because that falls back to term.\n\t\t\t$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\tif (isset($category['attribs']['']['domain']))\n\t\t\t{\n\t\t\t\t$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$scheme = null;\n\t\t\t}\n\t\t\t$categories[] = $this->registry->create('Category', array($term, $scheme, null));\n\t\t}\n\t\tforeach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)\n\t\t{\n\t\t\t$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\t\tforeach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)\n\t\t{\n\t\t\t$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\n\t\tif (!empty($categories))\n\t\t{\n\t\t\treturn array_unique($categories);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_author($key = 0)\n\t{\n\t\t$authors = $this->get_authors();\n\t\tif (isset($authors[$key]))\n\t\t{\n\t\t\treturn $authors[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_authors()\n\t{\n\t\t$authors = array();\n\t\tforeach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)\n\t\t{\n\t\t\t$name = null;\n\t\t\t$uri = null;\n\t\t\t$email = null;\n\t\t\tif (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))\n\t\t\t{\n\t\t\t\t$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))\n\t\t\t{\n\t\t\t\t$uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));\n\t\t\t}\n\t\t\tif (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))\n\t\t\t{\n\t\t\t\t$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif ($name !== null || $email !== null || $uri !== null)\n\t\t\t{\n\t\t\t\t$authors[] = $this->registry->create('Author', array($name, $uri, $email));\n\t\t\t}\n\t\t}\n\t\tif ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))\n\t\t{\n\t\t\t$name = null;\n\t\t\t$url = null;\n\t\t\t$email = null;\n\t\t\tif (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))\n\t\t\t{\n\t\t\t\t$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))\n\t\t\t{\n\t\t\t\t$url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));\n\t\t\t}\n\t\t\tif (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))\n\t\t\t{\n\t\t\t\t$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif ($name !== null || $email !== null || $url !== null)\n\t\t\t{\n\t\t\t\t$authors[] = $this->registry->create('Author', array($name, $url, $email));\n\t\t\t}\n\t\t}\n\t\tforeach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)\n\t\t{\n\t\t\t$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\t\tforeach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)\n\t\t{\n\t\t\t$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\t\tforeach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)\n\t\t{\n\t\t\t$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\n\t\tif (!empty($authors))\n\t\t{\n\t\t\treturn array_unique($authors);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_contributor($key = 0)\n\t{\n\t\t$contributors = $this->get_contributors();\n\t\tif (isset($contributors[$key]))\n\t\t{\n\t\t\treturn $contributors[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_contributors()\n\t{\n\t\t$contributors = array();\n\t\tforeach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)\n\t\t{\n\t\t\t$name = null;\n\t\t\t$uri = null;\n\t\t\t$email = null;\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))\n\t\t\t{\n\t\t\t\t$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))\n\t\t\t{\n\t\t\t\t$uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));\n\t\t\t}\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))\n\t\t\t{\n\t\t\t\t$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif ($name !== null || $email !== null || $uri !== null)\n\t\t\t{\n\t\t\t\t$contributors[] = $this->registry->create('Author', array($name, $uri, $email));\n\t\t\t}\n\t\t}\n\t\tforeach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)\n\t\t{\n\t\t\t$name = null;\n\t\t\t$url = null;\n\t\t\t$email = null;\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))\n\t\t\t{\n\t\t\t\t$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))\n\t\t\t{\n\t\t\t\t$url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));\n\t\t\t}\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))\n\t\t\t{\n\t\t\t\t$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif ($name !== null || $email !== null || $url !== null)\n\t\t\t{\n\t\t\t\t$contributors[] = $this->registry->create('Author', array($name, $url, $email));\n\t\t\t}\n\t\t}\n\n\t\tif (!empty($contributors))\n\t\t{\n\t\t\treturn array_unique($contributors);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_link($key = 0, $rel = 'alternate')\n\t{\n\t\t$links = $this->get_links($rel);\n\t\tif (isset($links[$key]))\n\t\t{\n\t\t\treturn $links[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Added for parity between the parent-level and the item/entry-level.\n\t */\n\tpublic function get_permalink()\n\t{\n\t\treturn $this->get_link(0);\n\t}\n\n\tpublic function get_links($rel = 'alternate')\n\t{\n\t\tif (!isset($this->data['links']))\n\t\t{\n\t\t\t$this->data['links'] = array();\n\t\t\tif ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))\n\t\t\t{\n\t\t\t\tforeach ($links as $link)\n\t\t\t\t{\n\t\t\t\t\tif (isset($link['attribs']['']['href']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';\n\t\t\t\t\t\t$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))\n\t\t\t{\n\t\t\t\tforeach ($links as $link)\n\t\t\t\t{\n\t\t\t\t\tif (isset($link['attribs']['']['href']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';\n\t\t\t\t\t\t$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))\n\t\t\t{\n\t\t\t\t$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));\n\t\t\t}\n\t\t\tif ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))\n\t\t\t{\n\t\t\t\t$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));\n\t\t\t}\n\t\t\tif ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))\n\t\t\t{\n\t\t\t\t$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));\n\t\t\t}\n\n\t\t\t$keys = array_keys($this->data['links']);\n\t\t\tforeach ($keys as $key)\n\t\t\t{\n\t\t\t\tif ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))\n\t\t\t\t{\n\t\t\t\t\tif (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);\n\t\t\t\t\t\t$this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)\n\t\t\t\t{\n\t\t\t\t\t$this->data['links'][substr($key, 41)] =& $this->data['links'][$key];\n\t\t\t\t}\n\t\t\t\t$this->data['links'][$key] = array_unique($this->data['links'][$key]);\n\t\t\t}\n\t\t}\n\n\t\tif (isset($this->data['links'][$rel]))\n\t\t{\n\t\t\treturn $this->data['links'][$rel];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_description()\n\t{\n\t\tif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_copyright()\n\t{\n\t\tif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_language()\n\t{\n\t\tif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif (isset($this->data['xml_lang']))\n\t\t{\n\t\t\treturn $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_latitude()\n\t{\n\t\tif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))\n\t\t{\n\t\t\treturn (float) $return[0]['data'];\n\t\t}\n\t\telseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\\.[0-9]+)) ((?:-)?[0-9]+(?:\\.[0-9]+))$/', trim($return[0]['data']), $match))\n\t\t{\n\t\t\treturn (float) $match[1];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_longitude()\n\t{\n\t\tif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))\n\t\t{\n\t\t\treturn (float) $return[0]['data'];\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))\n\t\t{\n\t\t\treturn (float) $return[0]['data'];\n\t\t}\n\t\telseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\\.[0-9]+)) ((?:-)?[0-9]+(?:\\.[0-9]+))$/', trim($return[0]['data']), $match))\n\t\t{\n\t\t\treturn (float) $match[2];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_image_url()\n\t{\n\t\tif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/XML/Declaration/Parser.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n\n/**\n * Parses the XML Declaration\n *\n * @package SimplePie\n * @subpackage Parsing\n */\nclass SimplePie_XML_Declaration_Parser\n{\n\t/**\n\t * XML Version\n\t *\n\t * @access public\n\t * @var string\n\t */\n\tvar $version = '1.0';\n\n\t/**\n\t * Encoding\n\t *\n\t * @access public\n\t * @var string\n\t */\n\tvar $encoding = 'UTF-8';\n\n\t/**\n\t * Standalone\n\t *\n\t * @access public\n\t * @var bool\n\t */\n\tvar $standalone = false;\n\n\t/**\n\t * Current state of the state machine\n\t *\n\t * @access private\n\t * @var string\n\t */\n\tvar $state = 'before_version_name';\n\n\t/**\n\t * Input data\n\t *\n\t * @access private\n\t * @var string\n\t */\n\tvar $data = '';\n\n\t/**\n\t * Input data length (to avoid calling strlen() everytime this is needed)\n\t *\n\t * @access private\n\t * @var int\n\t */\n\tvar $data_length = 0;\n\n\t/**\n\t * Current position of the pointer\n\t *\n\t * @var int\n\t * @access private\n\t */\n\tvar $position = 0;\n\n\t/**\n\t * Create an instance of the class with the input data\n\t *\n\t * @access public\n\t * @param string $data Input data\n\t */\n\tpublic function __construct($data)\n\t{\n\t\t$this->data = $data;\n\t\t$this->data_length = strlen($this->data);\n\t}\n\n\t/**\n\t * Parse the input data\n\t *\n\t * @access public\n\t * @return bool true on success, false on failure\n\t */\n\tpublic function parse()\n\t{\n\t\twhile ($this->state && $this->state !== 'emit' && $this->has_data())\n\t\t{\n\t\t\t$state = $this->state;\n\t\t\t$this->$state();\n\t\t}\n\t\t$this->data = '';\n\t\tif ($this->state === 'emit')\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->version = '';\n\t\t\t$this->encoding = '';\n\t\t\t$this->standalone = '';\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Check whether there is data beyond the pointer\n\t *\n\t * @access private\n\t * @return bool true if there is further data, false if not\n\t */\n\tpublic function has_data()\n\t{\n\t\treturn (bool) ($this->position < $this->data_length);\n\t}\n\n\t/**\n\t * Advance past any whitespace\n\t *\n\t * @return int Number of whitespace characters passed\n\t */\n\tpublic function skip_whitespace()\n\t{\n\t\t$whitespace = strspn($this->data, \"\\x09\\x0A\\x0D\\x20\", $this->position);\n\t\t$this->position += $whitespace;\n\t\treturn $whitespace;\n\t}\n\n\t/**\n\t * Read value\n\t */\n\tpublic function get_value()\n\t{\n\t\t$quote = substr($this->data, $this->position, 1);\n\t\tif ($quote === '\"' || $quote === \"'\")\n\t\t{\n\t\t\t$this->position++;\n\t\t\t$len = strcspn($this->data, $quote, $this->position);\n\t\t\tif ($this->has_data())\n\t\t\t{\n\t\t\t\t$value = substr($this->data, $this->position, $len);\n\t\t\t\t$this->position += $len + 1;\n\t\t\t\treturn $value;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic function before_version_name()\n\t{\n\t\tif ($this->skip_whitespace())\n\t\t{\n\t\t\t$this->state = 'version_name';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = false;\n\t\t}\n\t}\n\n\tpublic function version_name()\n\t{\n\t\tif (substr($this->data, $this->position, 7) === 'version')\n\t\t{\n\t\t\t$this->position += 7;\n\t\t\t$this->skip_whitespace();\n\t\t\t$this->state = 'version_equals';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = false;\n\t\t}\n\t}\n\n\tpublic function version_equals()\n\t{\n\t\tif (substr($this->data, $this->position, 1) === '=')\n\t\t{\n\t\t\t$this->position++;\n\t\t\t$this->skip_whitespace();\n\t\t\t$this->state = 'version_value';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = false;\n\t\t}\n\t}\n\n\tpublic function version_value()\n\t{\n\t\tif ($this->version = $this->get_value())\n\t\t{\n\t\t\t$this->skip_whitespace();\n\t\t\tif ($this->has_data())\n\t\t\t{\n\t\t\t\t$this->state = 'encoding_name';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->state = 'emit';\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = false;\n\t\t}\n\t}\n\n\tpublic function encoding_name()\n\t{\n\t\tif (substr($this->data, $this->position, 8) === 'encoding')\n\t\t{\n\t\t\t$this->position += 8;\n\t\t\t$this->skip_whitespace();\n\t\t\t$this->state = 'encoding_equals';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = 'standalone_name';\n\t\t}\n\t}\n\n\tpublic function encoding_equals()\n\t{\n\t\tif (substr($this->data, $this->position, 1) === '=')\n\t\t{\n\t\t\t$this->position++;\n\t\t\t$this->skip_whitespace();\n\t\t\t$this->state = 'encoding_value';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = false;\n\t\t}\n\t}\n\n\tpublic function encoding_value()\n\t{\n\t\tif ($this->encoding = $this->get_value())\n\t\t{\n\t\t\t$this->skip_whitespace();\n\t\t\tif ($this->has_data())\n\t\t\t{\n\t\t\t\t$this->state = 'standalone_name';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->state = 'emit';\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = false;\n\t\t}\n\t}\n\n\tpublic function standalone_name()\n\t{\n\t\tif (substr($this->data, $this->position, 10) === 'standalone')\n\t\t{\n\t\t\t$this->position += 10;\n\t\t\t$this->skip_whitespace();\n\t\t\t$this->state = 'standalone_equals';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = false;\n\t\t}\n\t}\n\n\tpublic function standalone_equals()\n\t{\n\t\tif (substr($this->data, $this->position, 1) === '=')\n\t\t{\n\t\t\t$this->position++;\n\t\t\t$this->skip_whitespace();\n\t\t\t$this->state = 'standalone_value';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = false;\n\t\t}\n\t}\n\n\tpublic function standalone_value()\n\t{\n\t\tif ($standalone = $this->get_value())\n\t\t{\n\t\t\tswitch ($standalone)\n\t\t\t{\n\t\t\t\tcase 'yes':\n\t\t\t\t\t$this->standalone = true;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'no':\n\t\t\t\t\t$this->standalone = false;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\t$this->state = false;\n\t\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$this->skip_whitespace();\n\t\t\tif ($this->has_data())\n\t\t\t{\n\t\t\t\t$this->state = false;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->state = 'emit';\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->state = false;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie/gzdecode.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n\n/**\n * Decode 'gzip' encoded HTTP data\n *\n * @package SimplePie\n * @subpackage HTTP\n * @link http://www.gzip.org/format.txt\n */\nclass SimplePie_gzdecode\n{\n\t/**\n\t * Compressed data\n\t *\n\t * @access private\n\t * @var string\n\t * @see gzdecode::$data\n\t */\n\tvar $compressed_data;\n\n\t/**\n\t * Size of compressed data\n\t *\n\t * @access private\n\t * @var int\n\t */\n\tvar $compressed_size;\n\n\t/**\n\t * Minimum size of a valid gzip string\n\t *\n\t * @access private\n\t * @var int\n\t */\n\tvar $min_compressed_size = 18;\n\n\t/**\n\t * Current position of pointer\n\t *\n\t * @access private\n\t * @var int\n\t */\n\tvar $position = 0;\n\n\t/**\n\t * Flags (FLG)\n\t *\n\t * @access private\n\t * @var int\n\t */\n\tvar $flags;\n\n\t/**\n\t * Uncompressed data\n\t *\n\t * @access public\n\t * @see gzdecode::$compressed_data\n\t * @var string\n\t */\n\tvar $data;\n\n\t/**\n\t * Modified time\n\t *\n\t * @access public\n\t * @var int\n\t */\n\tvar $MTIME;\n\n\t/**\n\t * Extra Flags\n\t *\n\t * @access public\n\t * @var int\n\t */\n\tvar $XFL;\n\n\t/**\n\t * Operating System\n\t *\n\t * @access public\n\t * @var int\n\t */\n\tvar $OS;\n\n\t/**\n\t * Subfield ID 1\n\t *\n\t * @access public\n\t * @see gzdecode::$extra_field\n\t * @see gzdecode::$SI2\n\t * @var string\n\t */\n\tvar $SI1;\n\n\t/**\n\t * Subfield ID 2\n\t *\n\t * @access public\n\t * @see gzdecode::$extra_field\n\t * @see gzdecode::$SI1\n\t * @var string\n\t */\n\tvar $SI2;\n\n\t/**\n\t * Extra field content\n\t *\n\t * @access public\n\t * @see gzdecode::$SI1\n\t * @see gzdecode::$SI2\n\t * @var string\n\t */\n\tvar $extra_field;\n\n\t/**\n\t * Original filename\n\t *\n\t * @access public\n\t * @var string\n\t */\n\tvar $filename;\n\n\t/**\n\t * Human readable comment\n\t *\n\t * @access public\n\t * @var string\n\t */\n\tvar $comment;\n\n\t/**\n\t * Don't allow anything to be set\n\t *\n\t * @param string $name\n\t * @param mixed $value\n\t */\n\tpublic function __set($name, $value)\n\t{\n\t\ttrigger_error(\"Cannot write property $name\", E_USER_ERROR);\n\t}\n\n\t/**\n\t * Set the compressed string and related properties\n\t *\n\t * @param string $data\n\t */\n\tpublic function __construct($data)\n\t{\n\t\t$this->compressed_data = $data;\n\t\t$this->compressed_size = strlen($data);\n\t}\n\n\t/**\n\t * Decode the GZIP stream\n\t *\n\t * @return bool Successfulness\n\t */\n\tpublic function parse()\n\t{\n\t\tif ($this->compressed_size >= $this->min_compressed_size)\n\t\t{\n\t\t\t// Check ID1, ID2, and CM\n\t\t\tif (substr($this->compressed_data, 0, 3) !== \"\\x1F\\x8B\\x08\")\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Get the FLG (FLaGs)\n\t\t\t$this->flags = ord($this->compressed_data[3]);\n\n\t\t\t// FLG bits above (1 << 4) are reserved\n\t\t\tif ($this->flags > 0x1F)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Advance the pointer after the above\n\t\t\t$this->position += 4;\n\n\t\t\t// MTIME\n\t\t\t$mtime = substr($this->compressed_data, $this->position, 4);\n\t\t\t// Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness\n\t\t\tif (current(unpack('S', \"\\x00\\x01\")) === 1)\n\t\t\t{\n\t\t\t\t$mtime = strrev($mtime);\n\t\t\t}\n\t\t\t$this->MTIME = current(unpack('l', $mtime));\n\t\t\t$this->position += 4;\n\n\t\t\t// Get the XFL (eXtra FLags)\n\t\t\t$this->XFL = ord($this->compressed_data[$this->position++]);\n\n\t\t\t// Get the OS (Operating System)\n\t\t\t$this->OS = ord($this->compressed_data[$this->position++]);\n\n\t\t\t// Parse the FEXTRA\n\t\t\tif ($this->flags & 4)\n\t\t\t{\n\t\t\t\t// Read subfield IDs\n\t\t\t\t$this->SI1 = $this->compressed_data[$this->position++];\n\t\t\t\t$this->SI2 = $this->compressed_data[$this->position++];\n\n\t\t\t\t// SI2 set to zero is reserved for future use\n\t\t\t\tif ($this->SI2 === \"\\x00\")\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Get the length of the extra field\n\t\t\t\t$len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));\n\t\t\t\t$this->position += 2;\n\n\t\t\t\t// Check the length of the string is still valid\n\t\t\t\t$this->min_compressed_size += $len + 4;\n\t\t\t\tif ($this->compressed_size >= $this->min_compressed_size)\n\t\t\t\t{\n\t\t\t\t\t// Set the extra field to the given data\n\t\t\t\t\t$this->extra_field = substr($this->compressed_data, $this->position, $len);\n\t\t\t\t\t$this->position += $len;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Parse the FNAME\n\t\t\tif ($this->flags & 8)\n\t\t\t{\n\t\t\t\t// Get the length of the filename\n\t\t\t\t$len = strcspn($this->compressed_data, \"\\x00\", $this->position);\n\n\t\t\t\t// Check the length of the string is still valid\n\t\t\t\t$this->min_compressed_size += $len + 1;\n\t\t\t\tif ($this->compressed_size >= $this->min_compressed_size)\n\t\t\t\t{\n\t\t\t\t\t// Set the original filename to the given string\n\t\t\t\t\t$this->filename = substr($this->compressed_data, $this->position, $len);\n\t\t\t\t\t$this->position += $len + 1;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Parse the FCOMMENT\n\t\t\tif ($this->flags & 16)\n\t\t\t{\n\t\t\t\t// Get the length of the comment\n\t\t\t\t$len = strcspn($this->compressed_data, \"\\x00\", $this->position);\n\n\t\t\t\t// Check the length of the string is still valid\n\t\t\t\t$this->min_compressed_size += $len + 1;\n\t\t\t\tif ($this->compressed_size >= $this->min_compressed_size)\n\t\t\t\t{\n\t\t\t\t\t// Set the original comment to the given string\n\t\t\t\t\t$this->comment = substr($this->compressed_data, $this->position, $len);\n\t\t\t\t\t$this->position += $len + 1;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Parse the FHCRC\n\t\t\tif ($this->flags & 2)\n\t\t\t{\n\t\t\t\t// Check the length of the string is still valid\n\t\t\t\t$this->min_compressed_size += $len + 2;\n\t\t\t\tif ($this->compressed_size >= $this->min_compressed_size)\n\t\t\t\t{\n\t\t\t\t\t// Read the CRC\n\t\t\t\t\t$crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));\n\n\t\t\t\t\t// Check the CRC matches\n\t\t\t\t\tif ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->position += 2;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Decompress the actual data\n\t\t\tif (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->position = $this->compressed_size - 8;\n\t\t\t}\n\n\t\t\t// Check CRC of data\n\t\t\t$crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));\n\t\t\t$this->position += 4;\n\t\t\t/*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}*/\n\n\t\t\t// Check ISIZE of data\n\t\t\t$isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));\n\t\t\t$this->position += 4;\n\t\t\tif (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Wow, against all odds, we've actually got a valid gzip string\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "libraries/simplepie/library/SimplePie.php",
    "content": "<?php\n/**\n * SimplePie\n *\n * A PHP-Based RSS and Atom Feed Framework.\n * Takes the hard work out of managing a complete RSS/Atom solution.\n *\n * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification, are\n * permitted provided that the following conditions are met:\n *\n * \t* Redistributions of source code must retain the above copyright notice, this list of\n * \t  conditions and the following disclaimer.\n *\n * \t* Redistributions in binary form must reproduce the above copyright notice, this list\n * \t  of conditions and the following disclaimer in the documentation and/or other materials\n * \t  provided with the distribution.\n *\n * \t* Neither the name of the SimplePie Team nor the names of its contributors may be used\n * \t  to endorse or promote products derived from this software without specific prior\n * \t  written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS\n * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * @package SimplePie\n * @version 1.3.1\n * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue\n * @author Ryan Parman\n * @author Geoffrey Sneddon\n * @author Ryan McCue\n * @link http://simplepie.org/ SimplePie\n * @license http://www.opensource.org/licenses/bsd-license.php BSD License\n */\n\n/**\n * SimplePie Name\n */\ndefine('SIMPLEPIE_NAME', 'SimplePie');\n\n/**\n * SimplePie Version\n */\ndefine('SIMPLEPIE_VERSION', '1.3.1');\n\n/**\n * SimplePie Build\n * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::get_build() only every load of simplepie.inc)\n */\ndefine('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::get_build()));\n\n/**\n * SimplePie Website URL\n */\ndefine('SIMPLEPIE_URL', 'http://localhost');\n\n/**\n * SimplePie Useragent\n * @see SimplePie::set_useragent()\n */\ndefine('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);\n\n/**\n * SimplePie Linkback\n */\ndefine('SIMPLEPIE_LINKBACK', '<a href=\"' . SIMPLEPIE_URL . '\" title=\"' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '\">' . SIMPLEPIE_NAME . '</a>');\n\n/**\n * No Autodiscovery\n * @see SimplePie::set_autodiscovery_level()\n */\ndefine('SIMPLEPIE_LOCATOR_NONE', 0);\n\n/**\n * Feed Link Element Autodiscovery\n * @see SimplePie::set_autodiscovery_level()\n */\ndefine('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);\n\n/**\n * Local Feed Extension Autodiscovery\n * @see SimplePie::set_autodiscovery_level()\n */\ndefine('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);\n\n/**\n * Local Feed Body Autodiscovery\n * @see SimplePie::set_autodiscovery_level()\n */\ndefine('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);\n\n/**\n * Remote Feed Extension Autodiscovery\n * @see SimplePie::set_autodiscovery_level()\n */\ndefine('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);\n\n/**\n * Remote Feed Body Autodiscovery\n * @see SimplePie::set_autodiscovery_level()\n */\ndefine('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);\n\n/**\n * All Feed Autodiscovery\n * @see SimplePie::set_autodiscovery_level()\n */\ndefine('SIMPLEPIE_LOCATOR_ALL', 31);\n\n/**\n * No known feed type\n */\ndefine('SIMPLEPIE_TYPE_NONE', 0);\n\n/**\n * RSS 0.90\n */\ndefine('SIMPLEPIE_TYPE_RSS_090', 1);\n\n/**\n * RSS 0.91 (Netscape)\n */\ndefine('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);\n\n/**\n * RSS 0.91 (Userland)\n */\ndefine('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);\n\n/**\n * RSS 0.91 (both Netscape and Userland)\n */\ndefine('SIMPLEPIE_TYPE_RSS_091', 6);\n\n/**\n * RSS 0.92\n */\ndefine('SIMPLEPIE_TYPE_RSS_092', 8);\n\n/**\n * RSS 0.93\n */\ndefine('SIMPLEPIE_TYPE_RSS_093', 16);\n\n/**\n * RSS 0.94\n */\ndefine('SIMPLEPIE_TYPE_RSS_094', 32);\n\n/**\n * RSS 1.0\n */\ndefine('SIMPLEPIE_TYPE_RSS_10', 64);\n\n/**\n * RSS 2.0\n */\ndefine('SIMPLEPIE_TYPE_RSS_20', 128);\n\n/**\n * RDF-based RSS\n */\ndefine('SIMPLEPIE_TYPE_RSS_RDF', 65);\n\n/**\n * Non-RDF-based RSS (truly intended as syndication format)\n */\ndefine('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);\n\n/**\n * All RSS\n */\ndefine('SIMPLEPIE_TYPE_RSS_ALL', 255);\n\n/**\n * Atom 0.3\n */\ndefine('SIMPLEPIE_TYPE_ATOM_03', 256);\n\n/**\n * Atom 1.0\n */\ndefine('SIMPLEPIE_TYPE_ATOM_10', 512);\n\n/**\n * All Atom\n */\ndefine('SIMPLEPIE_TYPE_ATOM_ALL', 768);\n\n/**\n * All feed types\n */\ndefine('SIMPLEPIE_TYPE_ALL', 1023);\n\n/**\n * No construct\n */\ndefine('SIMPLEPIE_CONSTRUCT_NONE', 0);\n\n/**\n * Text construct\n */\ndefine('SIMPLEPIE_CONSTRUCT_TEXT', 1);\n\n/**\n * HTML construct\n */\ndefine('SIMPLEPIE_CONSTRUCT_HTML', 2);\n\n/**\n * XHTML construct\n */\ndefine('SIMPLEPIE_CONSTRUCT_XHTML', 4);\n\n/**\n * base64-encoded construct\n */\ndefine('SIMPLEPIE_CONSTRUCT_BASE64', 8);\n\n/**\n * IRI construct\n */\ndefine('SIMPLEPIE_CONSTRUCT_IRI', 16);\n\n/**\n * A construct that might be HTML\n */\ndefine('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);\n\n/**\n * All constructs\n */\ndefine('SIMPLEPIE_CONSTRUCT_ALL', 63);\n\n/**\n * Don't change case\n */\ndefine('SIMPLEPIE_SAME_CASE', 1);\n\n/**\n * Change to lowercase\n */\ndefine('SIMPLEPIE_LOWERCASE', 2);\n\n/**\n * Change to uppercase\n */\ndefine('SIMPLEPIE_UPPERCASE', 4);\n\n/**\n * PCRE for HTML attributes\n */\ndefine('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\\x09\\x0A\\x0B\\x0C\\x0D\\x20]+[^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x2F\\x3E][^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x2F\\x3D\\x3E]*(?:[\\x09\\x0A\\x0B\\x0C\\x0D\\x20]*=[\\x09\\x0A\\x0B\\x0C\\x0D\\x20]*(?:\"(?:[^\"]*)\"|\\'(?:[^\\']*)\\'|(?:[^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x22\\x27\\x3E][^\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\x3E]*)?))?)*)[\\x09\\x0A\\x0B\\x0C\\x0D\\x20]*');\n\n/**\n * PCRE for XML attributes\n */\ndefine('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\\s+(?:(?:[^\\s:]+:)?[^\\s:]+)\\s*=\\s*(?:\"(?:[^\"]*)\"|\\'(?:[^\\']*)\\'))*)\\s*');\n\n/**\n * XML Namespace\n */\ndefine('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');\n\n/**\n * Atom 1.0 Namespace\n */\ndefine('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');\n\n/**\n * Atom 0.3 Namespace\n */\ndefine('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');\n\n/**\n * RDF Namespace\n */\ndefine('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');\n\n/**\n * RSS 0.90 Namespace\n */\ndefine('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');\n\n/**\n * RSS 1.0 Namespace\n */\ndefine('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');\n\n/**\n * RSS 1.0 Content Module Namespace\n */\ndefine('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');\n\n/**\n * RSS 2.0 Namespace\n * (Stupid, I know, but I'm certain it will confuse people less with support.)\n */\ndefine('SIMPLEPIE_NAMESPACE_RSS_20', '');\n\n/**\n * DC 1.0 Namespace\n */\ndefine('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');\n\n/**\n * DC 1.1 Namespace\n */\ndefine('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');\n\n/**\n * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace\n */\ndefine('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');\n\n/**\n * GeoRSS Namespace\n */\ndefine('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');\n\n/**\n * Media RSS Namespace\n */\ndefine('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');\n\n/**\n * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec.\n */\ndefine('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');\n\n/**\n * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5.\n */\ndefine('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss');\n\n/**\n * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace.\n */\ndefine('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/');\n\n/**\n * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace.\n */\ndefine('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss');\n\n/**\n * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL.\n */\ndefine('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/');\n\n/**\n * iTunes RSS Namespace\n */\ndefine('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');\n\n/**\n * XHTML Namespace\n */\ndefine('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');\n\n/**\n * IANA Link Relations Registry\n */\ndefine('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');\n\n/**\n * No file source\n */\ndefine('SIMPLEPIE_FILE_SOURCE_NONE', 0);\n\n/**\n * Remote file source\n */\ndefine('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);\n\n/**\n * Local file source\n */\ndefine('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);\n\n/**\n * fsockopen() file source\n */\ndefine('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);\n\n/**\n * cURL file source\n */\ndefine('SIMPLEPIE_FILE_SOURCE_CURL', 8);\n\n/**\n * file_get_contents() file source\n */\ndefine('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);\n\n\n\n/**\n * SimplePie\n *\n * @package SimplePie\n * @subpackage API\n */\nclass SimplePie\n{\n\t/**\n\t * @var array Raw data\n\t * @access private\n\t */\n\tpublic $data = array();\n\n\t/**\n\t * @var mixed Error string\n\t * @access private\n\t */\n\tpublic $error;\n\n\t/**\n\t * @var object Instance of SimplePie_Sanitize (or other class)\n\t * @see SimplePie::set_sanitize_class()\n\t * @access private\n\t */\n\tpublic $sanitize;\n\n\t/**\n\t * @var string SimplePie Useragent\n\t * @see SimplePie::set_useragent()\n\t * @access private\n\t */\n\tpublic $useragent = SIMPLEPIE_USERAGENT;\n\n\t/**\n\t * @var string Feed URL\n\t * @see SimplePie::set_feed_url()\n\t * @access private\n\t */\n\tpublic $feed_url;\n\n\t/**\n\t * @var object Instance of SimplePie_File to use as a feed\n\t * @see SimplePie::set_file()\n\t * @access private\n\t */\n\tpublic $file;\n\n\t/**\n\t * @var string Raw feed data\n\t * @see SimplePie::set_raw_data()\n\t * @access private\n\t */\n\tpublic $raw_data;\n\n\t/**\n\t * @var int Timeout for fetching remote files\n\t * @see SimplePie::set_timeout()\n\t * @access private\n\t */\n\tpublic $timeout = 10;\n\n\t/**\n\t * @var bool Forces fsockopen() to be used for remote files instead\n\t * of cURL, even if a new enough version is installed\n\t * @see SimplePie::force_fsockopen()\n\t * @access private\n\t */\n\tpublic $force_fsockopen = false;\n\n\t/**\n\t * @var bool Force the given data/URL to be treated as a feed no matter what\n\t * it appears like\n\t * @see SimplePie::force_feed()\n\t * @access private\n\t */\n\tpublic $force_feed = false;\n\n\t/**\n\t * @var bool Enable/Disable Caching\n\t * @see SimplePie::enable_cache()\n\t * @access private\n\t */\n\tpublic $cache = true;\n\n\t/**\n\t * @var int Cache duration (in seconds)\n\t * @see SimplePie::set_cache_duration()\n\t * @access private\n\t */\n\tpublic $cache_duration = 3600;\n\n\t/**\n\t * @var int Auto-discovery cache duration (in seconds)\n\t * @see SimplePie::set_autodiscovery_cache_duration()\n\t * @access private\n\t */\n\tpublic $autodiscovery_cache_duration = 604800; // 7 Days.\n\n\t/**\n\t * @var string Cache location (relative to executing script)\n\t * @see SimplePie::set_cache_location()\n\t * @access private\n\t */\n\tpublic $cache_location = './cache';\n\n\t/**\n\t * @var string Function that creates the cache filename\n\t * @see SimplePie::set_cache_name_function()\n\t * @access private\n\t */\n\tpublic $cache_name_function = 'md5';\n\n\t/**\n\t * @var bool Reorder feed by date descending\n\t * @see SimplePie::enable_order_by_date()\n\t * @access private\n\t */\n\tpublic $order_by_date = true;\n\n\t/**\n\t * @var mixed Force input encoding to be set to the follow value\n\t * (false, or anything type-cast to false, disables this feature)\n\t * @see SimplePie::set_input_encoding()\n\t * @access private\n\t */\n\tpublic $input_encoding = false;\n\n\t/**\n\t * @var int Feed Autodiscovery Level\n\t * @see SimplePie::set_autodiscovery_level()\n\t * @access private\n\t */\n\tpublic $autodiscovery = SIMPLEPIE_LOCATOR_ALL;\n\n\t/**\n\t * Class registry object\n\t *\n\t * @var SimplePie_Registry\n\t */\n\tpublic $registry;\n\n\t/**\n\t * @var int Maximum number of feeds to check with autodiscovery\n\t * @see SimplePie::set_max_checked_feeds()\n\t * @access private\n\t */\n\tpublic $max_checked_feeds = 10;\n\n\t/**\n\t * @var array All the feeds found during the autodiscovery process\n\t * @see SimplePie::get_all_discovered_feeds()\n\t * @access private\n\t */\n\tpublic $all_discovered_feeds = array();\n\n\t/**\n\t * @var string Web-accessible path to the handler_image.php file.\n\t * @see SimplePie::set_image_handler()\n\t * @access private\n\t */\n\tpublic $image_handler = '';\n\n\t/**\n\t * @var array Stores the URLs when multiple feeds are being initialized.\n\t * @see SimplePie::set_feed_url()\n\t * @access private\n\t */\n\tpublic $multifeed_url = array();\n\n\t/**\n\t * @var array Stores SimplePie objects when multiple feeds initialized.\n\t * @access private\n\t */\n\tpublic $multifeed_objects = array();\n\n\t/**\n\t * @var array Stores the get_object_vars() array for use with multifeeds.\n\t * @see SimplePie::set_feed_url()\n\t * @access private\n\t */\n\tpublic $config_settings = null;\n\n\t/**\n\t * @var integer Stores the number of items to return per-feed with multifeeds.\n\t * @see SimplePie::set_item_limit()\n\t * @access private\n\t */\n\tpublic $item_limit = 0;\n\n\t/**\n\t * @var array Stores the default attributes to be stripped by strip_attributes().\n\t * @see SimplePie::strip_attributes()\n\t * @access private\n\t */\n\tpublic $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');\n\n\t/**\n\t * @var array Stores the default tags to be stripped by strip_htmltags().\n\t * @see SimplePie::strip_htmltags()\n\t * @access private\n\t */\n\tpublic $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');\n\n\t/**\n\t * The SimplePie class contains feed level data and options\n\t *\n\t * To use SimplePie, create the SimplePie object with no parameters. You can\n\t * then set configuration options using the provided methods. After setting\n\t * them, you must initialise the feed using $feed->init(). At that point the\n\t * object's methods and properties will be available to you.\n\t *\n\t * Previously, it was possible to pass in the feed URL along with cache\n\t * options directly into the constructor. This has been removed as of 1.3 as\n\t * it caused a lot of confusion.\n\t *\n\t * @since 1.0 Preview Release\n\t */\n\tpublic function __construct()\n\t{\n\t\tif (version_compare(PHP_VERSION, '5.2', '<'))\n\t\t{\n\t\t\ttrigger_error('PHP 4.x, 5.0 and 5.1 are no longer supported. Please upgrade to PHP 5.2 or newer.');\n\t\t\tdie();\n\t\t}\n\n\t\t// Other objects, instances created here so we can set options on them\n\t\t$this->sanitize = new SimplePie_Sanitize();\n\t\t$this->registry = new SimplePie_Registry();\n\n\t\tif (func_num_args() > 0)\n\t\t{\n\t\t\t$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;\n\t\t\ttrigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.', $level);\n\n\t\t\t$args = func_get_args();\n\t\t\tswitch (count($args)) {\n\t\t\t\tcase 3:\n\t\t\t\t\t$this->set_cache_duration($args[2]);\n\t\t\t\tcase 2:\n\t\t\t\t\t$this->set_cache_location($args[1]);\n\t\t\t\tcase 1:\n\t\t\t\t\t$this->set_feed_url($args[0]);\n\t\t\t\t\t$this->init();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Used for converting object to a string\n\t */\n\tpublic function __toString()\n\t{\n\t\treturn md5(serialize($this->data));\n\t}\n\n\t/**\n\t * Remove items that link back to this before destroying this object\n\t */\n\tpublic function __destruct()\n\t{\n\t\tif ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))\n\t\t{\n\t\t\tif (!empty($this->data['items']))\n\t\t\t{\n\t\t\t\tforeach ($this->data['items'] as $item)\n\t\t\t\t{\n\t\t\t\t\t$item->__destruct();\n\t\t\t\t}\n\t\t\t\tunset($item, $this->data['items']);\n\t\t\t}\n\t\t\tif (!empty($this->data['ordered_items']))\n\t\t\t{\n\t\t\t\tforeach ($this->data['ordered_items'] as $item)\n\t\t\t\t{\n\t\t\t\t\t$item->__destruct();\n\t\t\t\t}\n\t\t\t\tunset($item, $this->data['ordered_items']);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Force the given data/URL to be treated as a feed\n\t *\n\t * This tells SimplePie to ignore the content-type provided by the server.\n\t * Be careful when using this option, as it will also disable autodiscovery.\n\t *\n\t * @since 1.1\n\t * @param bool $enable Force the given data/URL to be treated as a feed\n\t */\n\tpublic function force_feed($enable = false)\n\t{\n\t\t$this->force_feed = (bool) $enable;\n\t}\n\n\t/**\n\t * Set the URL of the feed you want to parse\n\t *\n\t * This allows you to enter the URL of the feed you want to parse, or the\n\t * website you want to try to use auto-discovery on. This takes priority\n\t * over any set raw data.\n\t *\n\t * You can set multiple feeds to mash together by passing an array instead\n\t * of a string for the $url. Remember that with each additional feed comes\n\t * additional processing and resources.\n\t *\n\t * @since 1.0 Preview Release\n\t * @see set_raw_data()\n\t * @param string|array $url This is the URL (or array of URLs) that you want to parse.\n\t */\n\tpublic function set_feed_url($url)\n\t{\n\t\t$this->multifeed_url = array();\n\t\tif (is_array($url))\n\t\t{\n\t\t\tforeach ($url as $value)\n\t\t\t{\n\t\t\t\t$this->multifeed_url[] = $this->registry->call('Misc', 'fix_protocol', array($value, 1));\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1));\n\t\t}\n\t}\n\n\t/**\n\t * Set an instance of {@see SimplePie_File} to use as a feed\n\t *\n\t * @param SimplePie_File &$file\n\t * @return bool True on success, false on failure\n\t */\n\tpublic function set_file(&$file)\n\t{\n\t\tif ($file instanceof SimplePie_File)\n\t\t{\n\t\t\t$this->feed_url = $file->url;\n\t\t\t$this->file =& $file;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Set the raw XML data to parse\n\t *\n\t * Allows you to use a string of RSS/Atom data instead of a remote feed.\n\t *\n\t * If you have a feed available as a string in PHP, you can tell SimplePie\n\t * to parse that data string instead of a remote feed. Any set feed URL\n\t * takes precedence.\n\t *\n\t * @since 1.0 Beta 3\n\t * @param string $data RSS or Atom data as a string.\n\t * @see set_feed_url()\n\t */\n\tpublic function set_raw_data($data)\n\t{\n\t\t$this->raw_data = $data;\n\t}\n\n\t/**\n\t * Set the the default timeout for fetching remote feeds\n\t *\n\t * This allows you to change the maximum time the feed's server to respond\n\t * and send the feed back.\n\t *\n\t * @since 1.0 Beta 3\n\t * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.\n\t */\n\tpublic function set_timeout($timeout = 10)\n\t{\n\t\t$this->timeout = (int) $timeout;\n\t}\n\n\t/**\n\t * Force SimplePie to use fsockopen() instead of cURL\n\t *\n\t * @since 1.0 Beta 3\n\t * @param bool $enable Force fsockopen() to be used\n\t */\n\tpublic function force_fsockopen($enable = false)\n\t{\n\t\t$this->force_fsockopen = (bool) $enable;\n\t}\n\n\t/**\n\t * Enable/disable caching in SimplePie.\n\t *\n\t * This option allows you to disable caching all-together in SimplePie.\n\t * However, disabling the cache can lead to longer load times.\n\t *\n\t * @since 1.0 Preview Release\n\t * @param bool $enable Enable caching\n\t */\n\tpublic function enable_cache($enable = true)\n\t{\n\t\t$this->cache = (bool) $enable;\n\t}\n\n\t/**\n\t * Set the length of time (in seconds) that the contents of a feed will be\n\t * cached\n\t *\n\t * @param int $seconds The feed content cache duration\n\t */\n\tpublic function set_cache_duration($seconds = 3600)\n\t{\n\t\t$this->cache_duration = (int) $seconds;\n\t}\n\n\t/**\n\t * Set the length of time (in seconds) that the autodiscovered feed URL will\n\t * be cached\n\t *\n\t * @param int $seconds The autodiscovered feed URL cache duration.\n\t */\n\tpublic function set_autodiscovery_cache_duration($seconds = 604800)\n\t{\n\t\t$this->autodiscovery_cache_duration = (int) $seconds;\n\t}\n\n\t/**\n\t * Set the file system location where the cached files should be stored\n\t *\n\t * @param string $location The file system location.\n\t */\n\tpublic function set_cache_location($location = './cache')\n\t{\n\t\t$this->cache_location = (string) $location;\n\t}\n\n\t/**\n\t * Set whether feed items should be sorted into reverse chronological order\n\t *\n\t * @param bool $enable Sort as reverse chronological order.\n\t */\n\tpublic function enable_order_by_date($enable = true)\n\t{\n\t\t$this->order_by_date = (bool) $enable;\n\t}\n\n\t/**\n\t * Set the character encoding used to parse the feed\n\t *\n\t * This overrides the encoding reported by the feed, however it will fall\n\t * back to the normal encoding detection if the override fails\n\t *\n\t * @param string $encoding Character encoding\n\t */\n\tpublic function set_input_encoding($encoding = false)\n\t{\n\t\tif ($encoding)\n\t\t{\n\t\t\t$this->input_encoding = (string) $encoding;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->input_encoding = false;\n\t\t}\n\t}\n\n\t/**\n\t * Set how much feed autodiscovery to do\n\t *\n\t * @see SIMPLEPIE_LOCATOR_NONE\n\t * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY\n\t * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION\n\t * @see SIMPLEPIE_LOCATOR_LOCAL_BODY\n\t * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION\n\t * @see SIMPLEPIE_LOCATOR_REMOTE_BODY\n\t * @see SIMPLEPIE_LOCATOR_ALL\n\t * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator)\n\t */\n\tpublic function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)\n\t{\n\t\t$this->autodiscovery = (int) $level;\n\t}\n\n\t/**\n\t * Get the class registry\n\t *\n\t * Use this to override SimplePie's default classes\n\t * @see SimplePie_Registry\n\t * @return SimplePie_Registry\n\t */\n\tpublic function &get_registry()\n\t{\n\t\treturn $this->registry;\n\t}\n\n\t/**#@+\n\t * Useful when you are overloading or extending SimplePie's default classes.\n\t *\n\t * @deprecated Use {@see get_registry()} instead\n\t * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation\n\t * @param string $class Name of custom class\n\t * @return boolean True on success, false otherwise\n\t */\n\t/**\n\t * Set which class SimplePie uses for caching\n\t */\n\tpublic function set_cache_class($class = 'SimplePie_Cache')\n\t{\n\t\treturn $this->registry->register('Cache', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses for auto-discovery\n\t */\n\tpublic function set_locator_class($class = 'SimplePie_Locator')\n\t{\n\t\treturn $this->registry->register('Locator', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses for XML parsing\n\t */\n\tpublic function set_parser_class($class = 'SimplePie_Parser')\n\t{\n\t\treturn $this->registry->register('Parser', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses for remote file fetching\n\t */\n\tpublic function set_file_class($class = 'SimplePie_File')\n\t{\n\t\treturn $this->registry->register('File', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses for data sanitization\n\t */\n\tpublic function set_sanitize_class($class = 'SimplePie_Sanitize')\n\t{\n\t\treturn $this->registry->register('Sanitize', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses for handling feed items\n\t */\n\tpublic function set_item_class($class = 'SimplePie_Item')\n\t{\n\t\treturn $this->registry->register('Item', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses for handling author data\n\t */\n\tpublic function set_author_class($class = 'SimplePie_Author')\n\t{\n\t\treturn $this->registry->register('Author', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses for handling category data\n\t */\n\tpublic function set_category_class($class = 'SimplePie_Category')\n\t{\n\t\treturn $this->registry->register('Category', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses for feed enclosures\n\t */\n\tpublic function set_enclosure_class($class = 'SimplePie_Enclosure')\n\t{\n\t\treturn $this->registry->register('Enclosure', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses for `<media:text>` captions\n\t */\n\tpublic function set_caption_class($class = 'SimplePie_Caption')\n\t{\n\t\treturn $this->registry->register('Caption', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses for `<media:copyright>`\n\t */\n\tpublic function set_copyright_class($class = 'SimplePie_Copyright')\n\t{\n\t\treturn $this->registry->register('Copyright', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses for `<media:credit>`\n\t */\n\tpublic function set_credit_class($class = 'SimplePie_Credit')\n\t{\n\t\treturn $this->registry->register('Credit', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses for `<media:rating>`\n\t */\n\tpublic function set_rating_class($class = 'SimplePie_Rating')\n\t{\n\t\treturn $this->registry->register('Rating', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses for `<media:restriction>`\n\t */\n\tpublic function set_restriction_class($class = 'SimplePie_Restriction')\n\t{\n\t\treturn $this->registry->register('Restriction', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses for content-type sniffing\n\t */\n\tpublic function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')\n\t{\n\t\treturn $this->registry->register('Content_Type_Sniffer', $class, true);\n\t}\n\n\t/**\n\t * Set which class SimplePie uses item sources\n\t */\n\tpublic function set_source_class($class = 'SimplePie_Source')\n\t{\n\t\treturn $this->registry->register('Source', $class, true);\n\t}\n\t/**#@-*/\n\n\t/**\n\t * Set the user agent string\n\t *\n\t * @param string $ua New user agent string.\n\t */\n\tpublic function set_useragent($ua = SIMPLEPIE_USERAGENT)\n\t{\n\t\t$this->useragent = (string) $ua;\n\t}\n\n\t/**\n\t * Set callback function to create cache filename with\n\t *\n\t * @param mixed $function Callback function\n\t */\n\tpublic function set_cache_name_function($function = 'md5')\n\t{\n\t\tif (is_callable($function))\n\t\t{\n\t\t\t$this->cache_name_function = $function;\n\t\t}\n\t}\n\n\t/**\n\t * Set options to make SP as fast as possible\n\t *\n\t * Forgoes a substantial amount of data sanitization in favor of speed. This\n\t * turns SimplePie into a dumb parser of feeds.\n\t *\n\t * @param bool $set Whether to set them or not\n\t */\n\tpublic function set_stupidly_fast($set = false)\n\t{\n\t\tif ($set)\n\t\t{\n\t\t\t$this->enable_order_by_date(false);\n\t\t\t$this->remove_div(false);\n\t\t\t$this->strip_comments(false);\n\t\t\t$this->strip_htmltags(false);\n\t\t\t$this->strip_attributes(false);\n\t\t\t$this->set_image_handler(false);\n\t\t}\n\t}\n\n\t/**\n\t * Set maximum number of feeds to check with autodiscovery\n\t *\n\t * @param int $max Maximum number of feeds to check\n\t */\n\tpublic function set_max_checked_feeds($max = 10)\n\t{\n\t\t$this->max_checked_feeds = (int) $max;\n\t}\n\n\tpublic function remove_div($enable = true)\n\t{\n\t\t$this->sanitize->remove_div($enable);\n\t}\n\n\tpublic function strip_htmltags($tags = '', $encode = null)\n\t{\n\t\tif ($tags === '')\n\t\t{\n\t\t\t$tags = $this->strip_htmltags;\n\t\t}\n\t\t$this->sanitize->strip_htmltags($tags);\n\t\tif ($encode !== null)\n\t\t{\n\t\t\t$this->sanitize->encode_instead_of_strip($tags);\n\t\t}\n\t}\n\n\tpublic function encode_instead_of_strip($enable = true)\n\t{\n\t\t$this->sanitize->encode_instead_of_strip($enable);\n\t}\n\n\tpublic function strip_attributes($attribs = '')\n\t{\n\t\tif ($attribs === '')\n\t\t{\n\t\t\t$attribs = $this->strip_attributes;\n\t\t}\n\t\t$this->sanitize->strip_attributes($attribs);\n\t}\n\n\t/**\n\t * Set the output encoding\n\t *\n\t * Allows you to override SimplePie's output to match that of your webpage.\n\t * This is useful for times when your webpages are not being served as\n\t * UTF-8.  This setting will be obeyed by {@see handle_content_type()}, and\n\t * is similar to {@see set_input_encoding()}.\n\t *\n\t * It should be noted, however, that not all character encodings can support\n\t * all characters.  If your page is being served as ISO-8859-1 and you try\n\t * to display a Japanese feed, you'll likely see garbled characters.\n\t * Because of this, it is highly recommended to ensure that your webpages\n\t * are served as UTF-8.\n\t *\n\t * The number of supported character encodings depends on whether your web\n\t * host supports {@link http://php.net/mbstring mbstring},\n\t * {@link http://php.net/iconv iconv}, or both. See\n\t * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for\n\t * more information.\n\t *\n\t * @param string $encoding\n\t */\n\tpublic function set_output_encoding($encoding = 'UTF-8')\n\t{\n\t\t$this->sanitize->set_output_encoding($encoding);\n\t}\n\n\tpublic function strip_comments($strip = false)\n\t{\n\t\t$this->sanitize->strip_comments($strip);\n\t}\n\n\t/**\n\t * Set element/attribute key/value pairs of HTML attributes\n\t * containing URLs that need to be resolved relative to the feed\n\t *\n\t * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,\n\t * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,\n\t * |q|@cite\n\t *\n\t * @since 1.0\n\t * @param array|null $element_attribute Element/attribute key/value pairs, null for default\n\t */\n\tpublic function set_url_replacements($element_attribute = null)\n\t{\n\t\t$this->sanitize->set_url_replacements($element_attribute);\n\t}\n\n\t/**\n\t * Set the handler to enable the display of cached images.\n\t *\n\t * @param str $page Web-accessible path to the handler_image.php file.\n\t * @param str $qs The query string that the value should be passed to.\n\t */\n\tpublic function set_image_handler($page = false, $qs = 'i')\n\t{\n\t\tif ($page !== false)\n\t\t{\n\t\t\t$this->sanitize->set_image_handler($page . '?' . $qs . '=');\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->image_handler = '';\n\t\t}\n\t}\n\n\t/**\n\t * Set the limit for items returned per-feed with multifeeds\n\t *\n\t * @param integer $limit The maximum number of items to return.\n\t */\n\tpublic function set_item_limit($limit = 0)\n\t{\n\t\t$this->item_limit = (int) $limit;\n\t}\n\n\t/**\n\t * Initialize the feed object\n\t *\n\t * This is what makes everything happen.  Period.  This is where all of the\n\t * configuration options get processed, feeds are fetched, cached, and\n\t * parsed, and all of that other good stuff.\n\t *\n\t * @return boolean True if successful, false otherwise\n\t */\n\tpublic function init()\n\t{\n\t\t// Check absolute bare minimum requirements.\n\t\tif (!extension_loaded('xml') || !extension_loaded('pcre'))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\t// Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.\n\t\telseif (!extension_loaded('xmlreader'))\n\t\t{\n\t\t\tstatic $xml_is_sane = null;\n\t\t\tif ($xml_is_sane === null)\n\t\t\t{\n\t\t\t\t$parser_check = xml_parser_create();\n\t\t\t\txml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);\n\t\t\t\txml_parser_free($parser_check);\n\t\t\t\t$xml_is_sane = isset($values[0]['value']);\n\t\t\t}\n\t\t\tif (!$xml_is_sane)\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tif (method_exists($this->sanitize, 'set_registry'))\n\t\t{\n\t\t\t$this->sanitize->set_registry($this->registry);\n\t\t}\n\n\t\t// Pass whatever was set with config options over to the sanitizer.\n\t\t// Pass the classes in for legacy support; new classes should use the registry instead\n\t\t$this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache'));\n\t\t$this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen);\n\n\t\tif (!empty($this->multifeed_url))\n\t\t{\n\t\t\t$i = 0;\n\t\t\t$success = 0;\n\t\t\t$this->multifeed_objects = array();\n\t\t\t$this->error = array();\n\t\t\tforeach ($this->multifeed_url as $url)\n\t\t\t{\n\t\t\t\t$this->multifeed_objects[$i] = clone $this;\n\t\t\t\t$this->multifeed_objects[$i]->set_feed_url($url);\n\t\t\t\t$single_success = $this->multifeed_objects[$i]->init();\n\t\t\t\t$success |= $single_success;\n\t\t\t\tif (!$single_success)\n\t\t\t\t{\n\t\t\t\t\t$this->error[$i] = $this->multifeed_objects[$i]->error();\n\t\t\t\t}\n\t\t\t\t$i++;\n\t\t\t}\n\t\t\treturn (bool) $success;\n\t\t}\n\t\telseif ($this->feed_url === null && $this->raw_data === null)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\n\t\t$this->error = null;\n\t\t$this->data = array();\n\t\t$this->multifeed_objects = array();\n\t\t$cache = false;\n\n\t\tif ($this->feed_url !== null)\n\t\t{\n\t\t\t$parsed_feed_url = $this->registry->call('Misc', 'parse_url', array($this->feed_url));\n\n\t\t\t// Decide whether to enable caching\n\t\t\tif ($this->cache && $parsed_feed_url['scheme'] !== '')\n\t\t\t{\n\t\t\t\t$cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc'));\n\t\t\t}\n\n\t\t\t// Fetch the data via SimplePie_File into $this->raw_data\n\t\t\tif (($fetched = $this->fetch_data($cache)) === true)\n\t\t\t{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telseif ($fetched === false) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tlist($headers, $sniffed) = $fetched;\n\t\t}\n\n\t\t// Set up array of possible encodings\n\t\t$encodings = array();\n\n\t\t// First check to see if input has been overridden.\n\t\tif ($this->input_encoding !== false)\n\t\t{\n\t\t\t$encodings[] = $this->input_encoding;\n\t\t}\n\n\t\t$application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');\n\t\t$text_types = array('text/xml', 'text/xml-external-parsed-entity');\n\n\t\t// RFC 3023 (only applies to sniffed content)\n\t\tif (isset($sniffed))\n\t\t{\n\t\t\tif (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')\n\t\t\t{\n\t\t\t\tif (isset($headers['content-type']) && preg_match('/;\\x20?charset=([^;]*)/i', $headers['content-type'], $charset))\n\t\t\t\t{\n\t\t\t\t\t$encodings[] = strtoupper($charset[1]);\n\t\t\t\t}\n\t\t\t\t$encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));\n\t\t\t\t$encodings[] = 'UTF-8';\n\t\t\t}\n\t\t\telseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')\n\t\t\t{\n\t\t\t\tif (isset($headers['content-type']) && preg_match('/;\\x20?charset=([^;]*)/i', $headers['content-type'], $charset))\n\t\t\t\t{\n\t\t\t\t\t$encodings[] = $charset[1];\n\t\t\t\t}\n\t\t\t\t$encodings[] = 'US-ASCII';\n\t\t\t}\n\t\t\t// Text MIME-type default\n\t\t\telseif (substr($sniffed, 0, 5) === 'text/')\n\t\t\t{\n\t\t\t\t$encodings[] = 'US-ASCII';\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1\n\t\t$encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));\n\t\t$encodings[] = 'UTF-8';\n\t\t$encodings[] = 'ISO-8859-1';\n\n\t\t// There's no point in trying an encoding twice\n\t\t$encodings = array_unique($encodings);\n\n\t\t// Loop through each possible encoding, till we return something, or run out of possibilities\n\t\tforeach ($encodings as $encoding)\n\t\t{\n\t\t\t// Change the encoding to UTF-8 (as we always use UTF-8 internally)\n\t\t\tif ($utf8_data = $this->registry->call('Misc', 'change_encoding', array($this->raw_data, $encoding, 'UTF-8')))\n\t\t\t{\n\t\t\t\t// Create new parser\n\t\t\t\t$parser = $this->registry->create('Parser');\n\n\t\t\t\t// If it's parsed fine\n\t\t\t\tif ($parser->parse($utf8_data, 'UTF-8'))\n\t\t\t\t{\n\t\t\t\t\t$this->data = $parser->get_data();\n\t\t\t\t\tif (!($this->get_type() & ~SIMPLEPIE_TYPE_NONE))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->error = \"A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.\";\n\t\t\t\t\t\t$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (isset($headers))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->data['headers'] = $headers;\n\t\t\t\t\t}\n\t\t\t\t\t$this->data['build'] = SIMPLEPIE_BUILD;\n\n\t\t\t\t\t// Cache the file if caching is enabled\n\t\t\t\t\tif ($cache && !$cache->save($this))\n\t\t\t\t\t{\n\t\t\t\t\t\ttrigger_error(\"$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.\", E_USER_WARNING);\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (isset($parser))\n\t\t{\n\t\t\t// We have an error, just set SimplePie_Misc::error to it and quit\n\t\t\t$this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';\n\t\t}\n\n\t\t$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Fetch the data via SimplePie_File\n\t *\n\t * If the data is already cached, attempt to fetch it from there instead\n\t * @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache\n\t * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type\n\t */\n\tprotected function fetch_data(&$cache)\n\t{\n\t\t// If it's enabled, use the cache\n\t\tif ($cache)\n\t\t{\n\t\t\t// Load the Cache\n\t\t\t$this->data = $cache->load();\n\t\t\tif (!empty($this->data))\n\t\t\t{\n\t\t\t\t// If the cache is for an outdated build of SimplePie\n\t\t\t\tif (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)\n\t\t\t\t{\n\t\t\t\t\t$cache->unlink();\n\t\t\t\t\t$this->data = array();\n\t\t\t\t}\n\t\t\t\t// If we've hit a collision just rerun it with caching disabled\n\t\t\t\telseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)\n\t\t\t\t{\n\t\t\t\t\t$cache = false;\n\t\t\t\t\t$this->data = array();\n\t\t\t\t}\n\t\t\t\t// If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.\n\t\t\t\telseif (isset($this->data['feed_url']))\n\t\t\t\t{\n\t\t\t\t\t// If the autodiscovery cache is still valid use it.\n\t\t\t\t\tif ($cache->mtime() + $this->autodiscovery_cache_duration > time())\n\t\t\t\t\t{\n\t\t\t\t\t\t// Do not need to do feed autodiscovery yet.\n\t\t\t\t\t\tif ($this->data['feed_url'] !== $this->data['url'])\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->set_feed_url($this->data['feed_url']);\n\t\t\t\t\t\t\treturn $this->init();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$cache->unlink();\n\t\t\t\t\t\t$this->data = array();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Check if the cache has been updated\n\t\t\t\telseif ($cache->mtime() + $this->cache_duration < time())\n\t\t\t\t{\n\t\t\t\t\t// If we have last-modified and/or etag set\n\t\t\t\t\tif (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$headers = array(\n\t\t\t\t\t\t\t'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (isset($this->data['headers']['last-modified']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$headers['if-modified-since'] = $this->data['headers']['last-modified'];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isset($this->data['headers']['etag']))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$headers['if-none-match'] = $this->data['headers']['etag'];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$file = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen));\n\n\t\t\t\t\t\tif ($file->success)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ($file->status_code === 304)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$cache->touch();\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tunset($file);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// If the cache is still valid, just return true\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->raw_data = false;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If the cache is empty, delete it\n\t\t\telse\n\t\t\t{\n\t\t\t\t$cache->unlink();\n\t\t\t\t$this->data = array();\n\t\t\t}\n\t\t}\n\t\t// If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.\n\t\tif (!isset($file))\n\t\t{\n\t\t\tif ($this->file instanceof SimplePie_File && $this->file->url === $this->feed_url)\n\t\t\t{\n\t\t\t\t$file =& $this->file;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$headers = array(\n\t\t\t\t\t'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',\n\t\t\t\t);\n\t\t\t\t$file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen));\n\t\t\t}\n\t\t}\n\t\t// If the file connection has an error, set SimplePie::error to that and quit\n\t\tif (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))\n\t\t{\n\t\t\t$this->error = $file->error;\n\t\t\treturn !empty($this->data);\n\t\t}\n\n\t\tif (!$this->force_feed)\n\t\t{\n\t\t\t// Check if the supplied URL is a feed, if it isn't, look for it.\n\t\t\t$locate = $this->registry->create('Locator', array(&$file, $this->timeout, $this->useragent, $this->max_checked_feeds));\n\n\t\t\tif (!$locate->is_feed($file))\n\t\t\t{\n\t\t\t\t// We need to unset this so that if SimplePie::set_file() has been called that object is untouched\n\t\t\t\tunset($file);\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tif (!($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds)))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->error = \"A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or \" . SIMPLEPIE_NAME . \" was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.\";\n\t\t\t\t\t\t$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch (SimplePie_Exception $e)\n\t\t\t\t{\n\t\t\t\t\t// This is usually because DOMDocument doesn't exist\n\t\t\t\t\t$this->error = $e->getMessage();\n\t\t\t\t\t$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, $e->getFile(), $e->getLine()));\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif ($cache)\n\t\t\t\t{\n\t\t\t\t\t$this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);\n\t\t\t\t\tif (!$cache->save($this))\n\t\t\t\t\t{\n\t\t\t\t\t\ttrigger_error(\"$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.\", E_USER_WARNING);\n\t\t\t\t\t}\n\t\t\t\t\t$cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc'));\n\t\t\t\t}\n\t\t\t\t$this->feed_url = $file->url;\n\t\t\t}\n\t\t\t$locate = null;\n\t\t}\n\n\t\t$this->raw_data = $file->body;\n\n\t\t$headers = $file->headers;\n\t\t$sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file));\n\t\t$sniffed = $sniffer->get_type();\n\n\t\treturn array($headers, $sniffed);\n\t}\n\n\t/**\n\t * Get the error message for the occured error\n\t *\n\t * @return string|array Error message, or array of messages for multifeeds\n\t */\n\tpublic function error()\n\t{\n\t\treturn $this->error;\n\t}\n\n\t/**\n\t * Get the raw XML\n\t *\n\t * This is the same as the old `$feed->enable_xml_dump(true)`, but returns\n\t * the data instead of printing it.\n\t *\n\t * @return string|boolean Raw XML data, false if the cache is used\n\t */\n\tpublic function get_raw_data()\n\t{\n\t\treturn $this->raw_data;\n\t}\n\n\t/**\n\t * Get the character encoding used for output\n\t *\n\t * @since Preview Release\n\t * @return string\n\t */\n\tpublic function get_encoding()\n\t{\n\t\treturn $this->sanitize->output_encoding;\n\t}\n\n\t/**\n\t * Send the content-type header with correct encoding\n\t *\n\t * This method ensures that the SimplePie-enabled page is being served with\n\t * the correct {@link http://www.iana.org/assignments/media-types/ mime-type}\n\t * and character encoding HTTP headers (character encoding determined by the\n\t * {@see set_output_encoding} config option).\n\t *\n\t * This won't work properly if any content or whitespace has already been\n\t * sent to the browser, because it relies on PHP's\n\t * {@link http://php.net/header header()} function, and these are the\n\t * circumstances under which the function works.\n\t *\n\t * Because it's setting these settings for the entire page (as is the nature\n\t * of HTTP headers), this should only be used once per page (again, at the\n\t * top).\n\t *\n\t * @param string $mime MIME type to serve the page as\n\t */\n\tpublic function handle_content_type($mime = 'text/html')\n\t{\n\t\tif (!headers_sent())\n\t\t{\n\t\t\t$header = \"Content-type: $mime;\";\n\t\t\tif ($this->get_encoding())\n\t\t\t{\n\t\t\t\t$header .= ' charset=' . $this->get_encoding();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$header .= ' charset=UTF-8';\n\t\t\t}\n\t\t\theader($header);\n\t\t}\n\t}\n\n\t/**\n\t * Get the type of the feed\n\t *\n\t * This returns a SIMPLEPIE_TYPE_* constant, which can be tested against\n\t * using {@link http://php.net/language.operators.bitwise bitwise operators}\n\t *\n\t * @since 0.8 (usage changed to using constants in 1.0)\n\t * @see SIMPLEPIE_TYPE_NONE Unknown.\n\t * @see SIMPLEPIE_TYPE_RSS_090 RSS 0.90.\n\t * @see SIMPLEPIE_TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape).\n\t * @see SIMPLEPIE_TYPE_RSS_091_USERLAND RSS 0.91 (Userland).\n\t * @see SIMPLEPIE_TYPE_RSS_091 RSS 0.91.\n\t * @see SIMPLEPIE_TYPE_RSS_092 RSS 0.92.\n\t * @see SIMPLEPIE_TYPE_RSS_093 RSS 0.93.\n\t * @see SIMPLEPIE_TYPE_RSS_094 RSS 0.94.\n\t * @see SIMPLEPIE_TYPE_RSS_10 RSS 1.0.\n\t * @see SIMPLEPIE_TYPE_RSS_20 RSS 2.0.x.\n\t * @see SIMPLEPIE_TYPE_RSS_RDF RDF-based RSS.\n\t * @see SIMPLEPIE_TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format).\n\t * @see SIMPLEPIE_TYPE_RSS_ALL Any version of RSS.\n\t * @see SIMPLEPIE_TYPE_ATOM_03 Atom 0.3.\n\t * @see SIMPLEPIE_TYPE_ATOM_10 Atom 1.0.\n\t * @see SIMPLEPIE_TYPE_ATOM_ALL Any version of Atom.\n\t * @see SIMPLEPIE_TYPE_ALL Any known/supported feed type.\n\t * @return int SIMPLEPIE_TYPE_* constant\n\t */\n\tpublic function get_type()\n\t{\n\t\tif (!isset($this->data['type']))\n\t\t{\n\t\t\t$this->data['type'] = SIMPLEPIE_TYPE_ALL;\n\t\t\tif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))\n\t\t\t{\n\t\t\t\t$this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;\n\t\t\t}\n\t\t\telseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))\n\t\t\t{\n\t\t\t\t$this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;\n\t\t\t}\n\t\t\telseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))\n\t\t\t{\n\t\t\t\tif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])\n\t\t\t\t|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])\n\t\t\t\t|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])\n\t\t\t\t|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))\n\t\t\t\t{\n\t\t\t\t\t$this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;\n\t\t\t\t}\n\t\t\t\tif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])\n\t\t\t\t|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])\n\t\t\t\t|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])\n\t\t\t\t|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))\n\t\t\t\t{\n\t\t\t\t\t$this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))\n\t\t\t{\n\t\t\t\t$this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;\n\t\t\t\tif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))\n\t\t\t\t{\n\t\t\t\t\tswitch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))\n\t\t\t\t\t{\n\t\t\t\t\t\tcase '0.91':\n\t\t\t\t\t\t\t$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;\n\t\t\t\t\t\t\tif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tswitch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcase '0':\n\t\t\t\t\t\t\t\t\t\t$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\t\tcase '24':\n\t\t\t\t\t\t\t\t\t\t$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase '0.92':\n\t\t\t\t\t\t\t$this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase '0.93':\n\t\t\t\t\t\t\t$this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase '0.94':\n\t\t\t\t\t\t\t$this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase '2.0':\n\t\t\t\t\t\t\t$this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->data['type'] = SIMPLEPIE_TYPE_NONE;\n\t\t\t}\n\t\t}\n\t\treturn $this->data['type'];\n\t}\n\n\t/**\n\t * Get the URL for the feed\n\t *\n\t * May or may not be different from the URL passed to {@see set_feed_url()},\n\t * depending on whether auto-discovery was used.\n\t *\n\t * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.)\n\t * @todo If we have a perm redirect we should return the new URL\n\t * @todo When we make the above change, let's support <itunes:new-feed-url> as well\n\t * @todo Also, |atom:link|@rel=self\n\t * @return string|null\n\t */\n\tpublic function subscribe_url()\n\t{\n\t\tif ($this->feed_url !== null)\n\t\t{\n\t\t\treturn $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get data for an feed-level element\n\t *\n\t * This method allows you to get access to ANY element/attribute that is a\n\t * sub-element of the opening feed tag.\n\t *\n\t * The return value is an indexed array of elements matching the given\n\t * namespace and tag name. Each element has `attribs`, `data` and `child`\n\t * subkeys. For `attribs` and `child`, these contain namespace subkeys.\n\t * `attribs` then has one level of associative name => value data (where\n\t * `value` is a string) after the namespace. `child` has tag-indexed keys\n\t * after the namespace, each member of which is an indexed array matching\n\t * this same format.\n\t *\n\t * For example:\n\t * <pre>\n\t * // This is probably a bad example because we already support\n\t * // <media:content> natively, but it shows you how to parse through\n\t * // the nodes.\n\t * $group = $item->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group');\n\t * $content = $group[0]['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'];\n\t * $file = $content[0]['attribs']['']['url'];\n\t * echo $file;\n\t * </pre>\n\t *\n\t * @since 1.0\n\t * @see http://simplepie.org/wiki/faq/supported_xml_namespaces\n\t * @param string $namespace The URL of the XML namespace of the elements you're trying to access\n\t * @param string $tag Tag name\n\t * @return array\n\t */\n\tpublic function get_feed_tags($namespace, $tag)\n\t{\n\t\t$type = $this->get_type();\n\t\tif ($type & SIMPLEPIE_TYPE_ATOM_10)\n\t\t{\n\t\t\tif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))\n\t\t\t{\n\t\t\t\treturn $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];\n\t\t\t}\n\t\t}\n\t\tif ($type & SIMPLEPIE_TYPE_ATOM_03)\n\t\t{\n\t\t\tif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))\n\t\t\t{\n\t\t\t\treturn $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];\n\t\t\t}\n\t\t}\n\t\tif ($type & SIMPLEPIE_TYPE_RSS_RDF)\n\t\t{\n\t\t\tif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))\n\t\t\t{\n\t\t\t\treturn $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];\n\t\t\t}\n\t\t}\n\t\tif ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)\n\t\t{\n\t\t\tif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))\n\t\t\t{\n\t\t\t\treturn $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Get data for an channel-level element\n\t *\n\t * This method allows you to get access to ANY element/attribute in the\n\t * channel/header section of the feed.\n\t *\n\t * See {@see SimplePie::get_feed_tags()} for a description of the return value\n\t *\n\t * @since 1.0\n\t * @see http://simplepie.org/wiki/faq/supported_xml_namespaces\n\t * @param string $namespace The URL of the XML namespace of the elements you're trying to access\n\t * @param string $tag Tag name\n\t * @return array\n\t */\n\tpublic function get_channel_tags($namespace, $tag)\n\t{\n\t\t$type = $this->get_type();\n\t\tif ($type & SIMPLEPIE_TYPE_ATOM_ALL)\n\t\t{\n\t\t\tif ($return = $this->get_feed_tags($namespace, $tag))\n\t\t\t{\n\t\t\t\treturn $return;\n\t\t\t}\n\t\t}\n\t\tif ($type & SIMPLEPIE_TYPE_RSS_10)\n\t\t{\n\t\t\tif ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))\n\t\t\t{\n\t\t\t\tif (isset($channel[0]['child'][$namespace][$tag]))\n\t\t\t\t{\n\t\t\t\t\treturn $channel[0]['child'][$namespace][$tag];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif ($type & SIMPLEPIE_TYPE_RSS_090)\n\t\t{\n\t\t\tif ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))\n\t\t\t{\n\t\t\t\tif (isset($channel[0]['child'][$namespace][$tag]))\n\t\t\t\t{\n\t\t\t\t\treturn $channel[0]['child'][$namespace][$tag];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)\n\t\t{\n\t\t\tif ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))\n\t\t\t{\n\t\t\t\tif (isset($channel[0]['child'][$namespace][$tag]))\n\t\t\t\t{\n\t\t\t\t\treturn $channel[0]['child'][$namespace][$tag];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Get data for an channel-level element\n\t *\n\t * This method allows you to get access to ANY element/attribute in the\n\t * image/logo section of the feed.\n\t *\n\t * See {@see SimplePie::get_feed_tags()} for a description of the return value\n\t *\n\t * @since 1.0\n\t * @see http://simplepie.org/wiki/faq/supported_xml_namespaces\n\t * @param string $namespace The URL of the XML namespace of the elements you're trying to access\n\t * @param string $tag Tag name\n\t * @return array\n\t */\n\tpublic function get_image_tags($namespace, $tag)\n\t{\n\t\t$type = $this->get_type();\n\t\tif ($type & SIMPLEPIE_TYPE_RSS_10)\n\t\t{\n\t\t\tif ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))\n\t\t\t{\n\t\t\t\tif (isset($image[0]['child'][$namespace][$tag]))\n\t\t\t\t{\n\t\t\t\t\treturn $image[0]['child'][$namespace][$tag];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif ($type & SIMPLEPIE_TYPE_RSS_090)\n\t\t{\n\t\t\tif ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))\n\t\t\t{\n\t\t\t\tif (isset($image[0]['child'][$namespace][$tag]))\n\t\t\t\t{\n\t\t\t\t\treturn $image[0]['child'][$namespace][$tag];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)\n\t\t{\n\t\t\tif ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))\n\t\t\t{\n\t\t\t\tif (isset($image[0]['child'][$namespace][$tag]))\n\t\t\t\t{\n\t\t\t\t\treturn $image[0]['child'][$namespace][$tag];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Get the base URL value from the feed\n\t *\n\t * Uses `<xml:base>` if available, otherwise uses the first link in the\n\t * feed, or failing that, the URL of the feed itself.\n\t *\n\t * @see get_link\n\t * @see subscribe_url\n\t *\n\t * @param array $element\n\t * @return string\n\t */\n\tpublic function get_base($element = array())\n\t{\n\t\tif (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))\n\t\t{\n\t\t\treturn $element['xml_base'];\n\t\t}\n\t\telseif ($this->get_link() !== null)\n\t\t{\n\t\t\treturn $this->get_link();\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn $this->subscribe_url();\n\t\t}\n\t}\n\n\t/**\n\t * Sanitize feed data\n\t *\n\t * @access private\n\t * @see SimplePie_Sanitize::sanitize()\n\t * @param string $data Data to sanitize\n\t * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants\n\t * @param string $base Base URL to resolve URLs against\n\t * @return string Sanitized data\n\t */\n\tpublic function sanitize($data, $type, $base = '')\n\t{\n\t\treturn $this->sanitize->sanitize($data, $type, $base);\n\t}\n\n\t/**\n\t * Get the title of the feed\n\t *\n\t * Uses `<atom:title>`, `<title>` or `<dc:title>`\n\t *\n\t * @since 1.0 (previously called `get_feed_title` since 0.8)\n\t * @return string|null\n\t */\n\tpublic function get_title()\n\t{\n\t\tif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get a category for the feed\n\t *\n\t * @since Unknown\n\t * @param int $key The category that you want to return.  Remember that arrays begin with 0, not 1\n\t * @return SimplePie_Category|null\n\t */\n\tpublic function get_category($key = 0)\n\t{\n\t\t$categories = $this->get_categories();\n\t\tif (isset($categories[$key]))\n\t\t{\n\t\t\treturn $categories[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all categories for the feed\n\t *\n\t * Uses `<atom:category>`, `<category>` or `<dc:subject>`\n\t *\n\t * @since Unknown\n\t * @return array|null List of {@see SimplePie_Category} objects\n\t */\n\tpublic function get_categories()\n\t{\n\t\t$categories = array();\n\n\t\tforeach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)\n\t\t{\n\t\t\t$term = null;\n\t\t\t$scheme = null;\n\t\t\t$label = null;\n\t\t\tif (isset($category['attribs']['']['term']))\n\t\t\t{\n\t\t\t\t$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($category['attribs']['']['scheme']))\n\t\t\t{\n\t\t\t\t$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($category['attribs']['']['label']))\n\t\t\t{\n\t\t\t\t$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\t$categories[] = $this->registry->create('Category', array($term, $scheme, $label));\n\t\t}\n\t\tforeach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)\n\t\t{\n\t\t\t// This is really the label, but keep this as the term also for BC.\n\t\t\t// Label will also work on retrieving because that falls back to term.\n\t\t\t$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\tif (isset($category['attribs']['']['domain']))\n\t\t\t{\n\t\t\t\t$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$scheme = null;\n\t\t\t}\n\t\t\t$categories[] = $this->registry->create('Category', array($term, $scheme, null));\n\t\t}\n\t\tforeach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)\n\t\t{\n\t\t\t$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\t\tforeach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)\n\t\t{\n\t\t\t$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\n\t\tif (!empty($categories))\n\t\t{\n\t\t\treturn array_unique($categories);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get an author for the feed\n\t *\n\t * @since 1.1\n\t * @param int $key The author that you want to return.  Remember that arrays begin with 0, not 1\n\t * @return SimplePie_Author|null\n\t */\n\tpublic function get_author($key = 0)\n\t{\n\t\t$authors = $this->get_authors();\n\t\tif (isset($authors[$key]))\n\t\t{\n\t\t\treturn $authors[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all authors for the feed\n\t *\n\t * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`\n\t *\n\t * @since 1.1\n\t * @return array|null List of {@see SimplePie_Author} objects\n\t */\n\tpublic function get_authors()\n\t{\n\t\t$authors = array();\n\t\tforeach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)\n\t\t{\n\t\t\t$name = null;\n\t\t\t$uri = null;\n\t\t\t$email = null;\n\t\t\tif (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))\n\t\t\t{\n\t\t\t\t$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))\n\t\t\t{\n\t\t\t\t$uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));\n\t\t\t}\n\t\t\tif (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))\n\t\t\t{\n\t\t\t\t$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif ($name !== null || $email !== null || $uri !== null)\n\t\t\t{\n\t\t\t\t$authors[] = $this->registry->create('Author', array($name, $uri, $email));\n\t\t\t}\n\t\t}\n\t\tif ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))\n\t\t{\n\t\t\t$name = null;\n\t\t\t$url = null;\n\t\t\t$email = null;\n\t\t\tif (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))\n\t\t\t{\n\t\t\t\t$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))\n\t\t\t{\n\t\t\t\t$url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));\n\t\t\t}\n\t\t\tif (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))\n\t\t\t{\n\t\t\t\t$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif ($name !== null || $email !== null || $url !== null)\n\t\t\t{\n\t\t\t\t$authors[] = $this->registry->create('Author', array($name, $url, $email));\n\t\t\t}\n\t\t}\n\t\tforeach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)\n\t\t{\n\t\t\t$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\t\tforeach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)\n\t\t{\n\t\t\t$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\t\tforeach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)\n\t\t{\n\t\t\t$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));\n\t\t}\n\n\t\tif (!empty($authors))\n\t\t{\n\t\t\treturn array_unique($authors);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get a contributor for the feed\n\t *\n\t * @since 1.1\n\t * @param int $key The contrbutor that you want to return.  Remember that arrays begin with 0, not 1\n\t * @return SimplePie_Author|null\n\t */\n\tpublic function get_contributor($key = 0)\n\t{\n\t\t$contributors = $this->get_contributors();\n\t\tif (isset($contributors[$key]))\n\t\t{\n\t\t\treturn $contributors[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all contributors for the feed\n\t *\n\t * Uses `<atom:contributor>`\n\t *\n\t * @since 1.1\n\t * @return array|null List of {@see SimplePie_Author} objects\n\t */\n\tpublic function get_contributors()\n\t{\n\t\t$contributors = array();\n\t\tforeach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)\n\t\t{\n\t\t\t$name = null;\n\t\t\t$uri = null;\n\t\t\t$email = null;\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))\n\t\t\t{\n\t\t\t\t$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))\n\t\t\t{\n\t\t\t\t$uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));\n\t\t\t}\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))\n\t\t\t{\n\t\t\t\t$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif ($name !== null || $email !== null || $uri !== null)\n\t\t\t{\n\t\t\t\t$contributors[] = $this->registry->create('Author', array($name, $uri, $email));\n\t\t\t}\n\t\t}\n\t\tforeach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)\n\t\t{\n\t\t\t$name = null;\n\t\t\t$url = null;\n\t\t\t$email = null;\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))\n\t\t\t{\n\t\t\t\t$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))\n\t\t\t{\n\t\t\t\t$url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));\n\t\t\t}\n\t\t\tif (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))\n\t\t\t{\n\t\t\t\t$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t\t}\n\t\t\tif ($name !== null || $email !== null || $url !== null)\n\t\t\t{\n\t\t\t\t$contributors[] = $this->registry->create('Author', array($name, $url, $email));\n\t\t\t}\n\t\t}\n\n\t\tif (!empty($contributors))\n\t\t{\n\t\t\treturn array_unique($contributors);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get a single link for the feed\n\t *\n\t * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)\n\t * @param int $key The link that you want to return.  Remember that arrays begin with 0, not 1\n\t * @param string $rel The relationship of the link to return\n\t * @return string|null Link URL\n\t */\n\tpublic function get_link($key = 0, $rel = 'alternate')\n\t{\n\t\t$links = $this->get_links($rel);\n\t\tif (isset($links[$key]))\n\t\t{\n\t\t\treturn $links[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the permalink for the item\n\t *\n\t * Returns the first link available with a relationship of \"alternate\".\n\t * Identical to {@see get_link()} with key 0\n\t *\n\t * @see get_link\n\t * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)\n\t * @internal Added for parity between the parent-level and the item/entry-level.\n\t * @return string|null Link URL\n\t */\n\tpublic function get_permalink()\n\t{\n\t\treturn $this->get_link(0);\n\t}\n\n\t/**\n\t * Get all links for the feed\n\t *\n\t * Uses `<atom:link>` or `<link>`\n\t *\n\t * @since Beta 2\n\t * @param string $rel The relationship of links to return\n\t * @return array|null Links found for the feed (strings)\n\t */\n\tpublic function get_links($rel = 'alternate')\n\t{\n\t\tif (!isset($this->data['links']))\n\t\t{\n\t\t\t$this->data['links'] = array();\n\t\t\tif ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))\n\t\t\t{\n\t\t\t\tforeach ($links as $link)\n\t\t\t\t{\n\t\t\t\t\tif (isset($link['attribs']['']['href']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';\n\t\t\t\t\t\t$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))\n\t\t\t{\n\t\t\t\tforeach ($links as $link)\n\t\t\t\t{\n\t\t\t\t\tif (isset($link['attribs']['']['href']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';\n\t\t\t\t\t\t$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))\n\t\t\t{\n\t\t\t\t$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));\n\t\t\t}\n\t\t\tif ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))\n\t\t\t{\n\t\t\t\t$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));\n\t\t\t}\n\t\t\tif ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))\n\t\t\t{\n\t\t\t\t$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));\n\t\t\t}\n\n\t\t\t$keys = array_keys($this->data['links']);\n\t\t\tforeach ($keys as $key)\n\t\t\t{\n\t\t\t\tif ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))\n\t\t\t\t{\n\t\t\t\t\tif (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);\n\t\t\t\t\t\t$this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)\n\t\t\t\t{\n\t\t\t\t\t$this->data['links'][substr($key, 41)] =& $this->data['links'][$key];\n\t\t\t\t}\n\t\t\t\t$this->data['links'][$key] = array_unique($this->data['links'][$key]);\n\t\t\t}\n\t\t}\n\n\t\tif (isset($this->data['links'][$rel]))\n\t\t{\n\t\t\treturn $this->data['links'][$rel];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic function get_all_discovered_feeds()\n\t{\n\t\treturn $this->all_discovered_feeds;\n\t}\n\n\t/**\n\t * Get the content for the item\n\t *\n\t * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`,\n\t * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>`\n\t *\n\t * @since 1.0 (previously called `get_feed_description()` since 0.8)\n\t * @return string|null\n\t */\n\tpublic function get_description()\n\t{\n\t\tif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the copyright info for the feed\n\t *\n\t * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>`\n\t *\n\t * @since 1.0 (previously called `get_feed_copyright()` since 0.8)\n\t * @return string|null\n\t */\n\tpublic function get_copyright()\n\t{\n\t\tif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the language for the feed\n\t *\n\t * Uses `<language>`, `<dc:language>`, or @xml_lang\n\t *\n\t * @since 1.0 (previously called `get_feed_language()` since 0.8)\n\t * @return string|null\n\t */\n\tpublic function get_language()\n\t{\n\t\tif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))\n\t\t{\n\t\t\treturn $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))\n\t\t{\n\t\t\treturn $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))\n\t\t{\n\t\t\treturn $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif (isset($this->data['headers']['content-language']))\n\t\t{\n\t\t\treturn $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the latitude coordinates for the item\n\t *\n\t * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications\n\t *\n\t * Uses `<geo:lat>` or `<georss:point>`\n\t *\n\t * @since 1.0\n\t * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo\n\t * @link http://www.georss.org/ GeoRSS\n\t * @return string|null\n\t */\n\tpublic function get_latitude()\n\t{\n\n\t\tif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))\n\t\t{\n\t\t\treturn (float) $return[0]['data'];\n\t\t}\n\t\telseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\\.[0-9]+)) ((?:-)?[0-9]+(?:\\.[0-9]+))$/', trim($return[0]['data']), $match))\n\t\t{\n\t\t\treturn (float) $match[1];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the longitude coordinates for the feed\n\t *\n\t * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications\n\t *\n\t * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`\n\t *\n\t * @since 1.0\n\t * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo\n\t * @link http://www.georss.org/ GeoRSS\n\t * @return string|null\n\t */\n\tpublic function get_longitude()\n\t{\n\t\tif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))\n\t\t{\n\t\t\treturn (float) $return[0]['data'];\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))\n\t\t{\n\t\t\treturn (float) $return[0]['data'];\n\t\t}\n\t\telseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\\.[0-9]+)) ((?:-)?[0-9]+(?:\\.[0-9]+))$/', trim($return[0]['data']), $match))\n\t\t{\n\t\t\treturn (float) $match[2];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the feed logo's title\n\t *\n\t * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a \"feed logo\" title.\n\t *\n\t * Uses `<image><title>` or `<image><dc:title>`\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_image_title()\n\t{\n\t\tif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the feed logo's URL\n\t *\n\t * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to\n\t * have a \"feed logo\" URL. This points directly to the image itself.\n\t *\n\t * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,\n\t * `<image><title>` or `<image><dc:title>`\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_image_url()\n\t{\n\t\tif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\n\t/**\n\t * Get the feed logo's link\n\t *\n\t * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a \"feed logo\" link. This\n\t * points to a human-readable page that the image should link to.\n\t *\n\t * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,\n\t * `<image><title>` or `<image><dc:title>`\n\t *\n\t * @return string|null\n\t */\n\tpublic function get_image_link()\n\t{\n\t\tif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));\n\t\t}\n\t\telseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))\n\t\t{\n\t\t\treturn $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the feed logo's link\n\t *\n\t * RSS 2.0 feeds are allowed to have a \"feed logo\" width.\n\t *\n\t * Uses `<image><width>` or defaults to 88.0 if no width is specified and\n\t * the feed is an RSS 2.0 feed.\n\t *\n\t * @return int|float|null\n\t */\n\tpublic function get_image_width()\n\t{\n\t\tif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))\n\t\t{\n\t\t\treturn round($return[0]['data']);\n\t\t}\n\t\telseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))\n\t\t{\n\t\t\treturn 88.0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the feed logo's height\n\t *\n\t * RSS 2.0 feeds are allowed to have a \"feed logo\" height.\n\t *\n\t * Uses `<image><height>` or defaults to 31.0 if no height is specified and\n\t * the feed is an RSS 2.0 feed.\n\t *\n\t * @return int|float|null\n\t */\n\tpublic function get_image_height()\n\t{\n\t\tif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))\n\t\t{\n\t\t\treturn round($return[0]['data']);\n\t\t}\n\t\telseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))\n\t\t{\n\t\t\treturn 31.0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get the number of items in the feed\n\t *\n\t * This is well-suited for {@link http://php.net/for for()} loops with\n\t * {@see get_item()}\n\t *\n\t * @param int $max Maximum value to return. 0 for no limit\n\t * @return int Number of items in the feed\n\t */\n\tpublic function get_item_quantity($max = 0)\n\t{\n\t\t$max = (int) $max;\n\t\t$qty = count($this->get_items());\n\t\tif ($max === 0)\n\t\t{\n\t\t\treturn $qty;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn ($qty > $max) ? $max : $qty;\n\t\t}\n\t}\n\n\t/**\n\t * Get a single item from the feed\n\t *\n\t * This is better suited for {@link http://php.net/for for()} loops, whereas\n\t * {@see get_items()} is better suited for\n\t * {@link http://php.net/foreach foreach()} loops.\n\t *\n\t * @see get_item_quantity()\n\t * @since Beta 2\n\t * @param int $key The item that you want to return.  Remember that arrays begin with 0, not 1\n\t * @return SimplePie_Item|null\n\t */\n\tpublic function get_item($key = 0)\n\t{\n\t\t$items = $this->get_items();\n\t\tif (isset($items[$key]))\n\t\t{\n\t\t\treturn $items[$key];\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get all items from the feed\n\t *\n\t * This is better suited for {@link http://php.net/for for()} loops, whereas\n\t * {@see get_items()} is better suited for\n\t * {@link http://php.net/foreach foreach()} loops.\n\t *\n\t * @see get_item_quantity\n\t * @since Beta 2\n\t * @param int $start Index to start at\n\t * @param int $end Number of items to return. 0 for all items after `$start`\n\t * @return array|null List of {@see SimplePie_Item} objects\n\t */\n\tpublic function get_items($start = 0, $end = 0)\n\t{\n\t\tif (!isset($this->data['items']))\n\t\t{\n\t\t\tif (!empty($this->multifeed_objects))\n\t\t\t{\n\t\t\t\t$this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->data['items'] = array();\n\t\t\t\tif ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))\n\t\t\t\t{\n\t\t\t\t\t$keys = array_keys($items);\n\t\t\t\t\tforeach ($keys as $key)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))\n\t\t\t\t{\n\t\t\t\t\t$keys = array_keys($items);\n\t\t\t\t\tforeach ($keys as $key)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))\n\t\t\t\t{\n\t\t\t\t\t$keys = array_keys($items);\n\t\t\t\t\tforeach ($keys as $key)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))\n\t\t\t\t{\n\t\t\t\t\t$keys = array_keys($items);\n\t\t\t\t\tforeach ($keys as $key)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))\n\t\t\t\t{\n\t\t\t\t\t$keys = array_keys($items);\n\t\t\t\t\tforeach ($keys as $key)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!empty($this->data['items']))\n\t\t{\n\t\t\t// If we want to order it by date, check if all items have a date, and then sort it\n\t\t\tif ($this->order_by_date && empty($this->multifeed_objects))\n\t\t\t{\n\t\t\t\tif (!isset($this->data['ordered_items']))\n\t\t\t\t{\n\t\t\t\t\t$do_sort = true;\n\t\t\t\t\tforeach ($this->data['items'] as $item)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!$item->get_date('U'))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$do_sort = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t$item = null;\n\t\t\t\t\t$this->data['ordered_items'] = $this->data['items'];\n\t\t\t\t\tif ($do_sort)\n\t\t\t\t\t{\n\t\t\t\t\t\tusort($this->data['ordered_items'], array(get_class($this), 'sort_items'));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$items = $this->data['ordered_items'];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$items = $this->data['items'];\n\t\t\t}\n\n\t\t\t// Slice the data as desired\n\t\t\tif ($end === 0)\n\t\t\t{\n\t\t\t\treturn array_slice($items, $start);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn array_slice($items, $start, $end);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn array();\n\t\t}\n\t}\n\n\t/**\n\t * Set the favicon handler\n\t *\n\t * @deprecated Use your own favicon handling instead\n\t */\n\tpublic function set_favicon_handler($page = false, $qs = 'i')\n\t{\n\t\t$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;\n\t\ttrigger_error('Favicon handling has been removed, please use your own handling', $level);\n\t\treturn false;\n\t}\n\n\t/**\n\t * Get the favicon for the current feed\n\t *\n\t * @deprecated Use your own favicon handling instead\n\t */\n\tpublic function get_favicon()\n\t{\n\t\t$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;\n\t\ttrigger_error('Favicon handling has been removed, please use your own handling', $level);\n\n\t\tif (($url = $this->get_link()) !== null)\n\t\t{\n\t\t\treturn 'http://g.etfv.co/' . urlencode($url);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Magic method handler\n\t *\n\t * @param string $method Method name\n\t * @param array $args Arguments to the method\n\t * @return mixed\n\t */\n\tpublic function __call($method, $args)\n\t{\n\t\tif (strpos($method, 'subscribe_') === 0)\n\t\t{\n\t\t\t$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;\n\t\t\ttrigger_error('subscribe_*() has been deprecated, implement the callback yourself', $level);\n\t\t\treturn '';\n\t\t}\n\t\tif ($method === 'enable_xml_dump')\n\t\t{\n\t\t\t$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;\n\t\t\ttrigger_error('enable_xml_dump() has been deprecated, use get_raw_data() instead', $level);\n\t\t\treturn false;\n\t\t}\n\n\t\t$class = get_class($this);\n\t\t$trace = debug_backtrace();\n\t\t$file = $trace[0]['file'];\n\t\t$line = $trace[0]['line'];\n\t\ttrigger_error(\"Call to undefined method $class::$method() in $file on line $line\", E_USER_ERROR);\n\t}\n\n\t/**\n\t * Sorting callback for items\n\t *\n\t * @access private\n\t * @param SimplePie $a\n\t * @param SimplePie $b\n\t * @return boolean\n\t */\n\tpublic static function sort_items($a, $b)\n\t{\n\t\treturn $a->get_date('U') <= $b->get_date('U');\n\t}\n\n\t/**\n\t * Merge items from several feeds into one\n\t *\n\t * If you're merging multiple feeds together, they need to all have dates\n\t * for the items or else SimplePie will refuse to sort them.\n\t *\n\t * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings\n\t * @param array $urls List of SimplePie feed objects to merge\n\t * @param int $start Starting item\n\t * @param int $end Number of items to return\n\t * @param int $limit Maximum number of items per feed\n\t * @return array\n\t */\n\tpublic static function merge_items($urls, $start = 0, $end = 0, $limit = 0)\n\t{\n\t\tif (is_array($urls) && sizeof($urls) > 0)\n\t\t{\n\t\t\t$items = array();\n\t\t\tforeach ($urls as $arg)\n\t\t\t{\n\t\t\t\tif ($arg instanceof SimplePie)\n\t\t\t\t{\n\t\t\t\t\t$items = array_merge($items, $arg->get_items(0, $limit));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttrigger_error('Arguments must be SimplePie objects', E_USER_WARNING);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$do_sort = true;\n\t\t\tforeach ($items as $item)\n\t\t\t{\n\t\t\t\tif (!$item->get_date('U'))\n\t\t\t\t{\n\t\t\t\t\t$do_sort = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t$item = null;\n\t\t\tif ($do_sort)\n\t\t\t{\n\t\t\t\tusort($items, array(get_class($urls[0]), 'sort_items'));\n\t\t\t}\n\n\t\t\tif ($end === 0)\n\t\t\t{\n\t\t\t\treturn array_slice($items, $start);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn array_slice($items, $start, $end);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttrigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);\n\t\t\treturn array();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "license.txt",
    "content": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU Affero General Public License is a free, copyleft license for\nsoftware and other kinds of works, specifically designed to ensure\ncooperation with the community in the case of network server software.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nour General Public Licenses are intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  Developers that use our General Public Licenses protect your rights\nwith two steps: (1) assert copyright on the software, and (2) offer\nyou this License which gives you legal permission to copy, distribute\nand/or modify the software.\n\n  A secondary benefit of defending all users' freedom is that\nimprovements made in alternate versions of the program, if they\nreceive widespread use, become available for other developers to\nincorporate.  Many developers of free software are heartened and\nencouraged by the resulting cooperation.  However, in the case of\nsoftware used on network servers, this result may fail to come about.\nThe GNU General Public License permits making a modified version and\nletting the public access it on a server without ever releasing its\nsource code to the public.\n\n  The GNU Affero General Public License is designed specifically to\nensure that, in such cases, the modified source code becomes available\nto the community.  It requires the operator of a network server to\nprovide the source code of the modified version running there to the\nusers of that server.  Therefore, public use of a modified version, on\na publicly accessible server, gives the public access to the source\ncode of the modified version.\n\n  An older license, called the Affero General Public License and\npublished by Affero, was designed to accomplish similar goals.  This is\na different license, not a version of the Affero GPL, but Affero has\nreleased a new version of the Affero GPL which permits relicensing under\nthis license.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU Affero General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Remote Network Interaction; Use with the GNU General Public License.\n\n  Notwithstanding any other provision of this License, if you modify the\nProgram, your modified version must prominently offer all users\ninteracting with it remotely through a computer network (if your version\nsupports such interaction) an opportunity to receive the Corresponding\nSource of your version by providing access to the Corresponding Source\nfrom a network server at no charge, through some standard or customary\nmeans of facilitating copying of software.  This Corresponding Source\nshall include the Corresponding Source for any work covered by version 3\nof the GNU General Public License that is incorporated pursuant to the\nfollowing paragraph.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the work with which it is combined will remain governed by version\n3 of the GNU General Public License.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU Affero General Public License from time to time.  Such new versions\nwill be similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU Affero General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU Affero General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU Affero General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If your software can interact with users remotely through a computer\nnetwork, you should also make sure that it provides a way for users to\nget its source.  For example, if your program is a web application, its\ninterface could display a \"Source\" link that leads users to an archive\nof the code.  There are many ways you could offer source, and different\nsolutions will be better for different programs; see section 13 for the\nspecific requirements.\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU AGPL, see\n<http://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "makefulltextfeed.php",
    "content": "<?php\n// Full-Text RSS: Create Full-Text Feeds\n// Author: Keyvan Minoukadeh\n// Copyright (c) 2013 Keyvan Minoukadeh\n// License: AGPLv3\n// Version: 3.2\n// Date: 2013-05-13\n// More info: http://fivefilters.org/content-only/\n// Help: http://help.fivefilters.org\n\n/*\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n// Usage\n// -----\n// Request this file passing it a web page or feed URL in the querystring: makefulltextfeed.php?url=example.org/article\n// For more request parameters, see http://help.fivefilters.org/customer/portal/articles/226660-usage\n\nerror_reporting(E_ALL ^ E_NOTICE);\nini_set('display_errors', 'On');\nini_set('xdebug.overload_var_dump', '0');\nmb_internal_encoding('UTF-8');\n@set_time_limit(600);\n\n// Deal with magic quotes\nif (get_magic_quotes_gpc()) {\n\t$process = array(&$_GET, &$_POST, &$_REQUEST);\n\twhile (list($key, $val) = each($process)) {\n\t\tforeach ($val as $k => $v) {\n\t\t\tunset($process[$key][$k]);\n\t\t\tif (is_array($v)) {\n\t\t\t\t$process[$key][stripslashes($k)] = $v;\n\t\t\t\t$process[] = &$process[$key][stripslashes($k)];\n\t\t\t} else {\n\t\t\t\t$process[$key][stripslashes($k)] = stripslashes($v);\n\t\t\t}\n\t\t}\n\t}\n\tunset($process);\n}\n\n// set include path\nset_include_path(realpath(dirname(__FILE__).'/libraries').PATH_SEPARATOR.get_include_path());\n\nfunction encodeURI($url) {\n\t// http://php.net/manual/en/function.rawurlencode.php\n\t// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/encodeURI\n\t$reserved = array( '%2D'=>'-','%5F'=>'_','%2E'=>'.','%21'=>'!', '%2A'=>'*', '%27'=>\"'\", '%28'=>'(', '%29'=>')' );\n\t$unescaped = array( '%3B'=>';','%2C'=>',','%2F'=>'/','%3F'=>'?','%3A'=>':', '%40'=>'@','%26'=>'&','%3D'=>'=','%2B'=>'+','%24'=>'$');\n\t$score = array( '%23'=>'#' );\n\n\tstatic $url_entities = null;\n\tif ($url_entities === null) $url_entities = array_merge($reserved, $unescaped, $score);\n\n\t$parsed_url = parse_url($url);\n\n\t$scheme   = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';\n\t$host\t = isset($parsed_url['host']) ? $parsed_url['host'] : '';\n\t$port\t = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';\n\t$user\t = isset($parsed_url['user']) ? $parsed_url['user'] : '';\n\t$pass\t = isset($parsed_url['pass']) ? ':' . $parsed_url['pass']  : '';\n\t$pass\t = ($user || $pass) ? \"$pass@\" : '';\n\t$path\t = isset($parsed_url['path']) ? $parsed_url['path'] : '';\n\t$query\t= isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';\n\t$fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';\n\n\treturn $scheme.$user.$pass.$host.$port.strtr(rawurlencode($path.$query.$fragment), $url_entities);\n}\n\n// Autoloading of classes allows us to include files only when they're\n// needed. If we've got a cached copy, for example, only Zend_Cache is loaded.\nfunction autoload($class_name) {\n\tstatic $dir = null;\n\tif ($dir === null) $dir = dirname(__FILE__).'/libraries/';\n\tstatic $mapping = array(\n\t\t// Include FeedCreator for RSS/Atom creation\n\t\t'FeedWriter' => 'feedwriter/FeedWriter.php',\n\t\t'FeedItem' => 'feedwriter/FeedItem.php',\n\t\t// Include ContentExtractor and Readability for identifying and extracting content from URLs\n\t\t'ContentExtractor' => 'content-extractor/ContentExtractor.php',\n\t\t'SiteConfig' => 'content-extractor/SiteConfig.php',\n\t\t'Readability' => 'readability/Readability.php',\n\t\t// Include Humble HTTP Agent to allow parallel requests and response caching\n\t\t'HumbleHttpAgent' => 'humble-http-agent/HumbleHttpAgent.php',\n\t\t'SimplePie_HumbleHttpAgent' => 'humble-http-agent/SimplePie_HumbleHttpAgent.php',\n\t\t'CookieJar' => 'humble-http-agent/CookieJar.php',\n\t\t// Include Zend Cache to improve performance (cache results)\n\t\t'Zend_Cache' => 'Zend/Cache.php',\n\t\t// Language detect\n\t\t'Text_LanguageDetect' => 'language-detect/LanguageDetect.php',\n\t\t// HTML5 Lib\n\t\t'HTML5_Parser' => 'html5/Parser.php',\n\t\t// htmLawed - used if XSS filter is enabled (xss_filter)\n\t\t'htmLawed' => 'htmLawed/htmLawed2.php'\n\t);\n\tif (isset($mapping[$class_name])) {\n\t\tdebug(\"** Loading class $class_name ({$mapping[$class_name]})\");\n\t\trequire $dir.$mapping[$class_name];\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n}\nspl_autoload_register('autoload');\nrequire dirname(__FILE__).'/libraries/simplepie/autoloader.php';\n\n////////////////////////////////\n// Load config file\n////////////////////////////////\nrequire dirname(__FILE__).'/config.php';\n\n////////////////////////////////\n// Prevent indexing/following by search engines because:\n// 1. The content is already public and presumably indexed (why create duplicates?)\n// 2. Not doing so might increase number of requests from search engines, thus increasing server load\n// Note: feed readers and services such as Yahoo Pipes will not be affected by this header.\n// Note: Using Disallow in a robots.txt file will be more effective (search engines will check\n// that before even requesting makefulltextfeed.php).\n////////////////////////////////\nheader('X-Robots-Tag: noindex, nofollow');\n\n////////////////////////////////\n// Check if service is enabled\n////////////////////////////////\nif (!$options->enabled) {\n\tdie('The full-text RSS service is currently disabled');\n}\n\n////////////////////////////////\n// Debug mode?\n// See the config file for debug options.\n////////////////////////////////\n$debug_mode = false;\nif (isset($_GET['debug']) && intval($_GET['debug']) === 1) {\n\tif ($options->debug === true || $options->debug === 'user') {\n\t\t$debug_mode = true;\n\t} elseif ($options->debug == 'admin') {\n\t\tsession_start();\n\t\t$debug_mode = (intval(@$_SESSION['auth']) === 1);\n\t}\n\tif ($debug_mode) {\n\t\theader('Content-Type: text/html; charset=utf-8');\n\t\techo '<style>body {font:12px \"Lucida Console\", Monaco, monospace;}</style>';\n\t\tdebug('Running in debugging mode...');\n\t} else {\n\t\tif ($options->debug == 'admin') {\n\t\t\tdie('You must be logged in to the <a href=\"admin/\">admin area</a> to see debug output.');\n\t\t} else {\n\t\t\tdie('Debugging is disabled.');\n\t\t}\n\t}\n}\n\n\n////////////////////////////////\n// Check for APC\n////////////////////////////////\n$options->apc = $options->apc && function_exists('apc_add');\nif ($options->apc) {\n\tdebug('APC is enabled and available on server');\n} else {\n\tdebug('APC is disabled or not available on server');\n}\n\n////////////////////////////////\n// Check for smart cache\n////////////////////////////////\n$options->smart_cache = $options->smart_cache && function_exists('apc_inc');\n\n////////////////////////////////\n// Check for feed URL\n////////////////////////////////\nif (!isset($_GET['url'])) {\n\tdie('No URL supplied');\n}\n$url = filter_var(trim($_GET['url']), FILTER_SANITIZE_URL);\nif (strtolower(substr($url, 0, 7)) == 'feed://') {\n\t$url = 'http://'.substr($url, 7);\n}\nif (!preg_match('!^https?://.+!i', $url)) {\n\t$url = 'http://'.$url;\n}\n\n$test = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED);\n// deal with bug http://bugs.php.net/51192 (present in PHP 5.2.13 and PHP 5.3.2)\nif ($test === false) {\n\t$test = filter_var(strtr($url, '-', '_'), FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED);\n}\nif ($test !== false && $test !== null && preg_match('!^https?://!', $url)) {\n\t// all okay\n\tunset($test);\n} else {\n\tdie('Invalid URL supplied');\n}\ndebug(\"Supplied URL: $url\");\n\n/////////////////////////////////\n// Redirect to hide API key\n/////////////////////////////////\nif (isset($_GET['key']) && ($key_index = array_search($_GET['key'], $options->api_keys)) !== false) {\n\t$host = $_SERVER['HTTP_HOST'];\n\t$path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/\\\\');\n\t$_qs_url = (strtolower(substr($url, 0, 7)) == 'http://') ? substr($url, 7) : $url;\n\t$redirect = 'http://'.htmlspecialchars($host.$path).'/makefulltextfeed.php?url='.urlencode($_qs_url);\n\t$redirect .= '&key='.$key_index;\n\t$redirect .= '&hash='.urlencode(sha1($_GET['key'].$url));\n\tif (isset($_GET['html'])) $redirect .= '&html='.urlencode($_GET['html']);\n\tif (isset($_GET['max'])) $redirect .= '&max='.(int)$_GET['max'];\n\tif (isset($_GET['links'])) $redirect .= '&links='.urlencode($_GET['links']);\n\tif (isset($_GET['exc'])) $redirect .= '&exc='.urlencode($_GET['exc']);\n\tif (isset($_GET['format'])) $redirect .= '&format='.urlencode($_GET['format']);\n\tif (isset($_GET['callback'])) $redirect .= '&callback='.urlencode($_GET['callback']);\n\tif (isset($_GET['l'])) $redirect .= '&l='.urlencode($_GET['l']);\n\tif (isset($_GET['xss'])) $redirect .= '&xss';\n\tif (isset($_GET['use_extracted_title'])) $redirect .= '&use_extracted_title';\n\tif (isset($_GET['content'])) $redirect .= '&content='.urlencode($_GET['content']);\n\tif (isset($_GET['summary'])) $redirect .= '&summary='.urlencode($_GET['summary']);\n\tif (isset($_GET['debug'])) $redirect .= '&debug';\n\tif ($debug_mode) {\n\t\tdebug('Redirecting to hide access key, follow URL below to continue');\n\t\tdebug(\"Location: $redirect\");\n\t} else {\n\t\theader(\"Location: $redirect\");\n\t}\n\texit;\n}\n\n///////////////////////////////////////////////\n// Set timezone.\n// Prevents warnings, but needs more testing perhaps if timezone is set in php.ini we\n// don't need to set it at all...\n///////////////////////////////////////////////\nif (!ini_get('date.timezone') || !@date_default_timezone_set(ini_get('date.timezone'))) {\n\tdate_default_timezone_set('UTC');\n}\n\n///////////////////////////////////////////////\n// Check if the request is explicitly for an HTML page\n///////////////////////////////////////////////\n$html_only = (isset($_GET['html']) && (intval($_GET['html']) == 1 || $_GET['html'] == 'true'));\n\n///////////////////////////////////////////////\n// Check if valid key supplied\n///////////////////////////////////////////////\n$valid_key = false;\nif (isset($_GET['key']) && isset($_GET['hash']) && isset($options->api_keys[(int)$_GET['key']])) {\n\t$valid_key = ($_GET['hash'] == sha1($options->api_keys[(int)$_GET['key']].$url));\n}\n$key_index = ($valid_key) ? intval($_GET['key']) : 0;\nif (!$valid_key && $options->key_required) {\n\tdie('A valid key must be supplied');\n}\nif (!$valid_key && isset($_GET['key']) && $_GET['key'] != '') {\n\tdie('The entered key is invalid');\n}\n\nif (file_exists('custom_init.php')) require 'custom_init.php';\n\n///////////////////////////////////////////////\n// Check URL against list of blacklisted URLs\n///////////////////////////////////////////////\nif (!url_allowed($url)) die('URL blocked');\n\n///////////////////////////////////////////////\n// Max entries\n// see config.php to find these values\n///////////////////////////////////////////////\nif (isset($_GET['max'])) {\n\t$max = intval($_GET['max']);\n\tif ($valid_key) {\n\t\t$max = min($max, $options->max_entries_with_key);\n\t} else {\n\t\t$max = min($max, $options->max_entries);\n\t}\n} else {\n\tif ($valid_key) {\n\t\t$max = $options->default_entries_with_key;\n\t} else {\n\t\t$max = $options->default_entries;\n\t}\n}\n\n///////////////////////////////////////////////\n// Link handling\n///////////////////////////////////////////////\nif (isset($_GET['links']) && in_array($_GET['links'], array('preserve', 'footnotes', 'remove'))) {\n\t$links = $_GET['links'];\n} else {\n\t$links = 'preserve';\n}\n\n///////////////////////////////////////////////\n// Favour item titles in feed?\n///////////////////////////////////////////////\n$favour_feed_titles = true;\nif ($options->favour_feed_titles == 'user') {\n\t$favour_feed_titles = !isset($_GET['use_extracted_title']);\n} else {\n\t$favour_feed_titles = $options->favour_feed_titles;\n}\n\n///////////////////////////////////////////////\n// Include full content in output?\n///////////////////////////////////////////////\nif ($options->content === 'user') {\n\tif (isset($_GET['content']) && intval($_GET['content']) === 0) {\n\t\t$options->content = false;\n\t} else {\n\t\t$options->content = true;\n\t}\n}\n\n///////////////////////////////////////////////\n// Include summaries in output?\n///////////////////////////////////////////////\nif ($options->summary === 'user') {\n\tif (isset($_GET['summary']) && intval($_GET['summary']) === 1) {\n\t\t$options->summary = true;\n\t} else {\n\t\t$options->summary = false;\n\t}\n}\n\n///////////////////////////////////////////////\n// Exclude items if extraction fails\n///////////////////////////////////////////////\nif ($options->exclude_items_on_fail === 'user') {\n\t$exclude_on_fail = (isset($_GET['exc']) && (intval($_GET['exc']) === 1));\n} else {\n\t$exclude_on_fail = $options->exclude_items_on_fail;\n}\n\n///////////////////////////////////////////////\n// Detect language\n///////////////////////////////////////////////\nif ($options->detect_language === 'user') {\n\tif (isset($_GET['l'])) {\n\t\t$detect_language = intval($_GET['l']);\n\t} else {\n\t\t$detect_language = 1;\n\t}\n} else {\n\t$detect_language = $options->detect_language;\n}\n\n$use_cld = extension_loaded('cld') && (version_compare(PHP_VERSION, '5.3.0') >= 0);\n\n/////////////////////////////////////\n// Check for valid format\n// (stick to RSS (or RSS as JSON) for the time being)\n/////////////////////////////////////\nif (isset($_GET['format']) && $_GET['format'] == 'json') {\n\t$format = 'json';\n} else {\n\t$format = 'rss';\n}\n\n/////////////////////////////////////\n// Should we do XSS filtering?\n/////////////////////////////////////\nif ($options->xss_filter === 'user') {\n\t$xss_filter = isset($_GET['xss']);\n} else {\n\t$xss_filter = $options->xss_filter;\n}\nif (!$xss_filter && isset($_GET['xss'])) {\n\tdie('XSS filtering is disabled in config');\n}\n\n/////////////////////////////////////\n// Check for JSONP\n// Regex from https://gist.github.com/1217080\n/////////////////////////////////////\n$callback = null;\nif ($format =='json' && isset($_GET['callback'])) {\n\t$callback = trim($_GET['callback']);\n\tforeach (explode('.', $callback) as $_identifier) {\n\t\tif (!preg_match('/^[a-zA-Z_$][0-9a-zA-Z_$]*(?:\\[(?:\".+\"|\\'.+\\'|\\d+)\\])*?$/', $_identifier)) {\n\t\t\tdie('Invalid JSONP callback');\n\t\t}\n\t}\n\tdebug(\"JSONP callback: $callback\");\n}\n\n//////////////////////////////////\n// Enable Cross-Origin Resource Sharing (CORS)\n//////////////////////////////////\nif ($options->cors) header('Access-Control-Allow-Origin: *');\n\n//////////////////////////////////\n// Check for cached copy\n//////////////////////////////////\nif ($options->caching) {\n\tdebug('Caching is enabled...');\n\t$cache_id = md5((int)$max.$url.$links.(int)$favour_feed_titles.(int)$options->content.(int)$options->summary.(int)$xss_filter.(int)$exclude_on_fail.$format.$detect_language);\n\t$check_cache = true;\n\tif ($options->apc === true && $options->smart_cache === true) {\n\t\tapc_add(\"cache.$cache_id\", 0, isset($options->cache_ttl) ? $options->cache_ttl : 10*60);\n\t\t$apc_cache_hits = intval(apc_fetch(\"cache.$cache_id\"));\n\t\tapc_inc(\"cache.$cache_id\");\n\t\tif ($check_cache = ($apc_cache_hits >= 2)) {\n\t\t\tdebug('Cache key found in APC, we\\'ll try to load cache file from disk');\n\t\t} else {\n\t\t\tdebug('Cache key not found in APC');\n\t\t}\n\t}\n\tif ($check_cache === true) {\n\t\t$cache = get_cache();\n\t\tif ($data = $cache->load($cache_id)) {\n\t\t\tif ($debug_mode) {\n\t\t\t\tdebug('Loaded cached copy of RSS');\n\t\t\t\texit;\n\t\t\t}\n\t\t\tif ($format == 'json') {\n\t\t\t\tif ($callback === null) {\n\t\t\t\t\theader('Content-type: application/json; charset=UTF-8');\n\t\t\t\t} else {\n\t\t\t\t\theader('Content-type: application/javascript; charset=UTF-8');\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\theader('Content-type: text/xml; charset=UTF-8');\n\t\t\t\theader('X-content-type-options: nosniff');\n\t\t\t}\n\t\t\tif (headers_sent()) die('Some data has already been output, can\\'t send RSS file');\n\t\t\tif ($callback) {\n\t\t\t\techo \"$callback($data);\";\n\t\t\t} else {\n\t\t\t\techo $data;\n\t\t\t}\n\t\t\texit;\n\t\t}\n\t}\n}\n\n//////////////////////////////////\n// Set Expires header\n//////////////////////////////////\nif (!$debug_mode) {\n\theader('Expires: ' . gmdate('D, d M Y H:i:s', time()+ (isset($options->cache_ttl) ? $options->cache_ttl : 10*60)) . ' GMT');\n}\n\n//////////////////////////////////\n// Set up HTTP agent\n//////////////////////////////////\n$http = new HumbleHttpAgent();\n$http->debug = $debug_mode;\n$http->userAgentMap = $options->user_agents;\n$http->headerOnlyTypes = array_keys($options->content_type_exc);\n$http->rewriteUrls = $options->rewrite_url;\n//$http->initCache($options->cache_dir, $options->cache_directory_level, $options->cache_cleanup, isset($options->http_cache_ttl) ? $options->http_cache_ttl : 12*60*60);\n\n//////////////////////////////////\n// Set up Content Extractor\n//////////////////////////////////\n$extractor = new ContentExtractor(dirname(__FILE__).'/site_config/custom', dirname(__FILE__).'/site_config/standard');\n$extractor->debug = $debug_mode;\nSiteConfig::$debug = $debug_mode;\nSiteConfig::use_apc($options->apc);\n$extractor->fingerprints = $options->fingerprints;\n$extractor->allowedParsers = $options->allowed_parsers;\n\n////////////////////////////////\n// Get RSS/Atom feed\n////////////////////////////////\nif (!$html_only) {\n\tdebug('--------');\n\tdebug(\"Attempting to process URL as feed\");\n\t// Send user agent header showing PHP (prevents a HTML response from feedburner)\n\t$http->userAgentDefault = HumbleHttpAgent::UA_PHP;\n\t// configure SimplePie HTTP extension class to use our HumbleHttpAgent instance\n\tSimplePie_HumbleHttpAgent::set_agent($http);\n\t$feed = new SimplePie();\n\t// some feeds use the text/html content type - force_feed tells SimplePie to process anyway\n\t$feed->force_feed(true);\n\t$feed->set_file_class('SimplePie_HumbleHttpAgent');\n\t//$feed->set_feed_url($url); // colons appearing in the URL's path get encoded\n\t$feed->feed_url = $url;\n\t$feed->set_autodiscovery_level(SIMPLEPIE_LOCATOR_NONE);\n\t$feed->set_timeout(20);\n\t$feed->enable_cache(false);\n\t$feed->set_stupidly_fast(true);\n\t$feed->enable_order_by_date(false); // we don't want to do anything to the feed\n\t$feed->set_url_replacements(array());\n\t// initialise the feed\n\t// the @ suppresses notices which on some servers causes a 500 internal server error\n\t$result = @$feed->init();\n\t//$feed->handle_content_type();\n\t//$feed->get_title();\n\tif ($result && (!is_array($feed->data) || count($feed->data) == 0)) {\n\t\tdie('Sorry, no feed items found');\n\t}\n\t// from now on, we'll identify ourselves as a browser\n\t$http->userAgentDefault = HumbleHttpAgent::UA_BROWSER;\n\t// Enable caching for multiple downloader\n\tif (class_exists('HttpRequestPool')) {\n\t\t$http->method = $http::METHOD_REQUEST_POOL;\n\t} elseif (function_exists('curl_multi_init')) {\n\t\t$http->method = $http::METHOD_CURL_MULTI;\n\t} else {\n\t\t$http->method = $http::METHOD_FILE_GET_CONTENTS;\n\t}\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Our given URL is not a feed, so let's create our own feed with a single item:\n// the given URL. This basically treats all non-feed URLs as if they were\n// single-item feeds.\n////////////////////////////////////////////////////////////////////////////////\n$isDummyFeed = false;\nif ($html_only || !$result) {\n\tdebug('--------');\n\tdebug(\"Constructing a single-item feed from URL\");\n\t$isDummyFeed = true;\n\tunset($feed, $result);\n\t// create single item dummy feed object\n\tclass DummySingleItemFeed {\n\t\tpublic $item;\n\t\tfunction __construct($url) { $this->item = new DummySingleItem($url); }\n\t\tpublic function get_title() { return ''; }\n\t\tpublic function get_description() { return 'Content extracted from '.$this->item->url; }\n\t\tpublic function get_link() { return $this->item->url; }\n\t\tpublic function get_language() { return false; }\n\t\tpublic function get_image_url() { return false; }\n\t\tpublic function get_items($start=0, $max=1) { return array(0=>$this->item); }\n\t}\n\tclass DummySingleItem {\n\t\tpublic $url;\n\t\tfunction __construct($url) { $this->url = $url; }\n\t\tpublic function get_permalink() { return $this->url; }\n\t\tpublic function get_title() { return null; }\n\t\tpublic function get_date($format='') { return false; }\n\t\tpublic function get_author($key=0) { return null; }\n\t\tpublic function get_authors() { return null; }\n\t\tpublic function get_description() { return ''; }\n\t\tpublic function get_enclosure($key=0, $prefer=null) { return null; }\n\t\tpublic function get_enclosures() { return null; }\n\t\tpublic function get_categories() { return null; }\n\t}\n\t$feed = new DummySingleItemFeed($url);\n}\n\n////////////////////////////////////////////\n// Create full-text feed\n////////////////////////////////////////////\n$output = new FeedWriter();\n$output->setTitle(strip_tags($feed->get_title()));\n$output->setDescription(strip_tags($feed->get_description()));\n$output->setXsl('css/feed.xsl'); // Chrome uses this, most browsers ignore it\nif ($valid_key && isset($_GET['pubsub'])) { // used only on fivefilters.org at the moment\n\t$output->addHub('http://fivefilters.superfeedr.com/');\n\t$output->addHub('http://pubsubhubbub.appspot.com/');\n\t$output->setSelf('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);\n}\n$output->setLink($feed->get_link()); // Google Reader uses this for pulling in favicons\nif ($img_url = $feed->get_image_url()) {\n\t$output->setImage($feed->get_title(), $feed->get_link(), $img_url);\n}\n\n////////////////////////////////////////////\n// Loop through feed items\n////////////////////////////////////////////\n$items = $feed->get_items(0, $max);\n// Request all feed items in parallel (if supported)\n$urls_sanitized = array();\n$urls = array();\nforeach ($items as $key => $item) {\n\t$permalink = htmlspecialchars_decode($item->get_permalink());\n\t// Colons in URL path segments get encoded by SimplePie, yet some sites expect them unencoded\n\t$permalink = str_replace('%3A', ':', $permalink);\n\t// simplepie already sanitizes URLs so let's not do it again here.\n\tif ($permalink && !is_cached($permalink)) $urls_sanitized[] = $permalink;\n\t$urls[$key] = encodeURI($permalink);\n}\ndebug('--------');\ndebug('Fetching feed items');\n$http->fetchAll($urls_sanitized);\n\n// count number of items added to full feed\n$item_count = 0;\n\nforeach ($items as $key => $item) {\n\tdebug('--------');\n\n\t$do_content_extraction = true;\n\tdebug('Processing feed item '.sprintf('%02d', $item_count+1).'.');\n\n\t$extraction_successful = false;\n\t$text_sample = null;\n\t$permalink = $urls[$key];\n\tdebug(\"Item URL: $permalink\");\n\n\t$extracted_title = '';\n\t$feed_item_title = $item->get_title();\n\tif ($feed_item_title !== null) {\n\t\t$feed_item_title = strip_tags(htmlspecialchars_decode($feed_item_title));\n\t}\n\n\t$newitem = $output->createNewItem();\n\t$newitem->setTitle($feed_item_title);\n\n\t\tif (isset($permalink) && is_string($permalink)) {\n\t\t\t\t$newitem->setLink($permalink);\n\t\t} else {\n\t\t\t\t$permalink = $item->get_permalink();\n\t\t\t\t$newitem->setLink($permalink);\n\t\t}\n\n\t\tif (isset($permalink) && is_string($permalink) && strlen($permalink) < 9) {\n\t\t\t continue;\n\t\t}\n\n\t//if ($permalink && ($response = $http->get($permalink, true)) && $response['status_code'] < 300) {\n\t// Allowing error codes - some sites return correct content with error status\n\t// e.g. prospectmagazine.co.uk returns 403\n\t\t$cached_page = is_cached($permalink);\n\t\tif ($cached_page) {\n\t\t\tdebug('Loading processed page form cache...');\n\t\t\t$html = get_cached($permalink);\n\t\t\t$extraction_successful = true;\n\t\t} else if ((($response = $http->get($permalink, true)) && ($response['status_code'] < 300 || $response['status_code'] > 400))) {\n\t\t$effective_url = $response['effective_url'];\n\t\tif (!url_allowed($effective_url)) continue;\n\t\t// check if action defined for returned Content-Type\n\t\t$mime_info = get_mime_action_info($response['headers']);\n\t\tif (isset($mime_info['action'])) {\n\t\t\tif ($mime_info['action'] == 'exclude') {\n\t\t\t\tcontinue; // skip this feed item entry\n\t\t\t} elseif ($mime_info['action'] == 'link') {\n\t\t\t\tif ($mime_info['type'] == 'image') {\n\t\t\t\t\t$html = \"<a href=\\\"$effective_url\\\"><img src=\\\"$effective_url\\\" alt=\\\"{$mime_info['name']}\\\" /></a>\";\n\t\t\t\t} else {\n\t\t\t\t\t$html = \"<a href=\\\"$effective_url\\\">Download {$mime_info['name']}</a>\";\n\t\t\t\t}\n\t\t\t\t$extracted_title = $mime_info['name'];\n\t\t\t\t$do_content_extraction = false;\n\t\t\t}\n\t\t}\n\t\tif ($do_content_extraction) {\n\t\t\t$html = $response['body'];\n\t\t\t// remove strange things\n\t\t\t$html = str_replace('</[>', '', $html);\n\t\t\t$html = convert_to_utf8($html, $response['headers']);\n\t\t\t// check site config for single page URL - fetch it if found\n\t\t\t$is_single_page = false;\n\t\t\tif ($single_page_response = getSinglePage($item, $html, $effective_url)) {\n\t\t\t\t$is_single_page = true;\n\t\t\t\t$effective_url = $single_page_response['effective_url'];\n\t\t\t\t// check if action defined for returned Content-Type\n\t\t\t\t$mime_info = get_mime_action_info($single_page_response['headers']);\n\t\t\t\tif (isset($mime_info['action'])) {\n\t\t\t\t\tif ($mime_info['action'] == 'exclude') {\n\t\t\t\t\t\tcontinue; // skip this feed item entry\n\t\t\t\t\t} elseif ($mime_info['action'] == 'link') {\n\t\t\t\t\t\tif ($mime_info['type'] == 'image') {\n\t\t\t\t\t\t\t$html = \"<a href=\\\"$effective_url\\\"><img src=\\\"$effective_url\\\" alt=\\\"{$mime_info['name']}\\\" /></a>\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$html = \"<a href=\\\"$effective_url\\\">Download {$mime_info['name']}</a>\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$extracted_title = $mime_info['name'];\n\t\t\t\t\t\t$do_content_extraction = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ($do_content_extraction) {\n\t\t\t\t\t$html = $single_page_response['body'];\n\t\t\t\t\t// remove strange things\n\t\t\t\t\t$html = str_replace('</[>', '', $html);\n\t\t\t\t\t$html = convert_to_utf8($html, $single_page_response['headers']);\n\t\t\t\t\tdebug(\"Retrieved single-page view from $effective_url\");\n\t\t\t\t}\n\t\t\t\tunset($single_page_response);\n\t\t\t}\n\t\t}\n\t\tif ($do_content_extraction) {\n\t\t\tdebug('--------');\n\t\t\tdebug('Attempting to extract content');\n\t\t\t$extraction_successful = $extractor->process($html, $effective_url);\n\t\t\t$readability = $extractor->readability;\n\t\t\t$content_block = ($extraction_successful) ? $extractor->getContent() : null;\n\t\t\t$extracted_title = ($extraction_successful) ? $extractor->getTitle() : '';\n\t\t\t// Deal with multi-page articles\n\t\t\t//die('Next: '.$extractor->getNextPageUrl());\n\t\t\t$is_multi_page = (!$is_single_page && $extraction_successful && $extractor->getNextPageUrl());\n\t\t\tif ($options->multipage && $is_multi_page && $options->content) {\n\t\t\t\tdebug('--------');\n\t\t\t\tdebug('Attempting to process multi-page article');\n\t\t\t\t$multi_page_urls = array();\n\t\t\t\t$multi_page_content = array();\n\t\t\t\twhile ($next_page_url = $extractor->getNextPageUrl()) {\n\t\t\t\t\tdebug('--------');\n\t\t\t\t\tdebug('Processing next page: '.$next_page_url);\n\t\t\t\t\t// If we've got URL, resolve against $url\n\t\t\t\t\tif ($next_page_url = makeAbsoluteStr($effective_url, $next_page_url)) {\n\t\t\t\t\t\t// check it's not what we have already!\n\t\t\t\t\t\tif (!in_array($next_page_url, $multi_page_urls)) {\n\t\t\t\t\t\t\t// it's not, so let's attempt to fetch it\n\t\t\t\t\t\t\t$multi_page_urls[] = $next_page_url;\n\t\t\t\t\t\t\t$_prev_ref = $http->referer;\n\t\t\t\t\t\t\tif (($response = $http->get($next_page_url, true)) && $response['status_code'] < 300) {\n\t\t\t\t\t\t\t\t// make sure mime type is not something with a different action associated\n\t\t\t\t\t\t\t\t$page_mime_info = get_mime_action_info($response['headers']);\n\t\t\t\t\t\t\t\tif (!isset($page_mime_info['action'])) {\n\t\t\t\t\t\t\t\t\t$html = $response['body'];\n\t\t\t\t\t\t\t\t\t// remove strange things\n\t\t\t\t\t\t\t\t\t$html = str_replace('</[>', '', $html);\n\t\t\t\t\t\t\t\t\t$html = convert_to_utf8($html, $response['headers']);\n\t\t\t\t\t\t\t\t\tif ($extractor->process($html, $next_page_url)) {\n\t\t\t\t\t\t\t\t\t\t$multi_page_content[] = $extractor->getContent();\n\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t} else { debug('Failed to extract content'); }\n\t\t\t\t\t\t\t\t} else { debug('MIME type requires different action'); }\n\t\t\t\t\t\t\t} else { debug('Failed to fetch URL'); }\n\t\t\t\t\t\t} else { debug('URL already processed'); }\n\t\t\t\t\t} else { debug('Failed to resolve against '.$effective_url); }\n\t\t\t\t\t// failed to process next_page_url, so cancel further requests\n\t\t\t\t\t$multi_page_content = array();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// did we successfully deal with this multi-page article?\n\t\t\t\tif (empty($multi_page_content)) {\n\t\t\t\t\tdebug('Failed to extract all parts of multi-page article, so not going to include them');\n\t\t\t\t\t$_page = $readability->dom->createElement('p');\n\t\t\t\t\t$_page->innerHTML = '<em>This article appears to continue on subsequent pages which we could not extract</em>';\n\t\t\t\t\t$multi_page_content[] = $_page;\n\t\t\t\t}\n\t\t\t\tforeach ($multi_page_content as $_page) {\n\t\t\t\t\t$_page = $content_block->ownerDocument->importNode($_page, true);\n\t\t\t\t\t$content_block->appendChild($_page);\n\t\t\t\t}\n\t\t\t\tunset($multi_page_urls, $multi_page_content, $page_mime_info, $next_page_url, $_page);\n\t\t\t}\n\t\t}\n\t\t// use extracted title for both feed and item title if we're using single-item dummy feed\n\t\tif ($isDummyFeed) {\n\t\t\t$output->setTitle($extracted_title);\n\t\t\t$newitem->setTitle($extracted_title);\n\t\t} else {\n\t\t\t// use extracted title instead of feed item title?\n\t\t\tif (!$favour_feed_titles && $extracted_title != '') {\n\t\t\t\tdebug('Using extracted title in generated feed');\n\t\t\t\t$newitem->setTitle($extracted_title);\n\t\t\t}\n\t\t}\n\t}\n\tif ($do_content_extraction) {\n\t\t// if we failed to extract content...\n\t\tif (!$extraction_successful) {\n\t\t\tif ($exclude_on_fail) {\n\t\t\t\tdebug('Failed to extract, so skipping (due to exclude on fail parameter)');\n\t\t\t\tcontinue; // skip this and move to next item\n\t\t\t}\n\t\t\t//TODO: get text sample for language detection\n\t\t\t$html = $options->error_message;\n\t\t\t// keep the original item description\n\t\t\t$html .= $item->get_description();\n\t\t} else {\n\t\t\tif (!$cached_page) {\n\t\t\t\t$readability->clean($content_block, 'select');\n\t\t\t\tif ($options->rewrite_relative_urls) makeAbsolute($effective_url, $content_block);\n\t\t\t\t// footnotes\n\t\t\t\tif (($links == 'footnotes') && (strpos($effective_url, 'wikipedia.org') === false)) {\n\t\t\t\t\t$readability->addFootnotes($content_block);\n\t\t\t\t}\n\t\t\t\t// remove nesting: <div><div><div><p>test</p></div></div></div> = <p>test</p>\n\t\t\t\twhile ($content_block->childNodes->length == 1 && $content_block->firstChild->nodeType === XML_ELEMENT_NODE) {\n\t\t\t\t\t// only follow these tag names\n\t\t\t\t\tif (!in_array(strtolower($content_block->tagName), array('div', 'article', 'section', 'header', 'footer'))) break;\n\t\t\t\t\t$content_block = $content_block->firstChild;\n\t\t\t\t}\n\t\t\t\t// convert content block to HTML string\n\t\t\t\t// Need to preserve things like body: //img[@id='feature']\n\n\t\t\t\tif (in_array(strtolower($content_block->tagName), array('div', 'article', 'section', 'header', 'footer'))) {\n\t\t\t\t\t$html = $content_block->innerHTML;\n\t\t\t\t} else {\n\t\t\t\t\t$html = $content_block->ownerDocument->saveXML($content_block); // essentially outerHTML\n\t\t\t\t}\n\n\t\t\t\t// post-processing cleanup\n\t\t\t\t$html = preg_replace('!<p>[\\s\\h\\v]*</p>!u', '', $html);\n\t\t\t\tif ($links == 'remove') {\n\t\t\t\t\t$html = preg_replace('!</?a[^>]*>!', '', $html);\n\t\t\t\t}\n\t\t\t\t// get text sample for language detection\n\t\t\t\t$text_sample = strip_tags(substr($html, 0, 500));\n\t\t\t\tif ($options->message_to_prepend) $html = make_substitutions($options->message_to_prepend).$html;\n\t\t\t\tif ($options->message_to_append) $html .= make_substitutions($options->message_to_append);\n\n\t\t\t\t// filter XSS\n\t\t\t\tif ($xss_filter) {\n\t\t\t\t\tdebug('Filtering HTML to remove XSS');\n\t\t\t\t\t$html = htmLawed::hl($html, array('safe'=>1, 'deny_attribute'=>'style', 'comment'=>1, 'cdata'=>1));\n\t\t\t\t}\n\n\t\t\t\tset_cached($permalink, $html);\n\t\t\t}\n\t\t}\n\t}\n\n\t$newitem->addElement('guid', $item->get_permalink(), array('isPermaLink'=>'true'));\n\n\t// add content\n\tif ($options->summary === true) {\n\t\t// get summary\n\t\t$summary = '';\n\t\tif (!$do_content_extraction) {\n\t\t\t$summary = $html;\n\t\t} else {\n\t\t\t// Try to get first few paragraphs\n\t\t\tif (isset($content_block) && ($content_block instanceof DOMElement)) {\n\t\t\t\t$_paras = $content_block->getElementsByTagName('p');\n\t\t\t\tforeach ($_paras as $_para) {\n\t\t\t\t\t$summary .= preg_replace(\"/[\\n\\r\\t ]+/\", ' ', $_para->textContent).' ';\n\t\t\t\t\tif (strlen($summary) > 200) break;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$summary = $html;\n\t\t\t}\n\t\t}\n\t\t$summary = get_excerpt($summary);\n\t\t$newitem->setDescription($summary);\n\t\tif ($options->content) $newitem->setElement('content:encoded', $html);\n\t\tunset($_paras, $_para, $content_block);\n\t} else {\n\t\tif ($options->content) $newitem->setDescription($html);\n\t\tunset($content_block);\n\t}\n\n\t// set date\n\tif ((int)$item->get_date('U') > 0) {\n\t\t$newitem->setDate((int)$item->get_date('U'));\n\t} elseif ($extractor->getDate()) {\n\t\t$newitem->setDate($extractor->getDate());\n\t}\n\n\t// add authors\n\tif ($authors = $item->get_authors()) {\n\t\tforeach ($authors as $author) {\n\t\t\t// for some feeds, SimplePie stores author's name as email, e.g. http://feeds.feedburner.com/nymag/intel\n\t\t\tif ($author->get_name() !== null) {\n\t\t\t\t$newitem->addElement('dc:creator', $author->get_name());\n\t\t\t} elseif ($author->get_email() !== null) {\n\t\t\t\t$newitem->addElement('dc:creator', $author->get_email());\n\t\t\t}\n\t\t}\n\t} elseif ($authors = $extractor->getAuthors()) {\n\t\t//TODO: make sure the list size is reasonable\n\t\tforeach ($authors as $author) {\n\t\t\t// TODO: xpath often selects authors from other articles linked from the page.\n\t\t\t// for now choose first item\n\t\t\t$newitem->addElement('dc:creator', $author);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// add language\n\tif ($detect_language) {\n\t\t$language = $extractor->getLanguage();\n\t\tif (!$language) $language = $feed->get_language();\n\t\tif (($detect_language == 3 || (!$language && $detect_language == 2)) && $text_sample) {\n\t\t\ttry {\n\t\t\t\tif ($use_cld) {\n\t\t\t\t\t// Use PHP-CLD extension\n\t\t\t\t\t$php_cld = 'CLD\\detect'; // in quotes to prevent PHP 5.2 parse error\n\t\t\t\t\t$res = $php_cld($text_sample);\n\t\t\t\t\tif (is_array($res) && count($res) > 0) {\n\t\t\t\t\t\t$language = $res[0]['code'];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t//die('what');\n\t\t\t\t\t// Use PEAR's Text_LanguageDetect\n\t\t\t\t\tif (!isset($l))\t{\n\t\t\t\t\t\t$l = new Text_LanguageDetect();\n\t\t\t\t\t\t$l->setNameMode(2); // return ISO 639-1 codes (e.g. \"en\")\n\t\t\t\t\t}\n\t\t\t\t\t$l_result = $l->detect($text_sample, 1);\n\t\t\t\t\tif (count($l_result) > 0) {\n\t\t\t\t\t\t$language = key($l_result);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (Exception $e) {\n\t\t\t\t//die('error: '.$e);\n\t\t\t\t// do nothing\n\t\t\t}\n\t\t}\n\t\tif ($language && (strlen($language) < 7)) {\n\t\t\t$newitem->addElement('dc:language', $language);\n\t\t}\n\t}\n\n\t// add MIME type (if it appeared in our exclusions lists)\n\tif (isset($mime_info['mime'])) $newitem->addElement('dc:format', $mime_info['mime']);\n\t// add effective URL (URL after redirects)\n\tif (isset($effective_url)) {\n\t\t//TODO: ensure $effective_url is valid witout - sometimes it causes problems, e.g.\n\t\t//http://www.siasat.pk/forum/showthread.php?108883-Pakistan-Chowk-by-Rana-Mubashir--25th-March-2012-Special-Program-from-Liari-(Karachi)\n\t\t//temporary measure: use utf8_encode()\n\t\t$newitem->addElement('dc:identifier', remove_url_cruft(utf8_encode($effective_url)));\n\t} else {\n\t\t$newitem->addElement('dc:identifier', remove_url_cruft($item->get_permalink()));\n\t}\n\n\t// add categories\n\tif ($categories = $item->get_categories()) {\n\t\tforeach ($categories as $category) {\n\t\t\tif ($category->get_label() !== null) {\n\t\t\t\t$newitem->addElement('category', $category->get_label());\n\t\t\t}\n\t\t}\n\t}\n\n\t// check for enclosures\n\tif ($options->keep_enclosures) {\n\t\tif ($enclosures = $item->get_enclosures()) {\n\t\t\tforeach ($enclosures as $enclosure) {\n\t\t\t\t// thumbnails\n\t\t\t\tforeach ((array)$enclosure->get_thumbnails() as $thumbnail) {\n\t\t\t\t\t$newitem->addElement('media:thumbnail', '', array('url'=>$thumbnail));\n\t\t\t\t}\n\t\t\t\tif (!$enclosure->get_link()) continue;\n\t\t\t\t$enc = array();\n\t\t\t\t// Media RSS spec ($enc): http://search.yahoo.com/mrss\n\t\t\t\t// SimplePie methods ($enclosure): http://simplepie.org/wiki/reference/start#methods4\n\t\t\t\t$enc['url'] = $enclosure->get_link();\n\t\t\t\tif ($enclosure->get_length()) $enc['fileSize'] = $enclosure->get_length();\n\t\t\t\tif ($enclosure->get_type()) $enc['type'] = $enclosure->get_type();\n\t\t\t\tif ($enclosure->get_medium()) $enc['medium'] = $enclosure->get_medium();\n\t\t\t\tif ($enclosure->get_expression()) $enc['expression'] = $enclosure->get_expression();\n\t\t\t\tif ($enclosure->get_bitrate()) $enc['bitrate'] = $enclosure->get_bitrate();\n\t\t\t\tif ($enclosure->get_framerate()) $enc['framerate'] = $enclosure->get_framerate();\n\t\t\t\tif ($enclosure->get_sampling_rate()) $enc['samplingrate'] = $enclosure->get_sampling_rate();\n\t\t\t\tif ($enclosure->get_channels()) $enc['channels'] = $enclosure->get_channels();\n\t\t\t\tif ($enclosure->get_duration()) $enc['duration'] = $enclosure->get_duration();\n\t\t\t\tif ($enclosure->get_height()) $enc['height'] = $enclosure->get_height();\n\t\t\t\tif ($enclosure->get_width()) $enc['width'] = $enclosure->get_width();\n\t\t\t\tif ($enclosure->get_language()) $enc['lang'] = $enclosure->get_language();\n\t\t\t\t$newitem->addElement('media:content', '', $enc);\n\t\t\t}\n\t\t}\n\t}\n\t$output->addItem($newitem);\n\tunset($html);\n\t$item_count++;\n}\n\n// output feed\ndebug('Done!');\n/*\nif ($debug_mode) {\n\t$_apc_data = apc_cache_info('user');\n\tvar_dump($_apc_data); exit;\n}\n*/\nif (!$debug_mode) {\n\tif ($callback) echo \"$callback(\"; // if $callback is set, $format also == 'json'\n\tif ($format == 'json') $output->setFormat(($callback === null) ? JSON : JSONP);\n\t$add_to_cache = ($options->caching === true);\n\t// is smart cache mode enabled?\n\tif ($add_to_cache && $options->apc === true && $options->smart_cache === true) {\n\t\t// yes, so only cache if this is the second request for this URL\n\t\t$add_to_cache = ($apc_cache_hits >= 2);\n\t\t// purge cache\n\t\tif ($options->cache_cleanup > 0) {\n\t\t\tif (rand(1, $options->cache_cleanup) == 1) {\n\t\t\t\t// apc purge code adapted from from http://www.thimbleopensource.com/tutorials-snippets/php-apc-expunge-script\n\t\t\t\t$_apc_data = apc_cache_info('user');\n\t\t\t\tforeach ($_apc_data['cache_list'] as $_apc_item) {\n\t\t\t\t  if ($_apc_item['ttl'] > 0 && ($_apc_item['ttl'] + $_apc_item['creation_time'] < time())) {\n\t\t\t\t\tapc_delete($_apc_item['info']);\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif ($add_to_cache) {\n\t\tob_start();\n\t\t$output->genarateFeed();\n\t\t$output = ob_get_contents();\n\t\tob_end_clean();\n\t\tif ($html_only && $item_count == 0) {\n\t\t\t// do not cache - in case of temporary server glitch at source URL\n\t\t} else {\n\t\t\t$cache = get_cache();\n\t\t\t$cache->save($output, $cache_id);\n\t\t}\n\t\techo $output;\n\t} else {\n\t\t$output->genarateFeed();\n\t}\n\tif ($callback) echo ');';\n}\n\n///////////////////////////////\n// HELPER FUNCTIONS\n///////////////////////////////\n\n// Adapted from WordPress: http://core.trac.wordpress.org/browser/tags/3.5.1/wp-includes/formatting.php#L2173\nfunction get_excerpt($text, $num_words=55, $more=null) {\n\tif (null === $more) $more = '&hellip;';\n\t$text = strip_tags($text);\n\t//TODO: Check if word count is based on single characters (East Asian characters)\n\t/*\n\tif (1==2) {\n\t\t$text = trim(preg_replace(\"/[\\n\\r\\t ]+/\", ' ', $text), ' ');\n\t\tpreg_match_all('/./u', $text, $words_array);\n\t\t$words_array = array_slice($words_array[0], 0, $num_words + 1);\n\t\t$sep = '';\n\t} else {\n\t\t$words_array = preg_split(\"/[\\n\\r\\t ]+/\", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY);\n\t\t$sep = ' ';\n\t}\n\t*/\n\t$words_array = preg_split(\"/[\\n\\r\\t ]+/\", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY);\n\t$sep = ' ';\n\tif (count($words_array) > $num_words) {\n\t\tarray_pop($words_array);\n\t\t$text = implode($sep, $words_array);\n\t\t$text = $text.$more;\n\t} else {\n\t\t$text = implode($sep, $words_array);\n\t}\n\t// trim whitespace at beginning or end of string\n\t// See: http://stackoverflow.com/questions/4166896/trim-unicode-whitespace-in-php-5-2\n\t$text = preg_replace('/^[\\pZ\\pC]+|[\\pZ\\pC]+$/u', '', $text);\n\treturn $text;\n}\n\nfunction url_allowed($url) {\n\tglobal $options;\n\tif (!empty($options->allowed_urls)) {\n\t\t$allowed = false;\n\t\tforeach ($options->allowed_urls as $allowurl) {\n\t\t\tif (stristr($url, $allowurl) !== false) {\n\t\t\t\t$allowed = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!$allowed) return false;\n\t} else {\n\t\tforeach ($options->blocked_urls as $blockurl) {\n\t\t\tif (stristr($url, $blockurl) !== false) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n\n//////////////////////////////////////////////\n// Convert $html to UTF8\n// (uses HTTP headers and HTML to find encoding)\n// adapted from http://stackoverflow.com/questions/910793/php-detect-encoding-and-make-everything-utf-8\n//////////////////////////////////////////////\nfunction convert_to_utf8($html, $header=null)\n{\n\t$encoding = null;\n\tif ($html || $header) {\n\t\tif (is_array($header)) $header = implode(\"\\n\", $header);\n\t\tif (!$header || !preg_match_all('/^Content-Type:\\s+([^;]+)(?:;\\s*charset=[\"\\']?([^;\"\\'\\n]*))?/im', $header, $match, PREG_SET_ORDER)) {\n\t\t\t// error parsing the response\n\t\t\tdebug('Could not find Content-Type header in HTTP response');\n\t\t} else {\n\t\t\t$match = end($match); // get last matched element (in case of redirects)\n\t\t\tif (isset($match[2])) $encoding = trim($match[2], \"\\\"' \\r\\n\\0\\x0B\\t\");\n\t\t}\n\t\t// TODO: check to see if encoding is supported (can we convert it?)\n\t\t// If it's not, result will be empty string.\n\t\t// For now we'll check for invalid encoding types returned by some sites, e.g. 'none'\n\t\t// Problem URL: http://facta.co.jp/blog/archives/20111026001026.html\n\t\tif (!$encoding || $encoding == 'none') {\n\t\t\t// search for encoding in HTML - only look at the first 50000 characters\n\t\t\t// Why 50000? See, for example, http://www.lemonde.fr/festival-de-cannes/article/2012/05/23/deux-cretes-en-goguette-sur-la-croisette_1705732_766360.html\n\t\t\t// TODO: improve this so it looks at smaller chunks first\n\t\t\t$html_head = substr($html, 0, 50000);\n\t\t\tif (preg_match('/^<\\?xml\\s+version=(?:\"[^\"]*\"|\\'[^\\']*\\')\\s+encoding=(\"[^\"]*\"|\\'[^\\']*\\')/s', $html_head, $match)) {\n\t\t\t\t$encoding = trim($match[1], '\"\\'');\n\t\t\t} elseif (preg_match('/<meta\\s+http-equiv=[\"\\']?Content-Type[\"\\']? content=[\"\\'][^;]+;\\s*charset=[\"\\']?([^;\"\\'>]+)/i', $html_head, $match)) {\n\t\t\t\t$encoding = trim($match[1]);\n\t\t\t} elseif (preg_match_all('/<meta\\s+([^>]+)>/i', $html_head, $match)) {\n\t\t\t\tforeach ($match[1] as $_test) {\n\t\t\t\t\tif (preg_match('/charset=[\"\\']?([^\"\\']+)/i', $_test, $_m)) {\n\t\t\t\t\t\t$encoding = trim($_m[1]);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (isset($encoding)) $encoding = trim($encoding);\n\t\t// trim is important here!\n\t\tif (!$encoding || (strtolower($encoding) == 'iso-8859-1')) {\n\t\t\t// replace MS Word smart qutoes\n\t\t\t$trans = array();\n\t\t\t$trans[chr(130)] = '&sbquo;';\t// Single Low-9 Quotation Mark\n\t\t\t$trans[chr(131)] = '&fnof;';\t// Latin Small Letter F With Hook\n\t\t\t$trans[chr(132)] = '&bdquo;';\t// Double Low-9 Quotation Mark\n\t\t\t$trans[chr(133)] = '&hellip;';\t// Horizontal Ellipsis\n\t\t\t$trans[chr(134)] = '&dagger;';\t// Dagger\n\t\t\t$trans[chr(135)] = '&Dagger;';\t// Double Dagger\n\t\t\t$trans[chr(136)] = '&circ;';\t// Modifier Letter Circumflex Accent\n\t\t\t$trans[chr(137)] = '&permil;';\t// Per Mille Sign\n\t\t\t$trans[chr(138)] = '&Scaron;';\t// Latin Capital Letter S With Caron\n\t\t\t$trans[chr(139)] = '&lsaquo;';\t// Single Left-Pointing Angle Quotation Mark\n\t\t\t$trans[chr(140)] = '&OElig;';\t// Latin Capital Ligature OE\n\t\t\t$trans[chr(145)] = '&lsquo;';\t// Left Single Quotation Mark\n\t\t\t$trans[chr(146)] = '&rsquo;';\t// Right Single Quotation Mark\n\t\t\t$trans[chr(147)] = '&ldquo;';\t// Left Double Quotation Mark\n\t\t\t$trans[chr(148)] = '&rdquo;';\t// Right Double Quotation Mark\n\t\t\t$trans[chr(149)] = '&bull;';\t// Bullet\n\t\t\t$trans[chr(150)] = '&ndash;';\t// En Dash\n\t\t\t$trans[chr(151)] = '&mdash;';\t// Em Dash\n\t\t\t$trans[chr(152)] = '&tilde;';\t// Small Tilde\n\t\t\t$trans[chr(153)] = '&trade;';\t// Trade Mark Sign\n\t\t\t$trans[chr(154)] = '&scaron;';\t// Latin Small Letter S With Caron\n\t\t\t$trans[chr(155)] = '&rsaquo;';\t// Single Right-Pointing Angle Quotation Mark\n\t\t\t$trans[chr(156)] = '&oelig;';\t// Latin Small Ligature OE\n\t\t\t$trans[chr(159)] = '&Yuml;';\t// Latin Capital Letter Y With Diaeresis\n\t\t\t$html = strtr($html, $trans);\n\t\t}\n\t\tif (!$encoding) {\n\t\t\tdebug('No character encoding found, so treating as UTF-8');\n\t\t\t$encoding = 'utf-8';\n\t\t} else {\n\t\t\tdebug('Character encoding: '.$encoding);\n\t\t\tif (strtolower($encoding) != 'utf-8') {\n\t\t\t\tdebug('Converting to UTF-8');\n\t\t\t\t$html = SimplePie_Misc::change_encoding($html, $encoding, 'utf-8');\n\t\t\t}\n\t\t}\n\t}\n\treturn $html;\n}\n\nfunction makeAbsolute($base, $elem) {\n\t$base = new SimplePie_IRI($base);\n\t// remove '//' in URL path (used to prevent URLs from resolving properly)\n\t// TODO: check if this is still the case\n\tif (isset($base->path)) $base->path = preg_replace('!//+!', '/', $base->path);\n\tforeach(array('a'=>'href', 'img'=>'src') as $tag => $attr) {\n\t\t$elems = $elem->getElementsByTagName($tag);\n\t\tfor ($i = $elems->length-1; $i >= 0; $i--) {\n\t\t\t$e = $elems->item($i);\n\t\t\t//$e->parentNode->replaceChild($articleContent->ownerDocument->createTextNode($e->textContent), $e);\n\t\t\tmakeAbsoluteAttr($base, $e, $attr);\n\t\t}\n\t\tif (strtolower($elem->tagName) == $tag) makeAbsoluteAttr($base, $elem, $attr);\n\t}\n}\nfunction makeAbsoluteAttr($base, $e, $attr) {\n\tif ($e->hasAttribute($attr)) {\n\t\t// Trim leading and trailing white space. I don't really like this but\n\t\t// unfortunately it does appear on some sites. e.g.  <img src=\" /path/to/image.jpg\" />\n\t\t$url = trim(str_replace('%20', ' ', $e->getAttribute($attr)));\n\t\t$url = str_replace(' ', '%20', $url);\n\t\tif (!preg_match('!https?://!i', $url)) {\n\t\t\tif ($absolute = SimplePie_IRI::absolutize($base, $url)) {\n\t\t\t\t$e->setAttribute($attr, $absolute);\n\t\t\t}\n\t\t}\n\t}\n}\nfunction makeAbsoluteStr($base, $url) {\n\t$base = new SimplePie_IRI($base);\n\t// remove '//' in URL path (causes URLs not to resolve properly)\n\tif (isset($base->path)) $base->path = preg_replace('!//+!', '/', $base->path);\n\tif (preg_match('!^https?://!i', $url)) {\n\t\t// already absolute\n\t\treturn $url;\n\t} else {\n\t\tif ($absolute = SimplePie_IRI::absolutize($base, $url)) {\n\t\t\treturn $absolute;\n\t\t}\n\t\treturn false;\n\t}\n}\n// returns single page response, or false if not found\nfunction getSinglePage($item, $html, $url) {\n\tglobal $http, $extractor;\n\tdebug('Looking for site config files to see if single page link exists');\n\t$site_config = $extractor->buildSiteConfig($url, $html);\n\t$splink = null;\n\tif (!empty($site_config->single_page_link)) {\n\t\t$splink = $site_config->single_page_link;\n\t} elseif (!empty($site_config->single_page_link_in_feed)) {\n\t\t// single page link xpath is targeted at feed\n\t\t$splink = $site_config->single_page_link_in_feed;\n\t\t// so let's replace HTML with feed item description\n\t\t$html = $item->get_description();\n\t}\n\tif (isset($splink)) {\n\t\t// Build DOM tree from HTML\n\t\t$readability = new Readability($html, $url);\n\t\t$xpath = new DOMXPath($readability->dom);\n\t\t// Loop through single_page_link xpath expressions\n\t\t$single_page_url = null;\n\t\tforeach ($splink as $pattern) {\n\t\t\t$elems = @$xpath->evaluate($pattern, $readability->dom);\n\t\t\tif (is_string($elems)) {\n\t\t\t\t$single_page_url = trim($elems);\n\t\t\t\tbreak;\n\t\t\t} elseif ($elems instanceof DOMNodeList && $elems->length > 0) {\n\t\t\t\tforeach ($elems as $item) {\n\t\t\t\t\tif ($item instanceof DOMElement && $item->hasAttribute('href')) {\n\t\t\t\t\t\t$single_page_url = $item->getAttribute('href');\n\t\t\t\t\t\tbreak 2;\n\t\t\t\t\t} elseif ($item instanceof DOMAttr && $item->value) {\n\t\t\t\t\t\t$single_page_url = $item->value;\n\t\t\t\t\t\tbreak 2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// If we've got URL, resolve against $url\n\t\tif (isset($single_page_url) && ($single_page_url = makeAbsoluteStr($url, $single_page_url))) {\n\t\t\t// check it's not what we have already!\n\t\t\tif ($single_page_url != $url) {\n\t\t\t\t// it's not, so let's try to fetch it...\n\t\t\t\t$_prev_ref = $http->referer;\n\t\t\t\t$http->referer = $single_page_url;\n\t\t\t\tif (($response = $http->get($single_page_url, true)) && $response['status_code'] < 300) {\n\t\t\t\t\t$http->referer = $_prev_ref;\n\t\t\t\t\treturn $response;\n\t\t\t\t}\n\t\t\t\t$http->referer = $_prev_ref;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n// based on content-type http header, decide what to do\n// param: HTTP headers string\n// return: array with keys: 'mime', 'type', 'subtype', 'action', 'name'\n// e.g. array('mime'=>'image/jpeg', 'type'=>'image', 'subtype'=>'jpeg', 'action'=>'link', 'name'=>'Image')\nfunction get_mime_action_info($headers) {\n\tglobal $options;\n\t// check if action defined for returned Content-Type\n\t$info = array();\n\tif (preg_match('!^Content-Type:\\s*(([-\\w]+)/([-\\w\\+]+))!im', $headers, $match)) {\n\t\t// look for full mime type (e.g. image/jpeg) or just type (e.g. image)\n\t\t// match[1] = full mime type, e.g. image/jpeg\n\t\t// match[2] = first part, e.g. image\n\t\t// match[3] = last part, e.g. jpeg\n\t\t$info['mime'] = strtolower(trim($match[1]));\n\t\t$info['type'] = strtolower(trim($match[2]));\n\t\t$info['subtype'] = strtolower(trim($match[3]));\n\t\tforeach (array($info['mime'], $info['type']) as $_mime) {\n\t\t\tif (isset($options->content_type_exc[$_mime])) {\n\t\t\t\t$info['action'] = $options->content_type_exc[$_mime]['action'];\n\t\t\t\t$info['name'] = $options->content_type_exc[$_mime]['name'];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn $info;\n}\n\nfunction remove_url_cruft($url) {\n\t// remove google analytics for the time being\n\t// regex adapted from http://navitronic.co.uk/2010/12/removing-google-analytics-cruft-from-urls/\n\t// https://gist.github.com/758177\n\treturn preg_replace('/(\\?|\\&)utm_[a-z]+=[^\\&]+/', '', $url);\n}\n\nfunction make_substitutions($string) {\n\tif ($string == '') return $string;\n\tglobal $item, $effective_url;\n\t$string = str_replace('{url}', htmlspecialchars($item->get_permalink()), $string);\n\t$string = str_replace('{effective-url}', htmlspecialchars($effective_url), $string);\n\treturn $string;\n}\n\nfunction get_cache() {\n\tglobal $options, $valid_key;\n\tif (!$options->caching) return;\n\tstatic $cache = null;\n\tif ($cache === null) {\n\t\tdebug('RSS cache TTL is set to '.(isset($options->cache_ttl) ? $options->cache_ttl : 10*60).' sec.');\n\t\t$frontendOptions = array(\n\t\t\t'lifetime' => isset($options->cache_ttl) ? $options->cache_ttl : 10*60, // cache lifetime of 10 minutes\n\t\t\t'automatic_serialization' => false,\n\t\t\t'write_control' => false,\n\t\t\t'automatic_cleaning_factor' => $options->cache_cleanup,\n\t\t\t'ignore_user_abort' => false\n\t\t);\n\t\t$backendOptions = array(\n\t\t\t'cache_dir' => ($valid_key) ? $options->cache_dir.'/rss-with-key/' : $options->cache_dir.'/rss/', // directory where to put the cache files\n\t\t\t'file_locking' => false,\n\t\t\t'read_control' => true,\n\t\t\t'read_control_type' => 'strlen',\n\t\t\t'hashed_directory_level' => $options->cache_directory_level,\n\t\t\t'hashed_directory_perm' => 0777,\n\t\t\t'cache_file_perm' => 0664,\n\t\t\t'file_name_prefix' => 'ff'\n\t\t);\n\t\t// getting a Zend_Cache_Core object\n\t\t$cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);\n\t}\n\treturn $cache;\n}\n\nfunction get_url_cache() {\n\tglobal $options, $valid_key;\n\tif (!$options->caching) return;\n\tstatic $url_cache = null;\n\tif ($url_cache === null) {\n\t\tdebug('HTTP cache TTL is set to '.(isset($options->http_cache_ttl) ? $options->http_cache_ttl : 3*24*60*60).' sec.');\n\t\t$frontendOptions = array(\n\t\t\t'lifetime' => isset($options->http_cache_ttl) ? $options->http_cache_ttl : 3*24*60*60, // cache lifetime\n\t\t\t'automatic_serialization' => false,\n\t\t\t'write_control' => false,\n\t\t\t'automatic_cleaning_factor' => $options->cache_cleanup,\n\t\t\t'ignore_user_abort' => false\n\t\t);\n\t\t$backendOptions = array(\n\t\t\t'cache_dir' => $options->cache_dir.'/urls/', // directory where to put the cache files\n\t\t\t'file_locking' => false,\n\t\t\t'read_control' => true,\n\t\t\t'read_control_type' => 'strlen',\n\t\t\t'hashed_directory_level' => $options->cache_directory_level,\n\t\t\t'hashed_directory_perm' => 0777,\n\t\t\t'cache_file_perm' => 0664,\n\t\t\t'file_name_prefix' => 'ff'\n\t\t);\n\t\t// getting a Zend_Cache_Core object\n\t\t$url_cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);\n\t}\n\treturn $url_cache;\n}\n\nfunction is_cached($url) {\n\tif (!($cache = get_url_cache()) || !$url) return false;\n\treturn ($cache->test('request'.md5($url)) !== false);\n}\n\nfunction set_cached($url, $data) {\n\tif (!($cache = get_url_cache()) || !$url || !$data) return;\n\t$cache->save(serialize($data), 'request'.md5($url));\n}\n\nfunction get_cached($url) {\n\tif (!($cache = get_url_cache()) || !$url) return null;\n\treturn unserialize($cache->load('request'.md5($url)));\n}\n\nfunction debug($msg) {\n\tglobal $debug_mode;\n\tif ($debug_mode) {\n\t\techo \"* \",$msg,\"<br />\";\n\t\tob_flush();\n\t\tflush();\n\t}\n}\n?>"
  },
  {
    "path": "manifest.yml",
    "content": "# This file is only used when deploying Full-Text RSS to AppFog.\n# See http://help.fivefilters.org/customer/portal/articles/1143210-hosting\n---\napplications:\n  .:\n#    name: full-text-rss\n    framework:\n      name: php\n      info:\n        mem: 512M\n        description: PHP Application\n        exec: \n    infra: aws\n#    url: ${name}.${target-base}\n    mem: 512M\n    instances: 1\n"
  },
  {
    "path": "site_config/README.txt",
    "content": "Full-Text RSS Site Patterns\n---------------------------\n\nSite patterns allow you to specify what should be extracted from specific sites.\n\nPlease see http://help.fivefilters.org/customer/portal/articles/223153-site-patterns for more information."
  },
  {
    "path": "site_config/custom/index.php",
    "content": "<?php\n// this is here to prevent directory listing over the web\n?>"
  },
  {
    "path": "site_config/index.php",
    "content": "<?php\n// this is here to prevent directory listing over the web"
  },
  {
    "path": "site_config/standard/.wikipedia.org.txt",
    "content": "title: //h1[@id='firstHeading']\nbody: //div[@id = 'bodyContent']\nstrip_id_or_class: editsection\n#strip_id_or_class: toc\nstrip_id_or_class: vertical-navbox\nstrip: //table[@id='toc']\nstrip: //div[@id='catlinks']\nstrip: //div[@id='jump-to-nav']\nstrip: //div[@class='thumbcaption']//div[@class='magnify']\nstrip: //table[@class='navbox']\nstrip: //table[contains(@class, 'infobox')]\nstrip: //div[@class='dablink']\nstrip: //div[@id='contentSub']\nstrip: //table[contains(@class, 'metadata')]\nstrip: //*[contains(@class, 'noprint')]\nstrip: //span[@title='pronunciation:']\nprune: no\ntidy: no\ntest_url: http://en.wikipedia.org/wiki/Christopher_Lloyd"
  },
  {
    "path": "site_config/standard/version.txt",
    "content": "2013-05-12T22:53:07Z"
  }
]