split html class to Api\Html, Api\Header\Content, Api\Header\UserAgent and translation

This commit is contained in:
Ralf Becker 2016-03-13 11:22:44 +00:00
parent 999b0a7083
commit 85695f0d41
15 changed files with 1866 additions and 2072 deletions

View File

@ -16,8 +16,6 @@ namespace EGroupware\Api\Db;
use EGroupware\Api;
use ZipArchive;
use html;
/**
* DB independent backup and restore of EGroupware database
*
@ -1100,7 +1098,7 @@ class Backup
else
{
$def = "<?php\n\t/* EGroupware schema-backup from ".date('Y-m-d H:i:s')." */\n\n".$def;
html::content_header('schema-backup-'.date('YmdHi').'.inc.php','text/plain',bytes($def));
Api\Header\Content::type('schema-backup-'.date('YmdHi').'.inc.php','text/plain',bytes($def));
echo $def;
}
}

167
api/src/Header/Content.php Normal file
View File

@ -0,0 +1,167 @@
<?php
/**
* EGroupware API: safe content type and disposition headers
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de> complete rewrite in 6/2006 and earlier modifications
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @author RalfBecker-AT-outdoor-training.de
* @copyright 2001-2016 by RalfBecker@outdoor-training.de
* @package api
* @version $Id$
*/
namespace EGroupware\Api\Header;
use EGroupware\Api;
/**
* Safe content type and disposition headers
*/
class Content
{
/**
* Output safe content headers for user-content, mitigating risk of javascript or html
*
* Mitigate risk of serving javascript or css from our domain,
* which will get around same origin policy and CSP!
*
* Mitigate risk of html downloads by using CSP or force download for IE
*
* @param resource|string &$content content might be changed by this call
* @param string $path filename or path for content-disposition header
* @param string &$mime ='' mimetype or '' (default) to detect it from filename, using mime_magic::filename2mime()
* on return used, maybe changed, mime-type
* @param int $length =0 content length, default 0 = skip that header
* on return changed size
* @param boolean $nocache =true send headers to disallow browser/proxies to cache the download
* @param boolean $force_download =true send content-disposition attachment header
* @param boolean $no_content_type =false do not send actual content-type and content-length header, just content-disposition
*/
public static function safe(&$content, $path, &$mime='', &$length=0, $nocache=true, $force_download=true, $no_content_type=false)
{
// change old/aliased mime-types to new one, eg. image/pdf to application/pdf
$mime = Api\Api\MimeMagic::fix_mime_type($mime);
// mitigate risk of serving javascript or css via webdav from our domain,
// which will get around same origin policy and CSP
list($type, $subtype) = explode('/', strtolower($mime));
if (!$force_download && in_array($type, array('application', 'text')) &&
in_array($subtype, array('javascript', 'x-javascript', 'ecmascript', 'jscript', 'vbscript', 'css')))
{
// unfortunatly only Chrome and IE >= 8 allow to switch content-sniffing off with X-Content-Type-Options: nosniff
if (UserAgent::type() == 'chrome' || UserAgent::type() == 'msie' && UserAgent::version() >= 8)
{
$mime = 'text/plain';
header('X-Content-Type-Options: nosniff'); // stop IE & Chrome from content-type sniffing
}
// for the rest we change mime-type to text/html and let code below handle it safely
// this stops Safari and Firefox from using it as src attribute in a script tag
// but only for "real" browsers, we dont want to modify data for our WebDAV clients
elseif (isset($_SERVER['HTTP_REFERER']))
{
$mime = 'text/html';
if (is_resource($content))
{
$data = fread($content, $length);
fclose($content);
$content =& $data;
unset($data);
}
$content = '<pre>'.$content;
$length += 5;
}
}
// mitigate risk of html downloads by using CSP or force download for IE
if (!$force_download && in_array($mime, array('text/html', 'application/xhtml+xml')))
{
// use CSP only for current user-agents/versions I was able to positivly test
if (UserAgent::type() == 'chrome' && UserAgent::version() >= 24 ||
// mobile FF 24 on Android does NOT honor CSP!
UserAgent::type() == 'firefox' && !UserAgent::mobile() && UserAgent::version() >= 24 ||
UserAgent::type() == 'safari' && !UserAgent::mobile() && UserAgent::version() >= 536 || // OS X
UserAgent::type() == 'safari' && UserAgent::mobile() && UserAgent::version() >= 9537) // iOS 7
{
$csp = "script-src 'none'"; // forbid to execute any javascript
header("Content-Security-Policy: $csp");
header("X-Webkit-CSP: $csp"); // Chrome: <= 24, Safari incl. iOS
//header("X-Content-Security-Policy: $csp"); // FF <= 22
//error_log(__METHOD__."('$options[path]') ".UserAgent::type().'/'.UserAgent::version().(UserAgent::mobile()?'/mobile':'').": using Content-Security-Policy: $csp");
}
else // everything else get's a Content-dispostion: attachment, to be on save side
{
//error_log(__METHOD__."('$options[path]') ".UserAgent::type().'/'.UserAgent::version().(UserAgent::mobile()?'/mobile':'').": using Content-disposition: attachment");
$force_download = true;
}
}
if ($no_content_type)
{
if ($force_download) self::disposition(Api\Vfs::basename($path), $force_download);
}
else
{
self::type(Api\Vfs::basename($path), $mime, $length, $nocache, $force_download);
}
}
/**
* Output content-type headers for file downloads
*
* This function should only be used for non-user supplied content!
* For uploaded files, mail attachmentes, etc, you have to use safe_content_header!
*
* @author Miles Lott originally in browser class
* @param string $fn filename
* @param string $mime ='' mimetype or '' (default) to detect it from filename, using mime_magic::filename2mime()
* @param int $length =0 content length, default 0 = skip that header
* @param boolean $nocache =true send headers to disallow browser/proxies to cache the download
* @param boolean $forceDownload =true send headers to handle as attachment/download
*/
public static function type($fn,$mime='',$length=0,$nocache=True,$forceDownload=true)
{
// if no mime-type is given or it's the default binary-type, guess it from the extension
if(empty($mime) || $mime == 'application/octet-stream')
{
$mime = Api\MimeMagic::filename2mime($fn);
}
if($fn)
{
// Show this for all
self::disposition($fn,$forceDownload);
header('Content-type: '.$mime);
if($length)
{
header('Content-length: '.$length);
}
if($nocache)
{
header('Pragma: no-cache');
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
}
}
}
/**
* Output content-disposition header for file downloads
*
* @param string $fn filename
* @param boolean $forceDownload =true send headers to handle as attachment/download
*/
public static function disposition($fn, $forceDownload=true)
{
if ($forceDownload)
{
$attachment = ' attachment;';
}
else
{
$attachment = ' inline;';
}
header('Content-disposition:'.$attachment.' filename="'.Api\Translation::to_ascii($fn).'"; filename*=utf-8\'\''.rawurlencode($fn));
}
}

View File

@ -0,0 +1,119 @@
<?php
/**
* EGroupware API: server-side browser and mobile device detection
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de> complete rewrite in 6/2006 and earlier modifications
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @author RalfBecker-AT-outdoor-training.de
* @copyright 2001-2016 by RalfBecker@outdoor-training.de
* @package api
* @subpackage header
* @version $Id$
*/
namespace EGroupware\Api\Header;
/**
* Server-side browser and mobile device detection based on User-Agent header
*/
class UserAgent
{
/**
* Normalized type of user-agent
*
* @return string 'firefox', 'msie', 'safari' (incl. iPhone), 'chrome', 'opera', 'konqueror', 'mozilla'
*/
public function type()
{
return self::$user_agent;
}
/**
* Version of user-agent as specified by browser
*
* @return string
*/
public function version()
{
return self::$ua_version;
}
/**
* Mobile device type
*
* @return string "iphone", "ipod", "ipad", "android", "symbianos", "blackberry", "kindle", "opera mobi", "windows phone"
*/
public function mobile()
{
return self::$ua_mobile;
}
/**
* user-agent: 'firefox', 'msie', 'safari' (incl. iPhone), 'chrome', 'opera', 'konqueror', 'mozilla'
*
* @var string
*/
protected static $user_agent;
/**
* User agent is mobile browser: "iphone", "ipod", "ipad", "android", "symbianos", "blackberry", "kindle", "opera mobi", "windows phone"
*
* @var string with name of mobile browser or null, if not mobile browser
*/
protected static $ua_mobile;
/**
* version of user-agent as specified by browser
*
* @var string
*/
protected static $ua_version;
/**
* initialise our static vars
*/
static function _init_static()
{
// should be Ok for all HTML 4 compatible browsers
$parts = $all_parts = null;
if(!preg_match('/compatible; ([a-z]+)[\/ ]+([0-9.]+)/i',$_SERVER['HTTP_USER_AGENT'],$parts))
{
preg_match_all('/([a-z]+)\/([0-9.]+)/i',$_SERVER['HTTP_USER_AGENT'],$all_parts,PREG_SET_ORDER);
$parts = array_pop($all_parts);
foreach($all_parts as $p)
{
if ($p[1] == 'Chrome' && $parts[1] != 'Edge')
{
$parts = $p;
break;
}
}
}
list(,self::$user_agent,self::$ua_version) = $parts;
if ((self::$user_agent = strtolower(self::$user_agent)) == 'version') self::$user_agent = 'opera';
// IE no longer reports MSIE, but "Trident/7.0; rv:11.0"
if (self::$user_agent=='trident')
{
self::$user_agent='msie';
$matches = null;
self::$ua_version = preg_match('|Trident/[0-9.]+; rv:([0-9.]+)|i', $_SERVER['HTTP_USER_AGENT'], $matches) ?
$matches[1] : 11.0;
}
// iceweasel is based on mozilla and we treat it like as firefox
if (self::$user_agent == 'iceweasel')
{
self::$user_agent = 'firefox';
}
// MS Edge sometimes reports just "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
if (self::$user_agent == 'mozilla' && self::$ua_version == '5.0')
{
self::$user_agent = 'edge';
self::$ua_version = '12.0';
}
self::$ua_mobile = preg_match('/(iPhone|iPod|iPad|Android|SymbianOS|Blackberry|Kindle|Opera Mobi|Windows Phone)/i',
$_SERVER['HTTP_USER_AGENT'], $matches) ? strtolower($matches[1]) : null;
//error_log("HTTP_USER_AGENT='$_SERVER[HTTP_USER_AGENT]', UserAgent: '".self::$user_agent."', Version: '".self::$ua_version."', isMobile=".array2string(self::$ua_mobile));
}
}
UserAgent::_init_static();

1310
api/src/Html.php Normal file

File diff suppressed because it is too large Load Diff

View File

@ -11,9 +11,6 @@
namespace EGroupware\Api;
// explicitly import old phpgwapi classes used:
use html;
/**
* Finding template specific images
*
@ -34,7 +31,7 @@ class Image
*/
static function find($app,$image,$extension='',$_svg=false)
{
$svg = html::$ua_mobile ? null : $_svg; // ATM we use svg icons only for mobile theme
$svg = Header\UserAgent::mobile() ? null : $_svg; // ATM we use svg icons only for mobile theme
static $image_map_no_svg = null, $image_map_svg = null;
if (is_null($svg)) $svg = self::svg_usable ();
if ($svg)
@ -114,7 +111,7 @@ class Image
*/
public static function svg_usable()
{
return html::$user_agent !== 'msie' || html::$ua_version >= 9;
return Header\UserAgent::type() !== 'msie' || Header\UserAgent::version() >= 9;
}
/**
@ -160,7 +157,7 @@ class Image
$app_map =& $map[$app];
if (true) $app_map = array();
$imagedirs = array();
if (html::$ua_mobile)
if (Header\UserAgent::mobile())
{
$imagedirs[] = '/'.$app.'/templates/mobile/images';
}

View File

@ -18,7 +18,6 @@
namespace EGroupware\Api;
// explicitly reference classes still in phpgwapi
use html;
use egw; // on_shutdown
use egw_json_response;
@ -202,7 +201,8 @@ class Link extends Link\Storage
{
// FireFox 36 can not display pdf with it's internal viewer in an iframe used by mobile theme/template for popups
// same is true for all mobile devices
if (html::$user_agent == 'firefox' && $GLOBALS['egw_info']['user']['preferences']['common']['theme'] == 'mobile' || html::$ua_mobile)
if (Header\UserAgent::type() == 'firefox' && $GLOBALS['egw_info']['user']['preferences']['common']['theme'] == 'mobile' ||
Header\UserAgent::mobile())
{
unset(self::$app_register['home']['mime']['application/pdf']);
}

View File

@ -25,7 +25,6 @@ namespace EGroupware\Api;
// explicitly reference classes still in phpgwapi
use egw_mailer;
use egw_digest_auth; // egw_digest_auth::parse_digest
use html; // html::$ua_mobile
/**
* Create, verifies or destroys an EGroupware session
@ -1245,7 +1244,7 @@ class Session
// if we are installed in iOS as web-app, we must not set a cookietime==0 (session-cookie),
// as every change between apps will cause the cookie to get lost
static $is_iOS = null;
if (!$cookietime && !isset($is_iOS)) $is_iOS = (bool)preg_match('/^(iPhone|iPad|iPod)/i', html::$ua_mobile);
if (!$cookietime && !isset($is_iOS)) $is_iOS = (bool)preg_match('/^(iPhone|iPad|iPod)/i', Header\UserAgent::mobile());
if(!headers_sent()) // gives only a warning, but can not send the cookie anyway
{

View File

@ -16,7 +16,6 @@ namespace EGroupware\Api\Storage;
use EGroupware\Api;
// explicitly reference classes still in phpgwapi or otherwise outside api
use html;
use notifications;
/**
@ -1057,7 +1056,7 @@ abstract class Tracking
if ($html_mail)
{
if (!$this->html_content_allow) $line = html::htmlspecialchars($line); // XSS
if (!$this->html_content_allow) $line = Api\Html::htmlspecialchars($line); // XSS
$color = $modified ? 'red' : false;
$size = '110%';
@ -1080,7 +1079,7 @@ abstract class Tracking
// Only Convert nl2br on non-html content
if (strpos($data, '<br') === false)
{
$data = nl2br($this->html_content_allow ? $data : html::htmlspecialchars($data));
$data = nl2br($this->html_content_allow ? $data : Api\Html::htmlspecialchars($data));
$this->html_content_allow = true; // to NOT do htmlspecialchars again
}
break;
@ -1108,15 +1107,15 @@ abstract class Tracking
if ($type == 'link')
{
// the link is often too long for html boxes chunk-split allows to break lines if needed
$content .= html::a_href(chunk_split(rawurldecode($data),40,'&#8203;'),$data,'','target="_blank"');
$content .= Api\Html::a_href(chunk_split(rawurldecode($data),40,'&#8203;'),$data,'','target="_blank"');
}
elseif ($this->html_content_allow)
{
$content .= html::activate_links($data);
$content .= Api\Html::activate_links($data);
}
else
{
$content .= html::htmlspecialchars($data);
$content .= Api\Html::htmlspecialchars($data);
}
}
else

View File

@ -230,7 +230,7 @@ class mail_compose
}
if (html::$ua_mobile)
{
foreach ($actions as $key => $action)
foreach (array_keys($actions) as $key)
{
if (!in_array($key, array('send','button[saveAsDraft]','uploadForCompose' ))) {
$actions[$key]['toolbarDefault'] = false;
@ -548,7 +548,7 @@ class mail_compose
$suppressSigOnTop = true;
if (stripos($content['mail_htmltext'],'<pre>')!==false)
{
$contentArr = html::splithtmlByPRE($content['mail_htmltext']);
$contentArr = translation::splithtmlByPRE($content['mail_htmltext']);
if (is_array($contentArr))
{
foreach ($contentArr as $k =>&$elem)
@ -1171,7 +1171,7 @@ class mail_compose
foreach((array)$addr_content as $key => $value) {
if ($value=="NIL@NIL") continue;
if ($destination=='replyto' && str_replace('"','',$value) ==
str_replace('"','',$identities[$presetId ? $presetId : $this->mail_bo->getDefaultIdentity()]))
str_replace('"','',$identities[$this->mail_bo->getDefaultIdentity()]))
{
// preserve/restore the value to content.
$content[strtolower($destination)][]=$value;
@ -1539,6 +1539,7 @@ class mail_compose
}
catch (Exception $e)
{
unset($e);
// fail silently
$this->sessionData['mailaccount'] = $mail_bo->profileID;
}
@ -2123,9 +2124,9 @@ class mail_compose
}
// add line breaks to $bodyParts
$newBody = translation::convert_jsonsafe($bodyParts[$i]['body'],$bodyParts[$i]['charSet']);
$newBody2 = translation::convert_jsonsafe($bodyParts[$i]['body'],$bodyParts[$i]['charSet']);
#error_log( "GetReplyData (Plain) CharSet:".mb_detect_encoding($bodyParts[$i]['body'] . 'a' , strtoupper($bodyParts[$i]['charSet']).','.strtoupper($this->displayCharset).',UTF-8, ISO-8859-1'));
$newBody = mail_ui::resolve_inline_images($newBody, $_folder, $_uid, $_partID, 'plain');
$newBody = mail_ui::resolve_inline_images($newBody2, $_folder, $_uid, $_partID, 'plain');
$this->sessionData['body'] .= "\r\n";
// create body new, with good line breaks and indention
foreach(explode("\n",$newBody) as $value) {

View File

@ -110,14 +110,109 @@ class egw_htmLawed
if (empty($Spec)) $Spec = $this->Spec;
// If we are processing mails, we take out stuff in <style> stuff </style> tags and
// put it back in after purifying; styles are processed for known security risks
// in html::getStyles
$styles='';
// in self::getStyles
// we allow filtered style sections now throughout egroupware
/*if ($Config['hook_tag'] =="hl_email_tag_transform")*/ $styles = html::getStyles($html2check);
/*if ($Config['hook_tag'] =="hl_email_tag_transform")*/ $styles = self::getStyles($html2check);
//error_log(__METHOD__.__LINE__.array2string($styles));
return ($styles?$styles:'').htmLawed($html2check, $Config, $Spec);
}
/**
* get all style tag definitions, <style> stuff </style> of the html passed in
* and remove it from input
* @author Leithoff, Klaus
* @param string html
* @return string the style css
*/
static function getStyles(&$html)
{
$ct=0;
$newStyle = null;
if (stripos($html,'<style')!==false) $ct = preg_match_all('#<style(?:\s.*)?>(.+)</style>#isU', $html, $newStyle);
if ($ct>0)
{
//error_log(__METHOD__.__LINE__.array2string($newStyle[0]));
$style2buffer = implode('',$newStyle[0]);
// only replace what we have found, we use it here, as we use the same routine in Translation::replaceTagsCompletley
// no need to do the extra routine
$html = str_ireplace($newStyle[0],'',$html);
}
if ($style2buffer)
{
//error_log(__METHOD__.__LINE__.array2string($style2buffer));
$test = json_encode($style2buffer);
//error_log(__METHOD__.__LINE__.'#'.$test.'# ->'.strlen($style2buffer).' Error:'.json_last_error());
//if (json_last_error() != JSON_ERROR_NONE && strlen($style2buffer)>0)
if ($test=="null" && strlen($style2buffer)>0)
{
// this should not be needed, unless something fails with charset detection/ wrong charset passed
error_log(__METHOD__.__LINE__.' Found Invalid sequence for utf-8 in CSS:'.$style2buffer.' Carset Detected:'.Translation::detect_encoding($style2buffer));
$style2buffer = utf8_encode($style2buffer);
}
}
$style .= $style2buffer;
// clean out comments and stuff
$search = array(
'@url\(http:\/\/[^\)].*?\)@si', // url calls e.g. in style definitions
// '@<!--[\s\S]*?[ \t\n\r]*-->@', // Strip multi-line comments including CDATA
// '@<!--[\s\S]*?[ \t\n\r]*--@', // Strip broken multi-line comments including CDATA
);
$style = preg_replace($search,"",$style);
// CSS Security
// http://code.google.com/p/browsersec/wiki/Part1#Cascading_stylesheets
$css = preg_replace('/(javascript|expession|-moz-binding)/i','',$style);
if (stripos($css,'script')!==false) Translation::replaceTagsCompletley($css,'script'); // Strip out script that may be included
// we need this, as styledefinitions are enclosed with curly brackets; and template stuff tries to replace everything between curly brackets that is having no horizontal whitespace
// as the comments as <!-- styledefinition --> in stylesheet are outdated, and ck-editor does not understand it, we remove it
$css_no_comment = str_replace(array(':','<!--','-->'),array(': ','',''),$css);
//error_log(__METHOD__.__LINE__.$css);
// we already removed what we have found, above, as we used pretty much the same routine as in Translation::replaceTagsCompletley
// no need to do the extra routine
// TODO: we may have to strip urls and maybe comments and ifs
//if (stripos($html,'style')!==false) Translation::replaceTagsCompletley($html,'style'); // clean out empty or pagewide style definitions / left over tags
return $css_no_comment;
}
/**
* Runs HTMLPurifier over supplied html to remove malicious code
*
* @param string $html
* @param array|string $config =null - config to influence the behavior of current purifying engine
* @param array|string $spec =null - spec to influence the behavior of current purifying engine
* The $spec argument can be used to disallow an otherwise legal attribute for an element,
* or to restrict the attribute's values
* @param boolean $_force =null - force the config passed to be used without merging to the default
*/
static function purify($html,$config=null,$spec=array(),$_force=false)
{
$defaultConfig = array('valid_xhtml'=>1,'safe'=>1);
if (empty($html)) return $html; // no need to process further
if (!empty($config) && is_string($config))
{
//error_log(__METHOD__.__LINE__.$config);
$config = json_decode($config,true);
if (is_null($config)) error_log(__METHOD__.__LINE__." decoding of config failed; standard will be applied");
}
// User preferences
$font = $GLOBALS['egw_info']['user']['preferences']['common']['rte_font'];
$font_size = $GLOBALS['egw_info']['user']['preferences']['common']['rte_font_size'];
// Check for "blank" = just user preference span - for some reason we can't match on the entity, so approximate
$regex = '#^<span style="font-family:'.$font.';font-size:'.$font_size.';">.?</span>$#us';
if(preg_match($regex,$html))
{
return '';
}
$htmLawed = new egw_htmLawed();
if (is_array($config) && $_force===false) $config = array_merge($defaultConfig, $config);
if (empty($config)) $config = $defaultConfig;
//error_log(__METHOD__.__LINE__.array2string($config));
return $htmLawed->egw_htmLawed($html,$config,$spec);
}
}
/**
@ -237,8 +332,8 @@ function hl_my_tag_transform($element, $attribute_array=0)
function hl_email_tag_transform($element, $attribute_array=0)
{
//error_log(__METHOD__.__LINE__.$element.array2string($attribute_array));
static $lastelement;
static $throwawaycounter;
static $lastelement = null;
static $throwawaycounter = null;
if (is_null($lastelement)) $lastelement='';
if (is_null($throwawaycounter)) $throwawaycounter = 0;
//if ($throwawaycounter>1) error_log(__METHOD__.__LINE__.' '.$throwawaycounter.$element.array2string($attribute_array));

File diff suppressed because it is too large Load Diff

View File

@ -279,7 +279,7 @@ class translation extends Api\Translation
{
if (stripos($_html,'<pre ')!==false || stripos($_html,'<pre>')!==false)
{
$contentArr = html::splithtmlByPRE($_html);
$contentArr = self::splithtmlByPRE($_html);
foreach ($contentArr as $k =>&$elem)
{
if (stripos($elem,'<pre ')===false && stripos($elem,'<pre>')===false)
@ -349,7 +349,7 @@ class translation extends Api\Translation
{
if (stripos($_html,'<pre ')!==false || stripos($_html,'<pre>')!==false)
{
$contentArr = html::splithtmlByPRE($_html);
$contentArr = self::splithtmlByPRE($_html);
foreach ($contentArr as $k =>&$elem)
{
if (stripos($elem,'<pre ')===false && stripos($elem,'<pre>')===false)
@ -458,4 +458,43 @@ class translation extends Api\Translation
return implode("\r\n",$asciiTextBuff);
}
}
/**
* split html by PRE tag, return array with all content pre-sections isolated in array elements
* @author Leithoff, Klaus
* @param string html
* @return mixed array of parts or unaffected html
*/
static function splithtmlByPRE($html)
{
$searchFor = '<pre ';
$pos = stripos($html,$searchFor);
if ($pos===false)
{
$searchFor = '<pre>';
$pos = stripos($html,$searchFor);
}
if ($pos === false)
{
return $html;
}
$html2ret[] = substr($html,0,$pos);
while ($pos!==false)
{
$endofpre = stripos($html,'</pre>',$pos);
$length = $endofpre-$pos+6;
$html2ret[] = substr($html,$pos,$length);
$searchFor = '<pre ';
$pos = stripos($html,$searchFor, $endofpre+6);
if ($pos===false)
{
$searchFor = '<pre>';
$pos = stripos($html,$searchFor, $endofpre+6);
}
$html2ret[] = ($pos ? substr($html,$endofpre+6,$pos-($endofpre+6)): substr($html,$endofpre+6));
//$pos=false;
}
//error_log(__METHOD__.__LINE__.array2string($html2ret));
return $html2ret;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 B

View File

@ -1,30 +0,0 @@
htmlArea License (based on BSD license)
Copyright (c) 2002-2004, interactivetools.com, inc.
Copyright (c) 2003-2004 dynarch.com
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1) Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2) Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3) Neither the name of interactivetools.com, inc. nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,370 +0,0 @@
<!--
/**************************************************************************\
* eGroupWare - Colorpicker *
* http://www.eGroupWare.org *
* Modified from htmlArea by Ralf Becker <RalfBecker@outdoor-training.de> *
\**************************************************************************/
htmlArea v3.0 - Copyright (c) 2002-2004 interactivetools.com, inc.
This copyright notice MUST stay intact for use (see license.txt).
Portions (c) dynarch.com, 2003-2004
$Id$
-->
<html><head><title>Select Color</title>
<script type="text/javascript">
window.resizeTo(240, 205);
function _CloseOnEsc() {
if (event.keyCode == 27) { window.close(); return; }
}
var id;
function Init() { // run on page load
document.body.onkeypress = _CloseOnEsc;
id = location.search.match(/id=([^&]+)/);
var color = location.search.match(/color=([^&]+)/);
if (id) id = decodeURIComponent(id[1]);
if (color) color = decodeURIComponent(color[1]);
//alert('id='+id+', color='+color);
color = ValidateColor(color) || '000000';
View(color); // set default color
}
function View(color) { // preview color
document.getElementById("ColorPreview").style.backgroundColor = '#' + color;
document.getElementById("ColorHex").value = '#' + color;
}
function Set(string) {
//alert (Set
// select color
var color = ValidateColor(string);
if (color == null) { alert("Invalid color code: " + string); } // invalid color
else { // valid color
View(color); // show selected color
var input=window.top.opener.document.getElementById(id);
if (input) {
input.value = '#'+color;
input.style.backgroundColor = '#'+color;
} else alert('id='+id+' is not a valid id in opener !!!');
window.close();
}
}
function ValidateColor(string) { // return valid color code
string = string || '';
string = string + "";
string = string.toUpperCase();
var chars = '0123456789ABCDEF';
var out = '';
for (var i=0; i<string.length; i++) { // remove invalid color chars
var schar = string.charAt(i);
if (chars.indexOf(schar) != -1) { out += schar; }
}
if (out.length != 6) { return null; } // check length
return out;
}
</script>
</head>
<body style="background:ButtonFace; margin:0px; padding:0px" onload="Init()">
<form method="get" style="margin:0px; padding:0px" onSubmit="Set(document.getElementById('ColorHex').value); return false;">
<table border="0px" cellspacing="0px" cellpadding="4" width="100%">
<tr>
<td style="background:buttonface"><div style="background-color: #000000; padding: 1; height: 21px; width: 50px"><div id="ColorPreview" style="height: 100%; width: 100%"></div></div></td>
<td style="background:buttonface"><input type="text" name="ColorHex" id="ColorHex" value="" size="15" style="font-size: 12px"></td>
<td style="background:buttonface" width=100%></td>
</tr>
</table>
</form>
<table border="0" cellspacing="0px" cellpadding="0px" width="100%" bgcolor="#000000" style="cursor: hand;">
<tr>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#003300" onMouseOver="View('003300')" onClick="Set('003300')" height="10px" width="10px"></td>
<td bgcolor="#006600" onMouseOver="View('006600')" onClick="Set('006600')" height="10px" width="10px"></td>
<td bgcolor="#009900" onMouseOver="View('009900')" onClick="Set('009900')" height="10px" width="10px"></td>
<td bgcolor="#00CC00" onMouseOver="View('00CC00')" onClick="Set('00CC00')" height="10px" width="10px"></td>
<td bgcolor="#00FF00" onMouseOver="View('00FF00')" onClick="Set('00FF00')" height="10px" width="10px"></td>
<td bgcolor="#330000" onMouseOver="View('330000')" onClick="Set('330000')" height="10px" width="10px"></td>
<td bgcolor="#333300" onMouseOver="View('333300')" onClick="Set('333300')" height="10px" width="10px"></td>
<td bgcolor="#336600" onMouseOver="View('336600')" onClick="Set('336600')" height="10px" width="10px"></td>
<td bgcolor="#339900" onMouseOver="View('339900')" onClick="Set('339900')" height="10px" width="10px"></td>
<td bgcolor="#33CC00" onMouseOver="View('33CC00')" onClick="Set('33CC00')" height="10px" width="10px"></td>
<td bgcolor="#33FF00" onMouseOver="View('33FF00')" onClick="Set('33FF00')" height="10px" width="10px"></td>
<td bgcolor="#660000" onMouseOver="View('660000')" onClick="Set('660000')" height="10px" width="10px"></td>
<td bgcolor="#663300" onMouseOver="View('663300')" onClick="Set('663300')" height="10px" width="10px"></td>
<td bgcolor="#666600" onMouseOver="View('666600')" onClick="Set('666600')" height="10px" width="10px"></td>
<td bgcolor="#669900" onMouseOver="View('669900')" onClick="Set('669900')" height="10px" width="10px"></td>
<td bgcolor="#66CC00" onMouseOver="View('66CC00')" onClick="Set('66CC00')" height="10px" width="10px"></td>
<td bgcolor="#66FF00" onMouseOver="View('66FF00')" onClick="Set('66FF00')" height="10px" width="10px"></td>
</tr>
<tr>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#333333" onMouseOver="View('333333')" onClick="Set('333333')" height="10px" width="10px"></td>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#000033" onMouseOver="View('000033')" onClick="Set('000033')" height="10px" width="10px"></td>
<td bgcolor="#003333" onMouseOver="View('003333')" onClick="Set('003333')" height="10px" width="10px"></td>
<td bgcolor="#006633" onMouseOver="View('006633')" onClick="Set('006633')" height="10px" width="10px"></td>
<td bgcolor="#009933" onMouseOver="View('009933')" onClick="Set('009933')" height="10px" width="10px"></td>
<td bgcolor="#00CC33" onMouseOver="View('00CC33')" onClick="Set('00CC33')" height="10px" width="10px"></td>
<td bgcolor="#00FF33" onMouseOver="View('00FF33')" onClick="Set('00FF33')" height="10px" width="10px"></td>
<td bgcolor="#330033" onMouseOver="View('330033')" onClick="Set('330033')" height="10px" width="10px"></td>
<td bgcolor="#333333" onMouseOver="View('333333')" onClick="Set('333333')" height="10px" width="10px"></td>
<td bgcolor="#336633" onMouseOver="View('336633')" onClick="Set('336633')" height="10px" width="10px"></td>
<td bgcolor="#339933" onMouseOver="View('339933')" onClick="Set('339933')" height="10px" width="10px"></td>
<td bgcolor="#33CC33" onMouseOver="View('33CC33')" onClick="Set('33CC33')" height="10px" width="10px"></td>
<td bgcolor="#33FF33" onMouseOver="View('33FF33')" onClick="Set('33FF33')" height="10px" width="10px"></td>
<td bgcolor="#660033" onMouseOver="View('660033')" onClick="Set('660033')" height="10px" width="10px"></td>
<td bgcolor="#663333" onMouseOver="View('663333')" onClick="Set('663333')" height="10px" width="10px"></td>
<td bgcolor="#666633" onMouseOver="View('666633')" onClick="Set('666633')" height="10px" width="10px"></td>
<td bgcolor="#669933" onMouseOver="View('669933')" onClick="Set('669933')" height="10px" width="10px"></td>
<td bgcolor="#66CC33" onMouseOver="View('66CC33')" onClick="Set('66CC33')" height="10px" width="10px"></td>
<td bgcolor="#66FF33" onMouseOver="View('66FF33')" onClick="Set('66FF33')" height="10px" width="10px"></td>
</tr>
<tr>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#666666" onMouseOver="View('666666')" onClick="Set('666666')" height="10px" width="10px"></td>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#000066" onMouseOver="View('000066')" onClick="Set('000066')" height="10px" width="10px"></td>
<td bgcolor="#003366" onMouseOver="View('003366')" onClick="Set('003366')" height="10px" width="10px"></td>
<td bgcolor="#006666" onMouseOver="View('006666')" onClick="Set('006666')" height="10px" width="10px"></td>
<td bgcolor="#009966" onMouseOver="View('009966')" onClick="Set('009966')" height="10px" width="10px"></td>
<td bgcolor="#00CC66" onMouseOver="View('00CC66')" onClick="Set('00CC66')" height="10px" width="10px"></td>
<td bgcolor="#00FF66" onMouseOver="View('00FF66')" onClick="Set('00FF66')" height="10px" width="10px"></td>
<td bgcolor="#330066" onMouseOver="View('330066')" onClick="Set('330066')" height="10px" width="10px"></td>
<td bgcolor="#333366" onMouseOver="View('333366')" onClick="Set('333366')" height="10px" width="10px"></td>
<td bgcolor="#336666" onMouseOver="View('336666')" onClick="Set('336666')" height="10px" width="10px"></td>
<td bgcolor="#339966" onMouseOver="View('339966')" onClick="Set('339966')" height="10px" width="10px"></td>
<td bgcolor="#33CC66" onMouseOver="View('33CC66')" onClick="Set('33CC66')" height="10px" width="10px"></td>
<td bgcolor="#33FF66" onMouseOver="View('33FF66')" onClick="Set('33FF66')" height="10px" width="10px"></td>
<td bgcolor="#660066" onMouseOver="View('660066')" onClick="Set('660066')" height="10px" width="10px"></td>
<td bgcolor="#663366" onMouseOver="View('663366')" onClick="Set('663366')" height="10px" width="10px"></td>
<td bgcolor="#666666" onMouseOver="View('666666')" onClick="Set('666666')" height="10px" width="10px"></td>
<td bgcolor="#669966" onMouseOver="View('669966')" onClick="Set('669966')" height="10px" width="10px"></td>
<td bgcolor="#66CC66" onMouseOver="View('66CC66')" onClick="Set('66CC66')" height="10px" width="10px"></td>
<td bgcolor="#66FF66" onMouseOver="View('66FF66')" onClick="Set('66FF66')" height="10px" width="10px"></td>
</tr>
<tr>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#999999" onMouseOver="View('999999')" onClick="Set('999999')" height="10px" width="10px"></td>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#000099" onMouseOver="View('000099')" onClick="Set('000099')" height="10px" width="10px"></td>
<td bgcolor="#003399" onMouseOver="View('003399')" onClick="Set('003399')" height="10px" width="10px"></td>
<td bgcolor="#006699" onMouseOver="View('006699')" onClick="Set('006699')" height="10px" width="10px"></td>
<td bgcolor="#009999" onMouseOver="View('009999')" onClick="Set('009999')" height="10px" width="10px"></td>
<td bgcolor="#00CC99" onMouseOver="View('00CC99')" onClick="Set('00CC99')" height="10px" width="10px"></td>
<td bgcolor="#00FF99" onMouseOver="View('00FF99')" onClick="Set('00FF99')" height="10px" width="10px"></td>
<td bgcolor="#330099" onMouseOver="View('330099')" onClick="Set('330099')" height="10px" width="10px"></td>
<td bgcolor="#333399" onMouseOver="View('333399')" onClick="Set('333399')" height="10px" width="10px"></td>
<td bgcolor="#336699" onMouseOver="View('336699')" onClick="Set('336699')" height="10px" width="10px"></td>
<td bgcolor="#339999" onMouseOver="View('339999')" onClick="Set('339999')" height="10px" width="10px"></td>
<td bgcolor="#33CC99" onMouseOver="View('33CC99')" onClick="Set('33CC99')" height="10px" width="10px"></td>
<td bgcolor="#33FF99" onMouseOver="View('33FF99')" onClick="Set('33FF99')" height="10px" width="10px"></td>
<td bgcolor="#660099" onMouseOver="View('660099')" onClick="Set('660099')" height="10px" width="10px"></td>
<td bgcolor="#663399" onMouseOver="View('663399')" onClick="Set('663399')" height="10px" width="10px"></td>
<td bgcolor="#666699" onMouseOver="View('666699')" onClick="Set('666699')" height="10px" width="10px"></td>
<td bgcolor="#669999" onMouseOver="View('669999')" onClick="Set('669999')" height="10px" width="10px"></td>
<td bgcolor="#66CC99" onMouseOver="View('66CC99')" onClick="Set('66CC99')" height="10px" width="10px"></td>
<td bgcolor="#66FF99" onMouseOver="View('66FF99')" onClick="Set('66FF99')" height="10px" width="10px"></td>
</tr>
<tr>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#CCCCCC" onMouseOver="View('CCCCCC')" onClick="Set('CCCCCC')" height="10px" width="10px"></td>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#0000CC" onMouseOver="View('0000CC')" onClick="Set('0000CC')" height="10px" width="10px"></td>
<td bgcolor="#0033CC" onMouseOver="View('0033CC')" onClick="Set('0033CC')" height="10px" width="10px"></td>
<td bgcolor="#0066CC" onMouseOver="View('0066CC')" onClick="Set('0066CC')" height="10px" width="10px"></td>
<td bgcolor="#0099CC" onMouseOver="View('0099CC')" onClick="Set('0099CC')" height="10px" width="10px"></td>
<td bgcolor="#00CCCC" onMouseOver="View('00CCCC')" onClick="Set('00CCCC')" height="10px" width="10px"></td>
<td bgcolor="#00FFCC" onMouseOver="View('00FFCC')" onClick="Set('00FFCC')" height="10px" width="10px"></td>
<td bgcolor="#3300CC" onMouseOver="View('3300CC')" onClick="Set('3300CC')" height="10px" width="10px"></td>
<td bgcolor="#3333CC" onMouseOver="View('3333CC')" onClick="Set('3333CC')" height="10px" width="10px"></td>
<td bgcolor="#3366CC" onMouseOver="View('3366CC')" onClick="Set('3366CC')" height="10px" width="10px"></td>
<td bgcolor="#3399CC" onMouseOver="View('3399CC')" onClick="Set('3399CC')" height="10px" width="10px"></td>
<td bgcolor="#33CCCC" onMouseOver="View('33CCCC')" onClick="Set('33CCCC')" height="10px" width="10px"></td>
<td bgcolor="#33FFCC" onMouseOver="View('33FFCC')" onClick="Set('33FFCC')" height="10px" width="10px"></td>
<td bgcolor="#6600CC" onMouseOver="View('6600CC')" onClick="Set('6600CC')" height="10px" width="10px"></td>
<td bgcolor="#6633CC" onMouseOver="View('6633CC')" onClick="Set('6633CC')" height="10px" width="10px"></td>
<td bgcolor="#6666CC" onMouseOver="View('6666CC')" onClick="Set('6666CC')" height="10px" width="10px"></td>
<td bgcolor="#6699CC" onMouseOver="View('6699CC')" onClick="Set('6699CC')" height="10px" width="10px"></td>
<td bgcolor="#66CCCC" onMouseOver="View('66CCCC')" onClick="Set('66CCCC')" height="10px" width="10px"></td>
<td bgcolor="#66FFCC" onMouseOver="View('66FFCC')" onClick="Set('66FFCC')" height="10px" width="10px"></td>
</tr>
<tr>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#FFFFFF" onMouseOver="View('FFFFFF')" onClick="Set('FFFFFF')" height="10px" width="10px"></td>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#0000FF" onMouseOver="View('0000FF')" onClick="Set('0000FF')" height="10px" width="10px"></td>
<td bgcolor="#0033FF" onMouseOver="View('0033FF')" onClick="Set('0033FF')" height="10px" width="10px"></td>
<td bgcolor="#0066FF" onMouseOver="View('0066FF')" onClick="Set('0066FF')" height="10px" width="10px"></td>
<td bgcolor="#0099FF" onMouseOver="View('0099FF')" onClick="Set('0099FF')" height="10px" width="10px"></td>
<td bgcolor="#00CCFF" onMouseOver="View('00CCFF')" onClick="Set('00CCFF')" height="10px" width="10px"></td>
<td bgcolor="#00FFFF" onMouseOver="View('00FFFF')" onClick="Set('00FFFF')" height="10px" width="10px"></td>
<td bgcolor="#3300FF" onMouseOver="View('3300FF')" onClick="Set('3300FF')" height="10px" width="10px"></td>
<td bgcolor="#3333FF" onMouseOver="View('3333FF')" onClick="Set('3333FF')" height="10px" width="10px"></td>
<td bgcolor="#3366FF" onMouseOver="View('3366FF')" onClick="Set('3366FF')" height="10px" width="10px"></td>
<td bgcolor="#3399FF" onMouseOver="View('3399FF')" onClick="Set('3399FF')" height="10px" width="10px"></td>
<td bgcolor="#33CCFF" onMouseOver="View('33CCFF')" onClick="Set('33CCFF')" height="10px" width="10px"></td>
<td bgcolor="#33FFFF" onMouseOver="View('33FFFF')" onClick="Set('33FFFF')" height="10px" width="10px"></td>
<td bgcolor="#6600FF" onMouseOver="View('6600FF')" onClick="Set('6600FF')" height="10px" width="10px"></td>
<td bgcolor="#6633FF" onMouseOver="View('6633FF')" onClick="Set('6633FF')" height="10px" width="10px"></td>
<td bgcolor="#6666FF" onMouseOver="View('6666FF')" onClick="Set('6666FF')" height="10px" width="10px"></td>
<td bgcolor="#6699FF" onMouseOver="View('6699FF')" onClick="Set('6699FF')" height="10px" width="10px"></td>
<td bgcolor="#66CCFF" onMouseOver="View('66CCFF')" onClick="Set('66CCFF')" height="10px" width="10px"></td>
<td bgcolor="#66FFFF" onMouseOver="View('66FFFF')" onClick="Set('66FFFF')" height="10px" width="10px"></td>
</tr>
<tr>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#FF0000" onMouseOver="View('FF0000')" onClick="Set('FF0000')" height="10px" width="10px"></td>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#990000" onMouseOver="View('990000')" onClick="Set('990000')" height="10px" width="10px"></td>
<td bgcolor="#993300" onMouseOver="View('993300')" onClick="Set('993300')" height="10px" width="10px"></td>
<td bgcolor="#996600" onMouseOver="View('996600')" onClick="Set('996600')" height="10px" width="10px"></td>
<td bgcolor="#999900" onMouseOver="View('999900')" onClick="Set('999900')" height="10px" width="10px"></td>
<td bgcolor="#99CC00" onMouseOver="View('99CC00')" onClick="Set('99CC00')" height="10px" width="10px"></td>
<td bgcolor="#99FF00" onMouseOver="View('99FF00')" onClick="Set('99FF00')" height="10px" width="10px"></td>
<td bgcolor="#CC0000" onMouseOver="View('CC0000')" onClick="Set('CC0000')" height="10px" width="10px"></td>
<td bgcolor="#CC3300" onMouseOver="View('CC3300')" onClick="Set('CC3300')" height="10px" width="10px"></td>
<td bgcolor="#CC6600" onMouseOver="View('CC6600')" onClick="Set('CC6600')" height="10px" width="10px"></td>
<td bgcolor="#CC9900" onMouseOver="View('CC9900')" onClick="Set('CC9900')" height="10px" width="10px"></td>
<td bgcolor="#CCCC00" onMouseOver="View('CCCC00')" onClick="Set('CCCC00')" height="10px" width="10px"></td>
<td bgcolor="#CCFF00" onMouseOver="View('CCFF00')" onClick="Set('CCFF00')" height="10px" width="10px"></td>
<td bgcolor="#FF0000" onMouseOver="View('FF0000')" onClick="Set('FF0000')" height="10px" width="10px"></td>
<td bgcolor="#FF3300" onMouseOver="View('FF3300')" onClick="Set('FF3300')" height="10px" width="10px"></td>
<td bgcolor="#FF6600" onMouseOver="View('FF6600')" onClick="Set('FF6600')" height="10px" width="10px"></td>
<td bgcolor="#FF9900" onMouseOver="View('FF9900')" onClick="Set('FF9900')" height="10px" width="10px"></td>
<td bgcolor="#FFCC00" onMouseOver="View('FFCC00')" onClick="Set('FFCC00')" height="10px" width="10px"></td>
<td bgcolor="#FFFF00" onMouseOver="View('FFFF00')" onClick="Set('FFFF00')" height="10px" width="10px"></td>
</tr>
<tr>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#00FF00" onMouseOver="View('00FF00')" onClick="Set('00FF00')" height="10px" width="10px"></td>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#990033" onMouseOver="View('990033')" onClick="Set('990033')" height="10px" width="10px"></td>
<td bgcolor="#993333" onMouseOver="View('993333')" onClick="Set('993333')" height="10px" width="10px"></td>
<td bgcolor="#996633" onMouseOver="View('996633')" onClick="Set('996633')" height="10px" width="10px"></td>
<td bgcolor="#999933" onMouseOver="View('999933')" onClick="Set('999933')" height="10px" width="10px"></td>
<td bgcolor="#99CC33" onMouseOver="View('99CC33')" onClick="Set('99CC33')" height="10px" width="10px"></td>
<td bgcolor="#99FF33" onMouseOver="View('99FF33')" onClick="Set('99FF33')" height="10px" width="10px"></td>
<td bgcolor="#CC0033" onMouseOver="View('CC0033')" onClick="Set('CC0033')" height="10px" width="10px"></td>
<td bgcolor="#CC3333" onMouseOver="View('CC3333')" onClick="Set('CC3333')" height="10px" width="10px"></td>
<td bgcolor="#CC6633" onMouseOver="View('CC6633')" onClick="Set('CC6633')" height="10px" width="10px"></td>
<td bgcolor="#CC9933" onMouseOver="View('CC9933')" onClick="Set('CC9933')" height="10px" width="10px"></td>
<td bgcolor="#CCCC33" onMouseOver="View('CCCC33')" onClick="Set('CCCC33')" height="10px" width="10px"></td>
<td bgcolor="#CCFF33" onMouseOver="View('CCFF33')" onClick="Set('CCFF33')" height="10px" width="10px"></td>
<td bgcolor="#FF0033" onMouseOver="View('FF0033')" onClick="Set('FF0033')" height="10px" width="10px"></td>
<td bgcolor="#FF3333" onMouseOver="View('FF3333')" onClick="Set('FF3333')" height="10px" width="10px"></td>
<td bgcolor="#FF6633" onMouseOver="View('FF6633')" onClick="Set('FF6633')" height="10px" width="10px"></td>
<td bgcolor="#FF9933" onMouseOver="View('FF9933')" onClick="Set('FF9933')" height="10px" width="10px"></td>
<td bgcolor="#FFCC33" onMouseOver="View('FFCC33')" onClick="Set('FFCC33')" height="10px" width="10px"></td>
<td bgcolor="#FFFF33" onMouseOver="View('FFFF33')" onClick="Set('FFFF33')" height="10px" width="10px"></td>
</tr>
<tr>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#0000FF" onMouseOver="View('0000FF')" onClick="Set('0000FF')" height="10px" width="10px"></td>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#990066" onMouseOver="View('990066')" onClick="Set('990066')" height="10px" width="10px"></td>
<td bgcolor="#993366" onMouseOver="View('993366')" onClick="Set('993366')" height="10px" width="10px"></td>
<td bgcolor="#996666" onMouseOver="View('996666')" onClick="Set('996666')" height="10px" width="10px"></td>
<td bgcolor="#999966" onMouseOver="View('999966')" onClick="Set('999966')" height="10px" width="10px"></td>
<td bgcolor="#99CC66" onMouseOver="View('99CC66')" onClick="Set('99CC66')" height="10px" width="10px"></td>
<td bgcolor="#99FF66" onMouseOver="View('99FF66')" onClick="Set('99FF66')" height="10px" width="10px"></td>
<td bgcolor="#CC0066" onMouseOver="View('CC0066')" onClick="Set('CC0066')" height="10px" width="10px"></td>
<td bgcolor="#CC3366" onMouseOver="View('CC3366')" onClick="Set('CC3366')" height="10px" width="10px"></td>
<td bgcolor="#CC6666" onMouseOver="View('CC6666')" onClick="Set('CC6666')" height="10px" width="10px"></td>
<td bgcolor="#CC9966" onMouseOver="View('CC9966')" onClick="Set('CC9966')" height="10px" width="10px"></td>
<td bgcolor="#CCCC66" onMouseOver="View('CCCC66')" onClick="Set('CCCC66')" height="10px" width="10px"></td>
<td bgcolor="#CCFF66" onMouseOver="View('CCFF66')" onClick="Set('CCFF66')" height="10px" width="10px"></td>
<td bgcolor="#FF0066" onMouseOver="View('FF0066')" onClick="Set('FF0066')" height="10px" width="10px"></td>
<td bgcolor="#FF3366" onMouseOver="View('FF3366')" onClick="Set('FF3366')" height="10px" width="10px"></td>
<td bgcolor="#FF6666" onMouseOver="View('FF6666')" onClick="Set('FF6666')" height="10px" width="10px"></td>
<td bgcolor="#FF9966" onMouseOver="View('FF9966')" onClick="Set('FF9966')" height="10px" width="10px"></td>
<td bgcolor="#FFCC66" onMouseOver="View('FFCC66')" onClick="Set('FFCC66')" height="10px" width="10px"></td>
<td bgcolor="#FFFF66" onMouseOver="View('FFFF66')" onClick="Set('FFFF66')" height="10px" width="10px"></td>
</tr>
<tr>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#FFFF00" onMouseOver="View('FFFF00')" onClick="Set('FFFF00')" height="10px" width="10px"></td>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#990099" onMouseOver="View('990099')" onClick="Set('990099')" height="10px" width="10px"></td>
<td bgcolor="#993399" onMouseOver="View('993399')" onClick="Set('993399')" height="10px" width="10px"></td>
<td bgcolor="#996699" onMouseOver="View('996699')" onClick="Set('996699')" height="10px" width="10px"></td>
<td bgcolor="#999999" onMouseOver="View('999999')" onClick="Set('999999')" height="10px" width="10px"></td>
<td bgcolor="#99CC99" onMouseOver="View('99CC99')" onClick="Set('99CC99')" height="10px" width="10px"></td>
<td bgcolor="#99FF99" onMouseOver="View('99FF99')" onClick="Set('99FF99')" height="10px" width="10px"></td>
<td bgcolor="#CC0099" onMouseOver="View('CC0099')" onClick="Set('CC0099')" height="10px" width="10px"></td>
<td bgcolor="#CC3399" onMouseOver="View('CC3399')" onClick="Set('CC3399')" height="10px" width="10px"></td>
<td bgcolor="#CC6699" onMouseOver="View('CC6699')" onClick="Set('CC6699')" height="10px" width="10px"></td>
<td bgcolor="#CC9999" onMouseOver="View('CC9999')" onClick="Set('CC9999')" height="10px" width="10px"></td>
<td bgcolor="#CCCC99" onMouseOver="View('CCCC99')" onClick="Set('CCCC99')" height="10px" width="10px"></td>
<td bgcolor="#CCFF99" onMouseOver="View('CCFF99')" onClick="Set('CCFF99')" height="10px" width="10px"></td>
<td bgcolor="#FF0099" onMouseOver="View('FF0099')" onClick="Set('FF0099')" height="10px" width="10px"></td>
<td bgcolor="#FF3399" onMouseOver="View('FF3399')" onClick="Set('FF3399')" height="10px" width="10px"></td>
<td bgcolor="#FF6699" onMouseOver="View('FF6699')" onClick="Set('FF6699')" height="10px" width="10px"></td>
<td bgcolor="#FF9999" onMouseOver="View('FF9999')" onClick="Set('FF9999')" height="10px" width="10px"></td>
<td bgcolor="#FFCC99" onMouseOver="View('FFCC99')" onClick="Set('FFCC99')" height="10px" width="10px"></td>
<td bgcolor="#FFFF99" onMouseOver="View('FFFF99')" onClick="Set('FFFF99')" height="10px" width="10px"></td>
</tr>
<tr>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#00FFFF" onMouseOver="View('00FFFF')" onClick="Set('00FFFF')" height="10px" width="10px"></td>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#9900CC" onMouseOver="View('9900CC')" onClick="Set('9900CC')" height="10px" width="10px"></td>
<td bgcolor="#9933CC" onMouseOver="View('9933CC')" onClick="Set('9933CC')" height="10px" width="10px"></td>
<td bgcolor="#9966CC" onMouseOver="View('9966CC')" onClick="Set('9966CC')" height="10px" width="10px"></td>
<td bgcolor="#9999CC" onMouseOver="View('9999CC')" onClick="Set('9999CC')" height="10px" width="10px"></td>
<td bgcolor="#99CCCC" onMouseOver="View('99CCCC')" onClick="Set('99CCCC')" height="10px" width="10px"></td>
<td bgcolor="#99FFCC" onMouseOver="View('99FFCC')" onClick="Set('99FFCC')" height="10px" width="10px"></td>
<td bgcolor="#CC00CC" onMouseOver="View('CC00CC')" onClick="Set('CC00CC')" height="10px" width="10px"></td>
<td bgcolor="#CC33CC" onMouseOver="View('CC33CC')" onClick="Set('CC33CC')" height="10px" width="10px"></td>
<td bgcolor="#CC66CC" onMouseOver="View('CC66CC')" onClick="Set('CC66CC')" height="10px" width="10px"></td>
<td bgcolor="#CC99CC" onMouseOver="View('CC99CC')" onClick="Set('CC99CC')" height="10px" width="10px"></td>
<td bgcolor="#CCCCCC" onMouseOver="View('CCCCCC')" onClick="Set('CCCCCC')" height="10px" width="10px"></td>
<td bgcolor="#CCFFCC" onMouseOver="View('CCFFCC')" onClick="Set('CCFFCC')" height="10px" width="10px"></td>
<td bgcolor="#FF00CC" onMouseOver="View('FF00CC')" onClick="Set('FF00CC')" height="10px" width="10px"></td>
<td bgcolor="#FF33CC" onMouseOver="View('FF33CC')" onClick="Set('FF33CC')" height="10px" width="10px"></td>
<td bgcolor="#FF66CC" onMouseOver="View('FF66CC')" onClick="Set('FF66CC')" height="10px" width="10px"></td>
<td bgcolor="#FF99CC" onMouseOver="View('FF99CC')" onClick="Set('FF99CC')" height="10px" width="10px"></td>
<td bgcolor="#FFCCCC" onMouseOver="View('FFCCCC')" onClick="Set('FFCCCC')" height="10px" width="10px"></td>
<td bgcolor="#FFFFCC" onMouseOver="View('FFFFCC')" onClick="Set('FFFFCC')" height="10px" width="10px"></td>
</tr>
<tr>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#FF00FF" onMouseOver="View('FF00FF')" onClick="Set('FF00FF')" height="10px" width="10px"></td>
<td bgcolor="#000000" onMouseOver="View('000000')" onClick="Set('000000')" height="10px" width="10px"></td>
<td bgcolor="#9900FF" onMouseOver="View('9900FF')" onClick="Set('9900FF')" height="10px" width="10px"></td>
<td bgcolor="#9933FF" onMouseOver="View('9933FF')" onClick="Set('9933FF')" height="10px" width="10px"></td>
<td bgcolor="#9966FF" onMouseOver="View('9966FF')" onClick="Set('9966FF')" height="10px" width="10px"></td>
<td bgcolor="#9999FF" onMouseOver="View('9999FF')" onClick="Set('9999FF')" height="10px" width="10px"></td>
<td bgcolor="#99CCFF" onMouseOver="View('99CCFF')" onClick="Set('99CCFF')" height="10px" width="10px"></td>
<td bgcolor="#99FFFF" onMouseOver="View('99FFFF')" onClick="Set('99FFFF')" height="10px" width="10px"></td>
<td bgcolor="#CC00FF" onMouseOver="View('CC00FF')" onClick="Set('CC00FF')" height="10px" width="10px"></td>
<td bgcolor="#CC33FF" onMouseOver="View('CC33FF')" onClick="Set('CC33FF')" height="10px" width="10px"></td>
<td bgcolor="#CC66FF" onMouseOver="View('CC66FF')" onClick="Set('CC66FF')" height="10px" width="10px"></td>
<td bgcolor="#CC99FF" onMouseOver="View('CC99FF')" onClick="Set('CC99FF')" height="10px" width="10px"></td>
<td bgcolor="#CCCCFF" onMouseOver="View('CCCCFF')" onClick="Set('CCCCFF')" height="10px" width="10px"></td>
<td bgcolor="#CCFFFF" onMouseOver="View('CCFFFF')" onClick="Set('CCFFFF')" height="10px" width="10px"></td>
<td bgcolor="#FF00FF" onMouseOver="View('FF00FF')" onClick="Set('FF00FF')" height="10px" width="10px"></td>
<td bgcolor="#FF33FF" onMouseOver="View('FF33FF')" onClick="Set('FF33FF')" height="10px" width="10px"></td>
<td bgcolor="#FF66FF" onMouseOver="View('FF66FF')" onClick="Set('FF66FF')" height="10px" width="10px"></td>
<td bgcolor="#FF99FF" onMouseOver="View('FF99FF')" onClick="Set('FF99FF')" height="10px" width="10px"></td>
<td bgcolor="#FFCCFF" onMouseOver="View('FFCCFF')" onClick="Set('FFCCFF')" height="10px" width="10px"></td>
<td bgcolor="#FFFFFF" onMouseOver="View('FFFFFF')" onClick="Set('FFFFFF')" height="10px" width="10px"></td>
</tr>
</table>
</body></html>