/** * encode a sequence of HTML tags, or plain text, to PDF * * @param string the text to append * @return the content of PDF * @see articles/fetch_as_pdf.php */ function encode($text) { global $context; // // meta information // // encode it to iso8859 -- sorry // document title if ($context['page_title']) { $this->SetTitle(utf8::to_iso8859(Safe::html_entity_decode($context['page_title'], ENT_COMPAT, 'ISO-8859-15'))); } // document author if ($context['page_author']) { $this->SetAuthor(utf8::to_iso8859(Safe::html_entity_decode($context['page_author'], ENT_COMPAT, 'ISO-8859-15'))); } // document subject if ($context['subject']) { $this->SetSubject(utf8::to_iso8859(Safe::html_entity_decode($context['subject'], ENT_COMPAT, 'ISO-8859-15'))); } // document creator (typically, the tool used to produce the document) $this->SetCreator('yacs'); // // PDF content // // start the rendering engine $this->AliasNbPages(); $this->AddPage(); $this->SetFont('Arial', 'B', 16); // reference view.php instead of ourself to achieve correct links $text = str_replace('/fetch_as_pdf.php', '/view.php', $text); // remove all unsupported tags $text = strip_tags($text, "<a><b><blockquote><br><code><div><em><font><h1><h2><h3><h4><hr><i><img><li><p><pre><strong><table><tr><tt><u><ul>"); // spaces instead of carriage returns $text = str_replace("\n", ' ', $text); // transcode to ISO8859-15 characters $text = utf8::to_iso8859(Safe::html_entity_decode($text, ENT_COMPAT, 'ISO-8859-15')); // locate every HTML/XML tag $areas = preg_split('/<(.*)>/U', $text, -1, PREG_SPLIT_DELIM_CAPTURE); $height = 5; $link = ''; foreach ($areas as $index => $entity) { // a tag entity if ($index % 2) { @(list($tag, $attributes) = explode(' ', $entity, 2)); switch (strtolower($tag)) { case 'a': if (preg_match('/href="(.*)"/i', $attributes, $matches)) { $link = $matches[1]; // suppress local references (eg, in table of content) if (preg_match('/(#.*)/', $link)) { $link = ''; } elseif ($link[0] == '/') { $link = $context['url_to_home'] . $link; } } break; case 'b': $this->SetFont('', 'B'); break; case '/b': $this->SetFont('', ''); break; case 'blockquote': $this->Ln($height); break; case '/blockquote': $this->Ln($height); break; case 'br': $this->Ln($height); break; case 'code': $this->SetFont('Courier', '', 11); $this->SetFontSize(11); break; case '/code': $this->SetFont('Times', '', 12); $this->SetFontSize(12); break; case 'div': case '/div': $this->Ln($height); break; case 'em': $this->SetFont('', 'I'); break; case '/em': $this->SetFont('', ''); break; case 'font': if (preg_match('/color="#(.{6})"/i', $attributes, $matches)) { $color = $matches[1]; $r = hexdec($color[0] . $color[1]); $g = hexdec($color[2] . $color[3]); $b = hexdec($color[4] . $color[5]); $this->SetTextColor($r, $g, $b); } break; case 'font': $this->SetFont('Times', '', 12); $this->SetTextColor(0, 0, 0); $this->SetFontSize(12); break; case 'h1': $this->Ln(10); $this->SetTextColor(150, 0, 0); $this->SetFontSize(22); $height = 8; break; case 'h2': $this->Ln(8); $this->SetFontSize(18); $height = 6; break; case 'h3': $this->Ln(6); $this->SetFontSize(16); $height = 5; break; case 'h4': $this->Ln(6); $this->SetTextColor(102, 0, 0); $this->SetFontSize(14); $height = 5; break; case '/h1': case '/h2': case '/h3': case '/h4': $this->Ln($height); $this->SetFont('Times', '', 12); $this->SetTextColor(0, 0, 0); $this->SetFontSize(12); $height = 5; break; case 'hr': $this->Ln($height + 2); $this->Line($this->GetX(), $this->GetY(), $this->GetX() + 187, $this->GetY()); $this->Ln(3); break; case 'i': $this->SetFont('', 'I'); break; case '/i': $this->SetFont('', ''); break; case 'img': // only accept JPG and PNG if (preg_match('/src="([^"]+\\.(jpg|jpeg|png))"/i', $attributes, $matches)) { $image = $matches[1]; // map on a file $image = preg_replace('/^' . preg_quote($context['url_to_home'] . $context['url_to_root'], '/') . '/', $context['path_to_root'], $image); // include the image only if the file exists if ($attributes = Safe::GetImageSize($image)) { // insert an image at 72 dpi -- the k factor $this->Image($image, $this->GetX(), $this->GetY(), $attributes[0] / $this->k, $attributes[1] / $this->k); // make room for the image $this->y += 3 + $attributes[1] / $this->k; } } break; case 'li': $this->Ln($height); break; case '/li': break; case 'p': case '/p': $this->Ln($height); break; case 'pre': $this->SetFont('Courier', '', 11); $this->SetFontSize(11); $preformatted = TRUE; break; case '/pre': $this->SetFont('Times', '', 12); $this->SetFontSize(12); $preformatted = FALSE; break; case 'strong': $this->SetFont('', 'B'); break; case '/strong': $this->SetFont('', ''); break; case 'table': $this->Ln($height); break; case '/table': $this->Ln($height); break; case 'tr': $this->Ln($height + 2); $this->Line($this->GetX(), $this->GetY(), $this->GetX() + 187, $this->GetY()); $this->Ln(3); break; case 'tt': $this->SetFont('Courier', '', 11); $this->SetFontSize(11); break; case '/tt': $this->SetFont('Times', '', 12); $this->SetFontSize(12); break; case 'u': $this->SetFont('', 'U'); break; case '/u': $this->SetFont('', ''); break; case 'ul': break; case '/ul': break; } // a textual entity } else { // we have to write a link if ($link) { // a blue underlined link $this->SetTextColor(0, 0, 255); $this->SetFont('', 'U'); $this->Write($height, $entity, $link); $link = ''; $this->SetTextColor(0, 0, 0); $this->SetFont('', ''); // regular text } else { $this->Write($height, $entity); } } } // return the PDF content as a string return $this->Output('dummy', 'S'); }
/** * process one uploaded image * * @param string file name * @param string path to the file * @param boolean TRUE to not report on errors * @return boolean TRUE on correct processing, FALSE otherwise */ public static function upload($file_name, $file_path, $silent = FALSE) { global $context, $_REQUEST; // we accept only valid images if (!($image_information = Safe::GetImageSize($file_path . $file_name))) { if (!$silent) { Logger::error(sprintf(i18n::s('No image information in %s'), $file_path . $file_name)); } return FALSE; // we accept only gif, jpeg and png } elseif ($image_information[2] != 1 && $image_information[2] != 2 && $image_information[2] != 3) { if (!$silent) { Logger::error(sprintf(i18n::s('Rejected file type %s'), $file_name)); } return FALSE; // post-upload processing } else { // create folders $_REQUEST['thumbnail_name'] = 'thumbs/' . $file_name; // derive a thumbnail image if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'set_as_avatar') { Image::shrink($file_path . $file_name, $file_path . $_REQUEST['thumbnail_name'], TRUE, TRUE); } else { Image::shrink($file_path . $file_name, $file_path . $_REQUEST['thumbnail_name'], FALSE, TRUE); } // always limit the size of avatar images if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'set_as_avatar') { if (Image::adjust($file_path . $file_name, TRUE, 'avatar')) { $_REQUEST['image_size'] = Safe::filesize($file_path . $file_name); } // always limit the size of icon images } elseif (isset($_REQUEST['action']) && $_REQUEST['action'] == 'set_as_icon') { if (Image::adjust($file_path . $file_name, TRUE, 'avatar')) { $_REQUEST['image_size'] = Safe::filesize($file_path . $file_name); } // resize the image where applicable } elseif (isset($_REQUEST['automatic_process'])) { if (Image::adjust($file_path . $file_name, TRUE, 'standard')) { $_REQUEST['image_size'] = Safe::filesize($file_path . $file_name); } } return TRUE; } }
/** * list articles * * @param resource the SQL result * @return string the rendered text * * @see layouts/layout.php **/ function layout($result) { global $context; // we return some text $text = ''; // empty list if (!SQL::count($result)) { return $text; } // sanity check if (!isset($this->focus)) { $this->focus = 'map'; } // put in cache $cache_id = Cache::hash('articles/layout_articles_as_carrousel:' . $this->focus) . '.xml'; // save for one minute if (!file_exists($context['path_to_root'] . $cache_id) || filemtime($context['path_to_root'] . $cache_id) + 60 < time()) { // content of the slideshow $content = '<?xml version="1.0" encoding="utf-8"?><!-- fhShow Carousel 2.0 configuration file Please visit http://www.flshow.net/ -->' . "\n" . '<slide_show>' . "\n" . ' <options>' . "\n" . ' <debug>false</debug> <!-- true, false -->' . "\n" . ' <background>transparent</background> <!-- #RRGGBB, transparent -->' . "\n" . ' <friction>5</friction> <!-- [1,100] -->' . "\n" . ' <fullscreen>false</fullscreen> <!-- true, false -->' . "\n" . ' <margins>' . "\n" . ' <top>0</top> <!-- [-1000,1000] pixels -->' . "\n" . ' <left>0</left> <!-- [-1000,1000] pixels -->' . "\n" . ' <bottom>0</bottom> <!-- [-1000,1000] pixels -->' . "\n" . ' <right>0</right> <!-- [-1000,1000] pixels -->' . "\n" . ' <horizontal_ratio>20%</horizontal_ratio> <!-- [1,50] a photo may occupy at most horizontalRatio percent of the Carousel width -->' . "\n" . ' <vertical_ratio>90%</vertical_ratio> <!-- [1,100] a photo may occupy at most verticalRatio percent of the Carousel height -->' . "\n" . ' </margins>' . "\n" . ' <interaction>' . "\n" . ' <rotation>mouse</rotation> <!-- auto, mouse, keyboard -->' . "\n" . ' <view_point>none</view_point> <!-- none, mouse, keyboard -->' . "\n" . ' <speed>15</speed> <!-- [-360,360] degrees per second -->' . "\n" . ' <default_speed>15</default_speed> <!-- [-360,360] degrees per second -->' . "\n" . ' <default_view_point>20%</default_view_point> <!-- [0,100] percentage -->' . "\n" . ' <reset_delay>20</reset_delay> <!-- [0,600] seconds, 0 means never reset -->' . "\n" . ' </interaction>' . "\n" . ' <far_photos>' . "\n" . ' <size>50%</size> <!-- [0,100] percentage -->' . "\n" . ' <amount>50%</amount> <!-- [0,100] percentage -->' . "\n" . ' <blur>10</blur> <!-- [0,100] amount -->' . "\n" . ' <blur_quality>3</blur_quality> <!-- [1,3] 1=low - 3=high -->' . "\n" . ' </far_photos>' . "\n" . ' <reflection>' . "\n" . ' <amount>25</amount> <!-- [0,1000] pixels -->' . "\n" . ' <blur>2</blur> <!-- [0,100] blur amount -->' . "\n" . ' <distance>0</distance> <!-- [-1000,1000] pixels -->' . "\n" . ' <alpha>40%</alpha> <!-- [0,100] percentage -->' . "\n" . ' </reflection>' . "\n" . ' <titles>' . "\n" . ' <style>font-size: 14px; font-family: Verdana, _serif; color: #000000;</style>' . "\n" . ' <position>above center</position> <!-- [above, below] [left,center,right]-->' . "\n" . ' <background>' . $context['url_to_home'] . $context['url_to_root'] . 'skins/_reference/layouts/carrousel_bubble.png</background> <!-- image url -->' . "\n" . ' <scale9>35 35 35 35</scale9> <!-- [0,1000] pixels -->' . "\n" . ' <padding>8 15 10 15</padding> <!-- [-1000,1000] pixels -->' . "\n" . ' </titles>' . "\n" . ' </options>' . "\n"; // get a default image if (Safe::GetImageSize($context['path_to_root'] . $context['skin'] . '/layouts/map.gif')) { $default_href = $context['url_to_root'] . $context['skin'] . '/layouts/map.gif'; } elseif ($size = Safe::GetImageSize($context['path_to_root'] . 'skins/_reference/layouts/map.gif')) { $default_href = $context['url_to_root'] . 'skins/_reference/layouts/map.gif'; } else { $default_href = NULL; } // process all items in the list while ($item = SQL::fetch($result)) { // get the related overlay $overlay = Overlay::load($item, 'article:' . $item['id']); // get the anchor $anchor = Anchors::get($item['anchor']); // this is visual if (isset($item['icon_url']) && $item['icon_url']) { $image = $item['icon_url']; } elseif (isset($item['thumbnail_url']) && $item['thumbnail_url']) { $image = $item['thumbnail_url']; } elseif (is_callable(array($anchor, 'get_bullet_url')) && ($image = $anchor->get_bullet_url())) { } elseif ($default_href) { $image = $default_href; } else { continue; } // fix relative path if (!preg_match('/^(\\/|http:|https:|ftp:)/', $image)) { $image = $context['url_to_home'] . $context['url_to_root'] . $image; } // build a title if (is_object($overlay)) { $title = Codes::beautify_title($overlay->get_text('title', $item)); } else { $title = Codes::beautify_title($item['title']); } // the url to view this item $url = Articles::get_permalink($item); // add to the list $content .= ' <photo>' . "\n" . ' <title>' . $title . '</title>' . "\n" . ' <src>' . $image . '</src>' . "\n" . ' <href>' . $url . '</href>' . "\n" . ' <target>_self</target>' . "\n" . ' </photo>' . "\n"; } // finalize slideshow content $content .= '</slide_show>'; // put in cache Safe::file_put_contents($cache_id, $content); } // allow multiple instances static $count; if (!isset($count)) { $count = 1; } else { $count++; } // load the right file $text = '<div id="articles_as_carrousel_' . $count . '"></div>' . "\n"; Page::insert_script('swfobject.embedSWF("' . $context['url_to_home'] . $context['url_to_root'] . 'included/browser/carrousel.swf",' . "\n" . '"articles_as_carrousel_' . $count . '",' . "\n" . '"100%",' . "\n" . '"150",' . "\n" . '"9.0.0",' . "\n" . 'false,' . "\n" . '{xmlfile:"' . $context['url_to_home'] . $context['url_to_root'] . $cache_id . '", loaderColor:"0x666666"},' . "\n" . '{wmode: "transparent"},' . "\n" . '{});' . "\n"); // end of processing SQL::free($result); return $text; }
/** * get a <img> element * * @param the type ('suggestion', etc.') * @return a suitable HTML element * * @see skins/skin_skeleton.php */ public static function get_img($type) { global $context; switch ($type) { // approval case 'approval': // use skin declaration if any if (!defined('APPROVAL_IMG')) { // else use default image file $file = 'skins/_reference/comments/yes.gif'; if ($size = Safe::GetImageSize($context['path_to_root'] . $file)) { define('APPROVAL_IMG', '<img src="' . $context['url_to_root'] . $file . '" ' . $size[3] . ' alt="" />'); } else { define('APPROVAL_IMG', ''); } } return APPROVAL_IMG; // it's worth the reading // it's worth the reading case 'attention': case 'default': default: // use skin declaration if any if (!defined('ATTENTION_IMG')) { // else use default image file $file = 'skins/_reference/comments/attention.gif'; if ($size = Safe::GetImageSize($context['path_to_root'] . $file)) { define('ATTENTION_IMG', '<img src="' . $context['url_to_root'] . $file . '" ' . $size[3] . ' alt="" />'); } else { define('ATTENTION_IMG', ''); } } return ATTENTION_IMG; // denial // denial case 'denial': // use skin declaration if any if (!defined('DENIAL_IMG')) { // else use default image file $file = 'skins/_reference/comments/no.gif'; if ($size = Safe::GetImageSize($context['path_to_root'] . $file)) { define('DENIAL_IMG', '<img src="' . $context['url_to_root'] . $file . '" ' . $size[3] . ' alt="" />'); } else { define('DENIAL_IMG', ''); } } return DENIAL_IMG; // job has been completed // job has been completed case 'done': // use skin declaration if any if (!defined('DONE_IMG')) { // else use default image file $file = 'skins/_reference/comments/done.gif'; if ($size = Safe::GetImageSize($context['path_to_root'] . $file)) { define('DONE_IMG', '<img src="' . $context['url_to_root'] . $file . '" ' . $size[3] . ' alt="" />'); } else { define('DONE_IMG', ''); } } return DONE_IMG; // to submit a new suggestion // to submit a new suggestion case 'idea': case 'suggestion': //-- legacy keyword // use skin declaration if any if (!defined('IDEA_IMG')) { // else use default image file $file = 'skins/_reference/comments/idea.gif'; if ($size = Safe::GetImageSize($context['path_to_root'] . $file)) { define('IDEA_IMG', '<img src="' . $context['url_to_root'] . $file . '" ' . $size[3] . ' alt="" />'); } else { define('IDEA_IMG', ''); } } return IDEA_IMG; // manual or automatic notification // manual or automatic notification case 'information': case 'notification': // use skin declaration if any if (!defined('INFORMATION_IMG')) { // else use default image file $file = 'skins/_reference/comments/information.gif'; if ($size = Safe::GetImageSize($context['path_to_root'] . $file)) { define('INFORMATION_IMG', '<img src="' . $context['url_to_root'] . $file . '" ' . $size[3] . ' alt="" />'); } else { define('INFORMATION_IMG', ''); } } return INFORMATION_IMG; // please help // please help case 'question': // use skin declaration if any if (!defined('QUESTION_IMG')) { // else use default image file $file = 'skins/_reference/comments/question.gif'; if ($size = Safe::GetImageSize($context['path_to_root'] . $file)) { define('QUESTION_IMG', '<img src="' . $context['url_to_root'] . $file . '" ' . $size[3] . ' alt="" />'); } else { define('QUESTION_IMG', ''); } } return QUESTION_IMG; // I dislike it // I dislike it case 'thumbs_down': case 'dislike': //-- legacy keyword // use skin declaration if any if (!defined('THUMBS_DOWN_IMG')) { // else use default image file $file = 'skins/_reference/comments/thumbs_down.gif'; if ($size = Safe::GetImageSize($context['path_to_root'] . $file)) { define('THUMBS_DOWN_IMG', '<img src="' . $context['url_to_root'] . $file . '" ' . $size[3] . ' alt="" />'); } else { define('THUMBS_DOWN_IMG', ''); } } return THUMBS_DOWN_IMG; // I like it // I like it case 'thumbs_up': case 'like': //-- legacy keyword // use skin declaration if any if (!defined('THUMBS_UP_IMG')) { // else use default image file $file = 'skins/_reference/comments/thumbs_up.gif'; if ($size = Safe::GetImageSize($context['path_to_root'] . $file)) { define('THUMBS_UP_IMG', '<img src="' . $context['url_to_root'] . $file . '" ' . $size[3] . ' alt="" />'); } else { define('THUMBS_UP_IMG', ''); } } return THUMBS_UP_IMG; // you should take care // you should take care case 'warning': // use skin declaration if any if (!defined('WARNING_IMG')) { // else use default image file $file = 'skins/_reference/comments/warning.gif'; if ($size = Safe::GetImageSize($context['path_to_root'] . $file)) { define('WARNING_IMG', '<img src="' . $context['url_to_root'] . $file . '" ' . $size[3] . ' alt="" />'); } else { define('WARNING_IMG', ''); } } return WARNING_IMG; } }
/** * create a referenced image * * @param array of entity attributes (e.g., 'Content-Disposition') * @param string image actual content * @param array poster attributes * @param string the target anchor (e.g., 'article:123') * @param string reference of the object to be extended, if any * @return string reference to the created object, or NULL */ public static function submit_image($entity_headers, $content, $user, $anchor, $target = NULL) { global $context; // retrieve queue parameters list($server, $account, $password, $allowed, $match, $section, $options, $hooks, $prefix, $suffix) = $context['mail_queue']; // locate content-disposition foreach ($entity_headers as $header) { if (preg_match('/Content-Disposition/i', $header['name'])) { $content_disposition = $header['value']; break; } } // find file name in content-disposition $file_name = ''; if ($content_disposition && preg_match('/filename="*([a-zA-Z0-9\'\\(\\)\\+_,-\\.\\/:=\\? ]+)"*\\s*/i', $content_disposition, $matches)) { $file_name = $matches[1]; } // as an alternative, look in content-type if (!$file_name) { // locate content-type foreach ($entity_headers as $header) { if (preg_match('/Content-Type/i', $header['name'])) { $content_type = $header['value']; break; } } // find file name in content-type if ($content_type && preg_match('/name="*([a-zA-Z0-9\'\\(\\)\\+_,-\\.\\/:=\\? ]+)"*\\s*/i', $content_type, $matches)) { $file_name = $matches[1]; } } // as an alternative, look in content-description if (!$file_name) { // locate content-description foreach ($entity_headers as $header) { if (preg_match('/Content-Description/i', $header['name'])) { $content_description = $header['value']; break; } } // find file name in content-description $file_name = $content_description; } // sanity check if (!$file_name) { Logger::remember('agents/messages.php: No file name to use for submitted image'); return NULL; } // file size $file_size = strlen($content); // sanity check if ($file_size < 7) { Logger::remember('agents/messages.php: Short image skipped', $file_name); return NULL; } // sanity check if (!$anchor) { Logger::remember('agents/messages.php: No anchor to use for submitted image', $file_name); return NULL; } // get anchor data -- this is a mutable object $host = Anchors::get($anchor, TRUE); if (!is_object($host)) { Logger::remember('agents/messages.php: Unknown anchor ' . $anchor, $file_name); return NULL; } // create target folders $file_path = Files::get_path($anchor, 'images'); if (!Safe::make_path($file_path)) { Logger::remember('agents/messages.php: Impossible to create ' . $file_path); return NULL; } if (!Safe::make_path($file_path . '/thumbs')) { Logger::remember('agents/messages.php: Impossible to create ' . $file_path . '/thumbs'); return NULL; } $file_path = $context['path_to_root'] . $file_path . '/'; // save the entity in the file system if (!($file = Safe::fopen($file_path . $file_name, 'wb'))) { Logger::remember('agents/messages.php: Impossible to open ' . $file_path . $file_name); return NULL; } if (fwrite($file, $content) === FALSE) { Logger::remember('agents/messages.php: Impossible to write to ' . $file_path . $file_name); return NULL; } fclose($file); // get image information if (!($image_information = Safe::GetImageSize($file_path . $file_name))) { Safe::unlink($file_path . $file_name); Logger::remember('agents/messages.php: No image information in ' . $file_path . $file_name); return NULL; } // we accept only gif, jpeg and png if ($image_information[2] != 1 && $image_information[2] != 2 && $image_information[2] != 3) { Safe::unlink($file_path . $file_name); Logger::remember('agents/messages.php: Rejected image type for ' . $file_path . $file_name); return NULL; } // build a thumbnail $thumbnail_name = 'thumbs/' . $file_name; // do not stop on error include_once $context['path_to_root'] . 'images/image.php'; if (!Image::shrink($file_path . $file_name, $file_path . $thumbnail_name, FALSE, FALSE)) { Logger::remember('agents/messages.php: No thumbnail has been created for ' . $file_path . $file_name); } // resize the image where applicable if (Image::adjust($file_path . $file_name, FALSE)) { $file_size = Safe::filesize($file_path . $file_name); } // all details $details = array(); // image size if ($image_information = Safe::GetImageSize($file_path . $file_name)) { $details[] = i18n::c('Size') . ': ' . $image_information[0] . ' x ' . $image_information[1]; } // update image description $item = array(); $item['anchor'] = $anchor; $item['image_name'] = $file_name; $item['thumbnail_name'] = $thumbnail_name; $item['image_size'] = $file_size; $item['description'] = ''; if (isset($content_description) && $content_description != $file_name) { $item['description'] .= $content_description; } if (@count($details)) { $item['description'] .= "\n\n" . '<p class="details">' . implode("<br />\n", $details) . "</p>\n"; } $item['edit_date'] = gmstrftime('%Y-%m-%d %H:%M:%S', time()); $item['edit_name'] = $user['nick_name']; $item['edit_id'] = $user['id']; $item['edit_address'] = $user['email']; // create an image record in the database include_once $context['path_to_root'] . 'images/images.php'; if (!($item['id'] = Images::post($item))) { Logger::remember('agents/messages.php: Impossible to save image ' . $item['image_name']); return NULL; } if ($context['debug_messages'] == 'Y') { Logger::remember('agents/messages.php: Messages::submit_image()', $item, 'debug'); } // insert the image in the anchor page $host->touch('image:create', $item['id'], TRUE); return 'image:' . $item['id']; }
/** * define a constant img tag * * mainly called from initialize(), in skins/skin_skeleton.php, and as Skin::initialize() * * @param string constant name, in upper case * @param string file name for this image * @param string to be used if the file does not exists * @param string to be displayed in textual browsers * @param string options to be integrated into the img tag, if any */ public static function define_img($name, $file, $default = '', $alternate = '', $options = '') { global $context; // sanity check if (defined($name)) { return; } // make an absolute path to image, in case of export (freemind, etc.) if ($size = Safe::GetImageSize($context['path_to_root'] . $context['skin'] . '/' . $file)) { define($name, ' <img src="' . $context['url_to_master'] . $context['url_to_root'] . $context['skin'] . '/' . $file . '" ' . $size[3] . ' alt="' . $alternate . '" ' . $options . ' />'); } elseif ($size = Safe::GetImageSize($context['path_to_root'] . 'skins/_reference/' . $file)) { define($name, ' <img src="' . $context['url_to_master'] . $context['url_to_root'] . 'skins/_reference/' . $file . '" ' . $size[3] . ' alt="' . $alternate . '" ' . $options . ' />'); } else { define($name, $default); } }
/** * give a preview of file rendering * used after ajax uploading in forms * * @param string $url string where is the file * @param string $input_name the input that what used to upload */ public static function preview($url, $input_name) { global $context; // get file ext. $ext = pathinfo($url, PATHINFO_EXTENSION); $basename = basename($url); // at least show file's name $preview = $basename; // destroy link, put it where you want $destroy = '<a class="yc-upload-destroy" data-del="' . $input_name . '" href="javascript:void(0);" title="' . i18n::s('Delete') . '" onclick="Yacs.uploadDestroy($(this).data(\'del\'),$(this))" >x</a>' . "\n"; // file is a image if (Files::is_image($url) && ($image_information = Safe::GetImageSize($url))) { // make a temp thumb name $thumb = uniqid() . '.' . $ext; $thumbpath = $context['path_to_root'] . UPLOAD_PATH . $thumb; $thumburl = $context['url_to_root'] . UPLOAD_PATH . $thumb; // make a thumb Image::shrink($url, $thumbpath, true); // build image $preview = Skin::build_image('left', $thumburl, '') . '<span style="line-height:34px"> ' . $basename . '</span>' . "\n" . $destroy; } else { // file is a reconnized audio format switch ($ext) { case 'mp3': case 'm4a': case 'aac': case 'oog': // audio file $audio_url = $context['url_to_root'] . UPLOAD_PATH . $basename; $preview .= $destroy . BR . Skin::build_audioplayer($audio_url); break; default: $icon = Skin::build_image('inline', $context['url_to_master'] . $context['url_to_root'] . Files::get_icon_url($basename), $basename); $preview = $icon . $preview . ' ' . $destroy; break; } } // add separator $preview .= '<hr class="clear" />' . "\n"; // wrap $preview = '<div class="yc-preview">' . $preview . '</div>'; return $preview; }
function explode_callback($name) { global $context; // reject all files put in sub-folders $file_path = Files::get_path($_REQUEST['anchor'], 'images'); if (($path = substr($name, strlen($file_path . '/'))) && strpos($path, '/') !== FALSE) { Safe::unlink($name); } elseif (!($attributes = Safe::GetImageSize($name))) { Safe::unlink($name); } elseif ($attributes[0] > 5000 || $attributes[1] > 5000) { Safe::unlink($name); } }
/** * list articles * * @param resource the SQL result * @return string the rendered text * * @see layouts/layout.php **/ function layout($result) { global $context; // we return some text $text = ''; // empty list if (!SQL::count($result)) { return $text; } // load the SIMILE Timeline javascript library in shared/global.php $context['javascript']['timeline'] = TRUE; // sanity check if (!isset($this->focus)) { $this->focus = 'default'; } // put in cache $cache_id = Cache::hash('articles/layout_articles_as_simile:' . $this->focus) . '.xml'; // save for one minute if (!file_exists($context['path_to_root'] . $cache_id) || filemtime($context['path_to_root'] . $cache_id) + 60 < time()) { // content of the slideshow $content = '<?xml version="1.0" encoding="utf-8"?>' . "\n" . '<data>' . "\n"; // get a default image if (Safe::GetImageSize($context['path_to_root'] . $context['skin'] . '/layouts/map.gif')) { $default_href = $context['url_to_root'] . $context['skin'] . '/layouts/map.gif'; } elseif ($size = Safe::GetImageSize($context['path_to_root'] . 'skins/_reference/layouts/map.gif')) { $default_href = $context['url_to_root'] . 'skins/_reference/layouts/map.gif'; } else { $default_href = NULL; } // process all items in the list while ($item = SQL::fetch($result)) { // get the related overlay $overlay = Overlay::load($item, 'article:' . $item['id']); // get the anchor $anchor = Anchors::get($item['anchor']); // start if ($item['publish_date'] > $item['create_date']) { $first = Skin::build_date($item['publish_date'], 'plain'); } else { $first = Skin::build_date($item['create_date'], 'plain'); } // end $last = Skin::build_date($item['edit_date'], 'plain'); if ($last != $first) { $last = ' end="' . $last . '"'; } else { $last = ''; } // build a title if (is_object($overlay)) { $title = Codes::beautify_title($overlay->get_text('title', $item)); } else { $title = Codes::beautify_title($item['title']); } // the url to view this item $url = str_replace('&', '&', Articles::get_permalink($item)); // this is visual if (isset($item['icon_url']) && $item['icon_url']) { $image = $item['icon_url']; } elseif (isset($item['thumbnail_url']) && $item['thumbnail_url']) { $image = $item['thumbnail_url']; } else { $image = ''; } // fix relative path if ($image && !preg_match('/^(\\/|http:|https:|ftp:)/', $image)) { $image = $context['url_to_root'] . $image; } if ($image) { $image = ' image="' . $image . '"'; } // introduction $introduction = ''; if (is_object($overlay)) { $introduction = $overlay->get_text('introduction', $item); } else { $introduction = $item['introduction']; } // insert overlay data, if any if (is_object($overlay) && ($data = $overlay->get_text('list', $item))) { if ($introduction) { $introduction .= BR; } $introduction .= $data; } // ampersands kill SIMILE Timeline if ($introduction) { $introduction = encode_field(str_replace(array(' ', '&'), ' ', Codes::beautify($introduction))); } // details $details = array(); // info on related comments if ($count = Comments::count_for_anchor('article:' . $item['id'], TRUE)) { $details[] = sprintf(i18n::ns('%d comment', '%d comments', $count), $count); } // info on related files if ($count = Files::count_for_anchor('article:' . $item['id'], TRUE)) { $details[] = sprintf(i18n::ns('%d file', '%d files', $count), $count); } // info on related links if ($count = Links::count_for_anchor('article:' . $item['id'], TRUE)) { $details[] = sprintf(i18n::ns('%d link', '%d links', $count), $count); } // combine in-line details if (count($details)) { if ($introduction) { $introduction .= BR; } $introduction .= '<span class="details">' . trim(implode(', ', $details)) . '</span>'; } // escape the introduction, if any if ($introduction) { $introduction = str_replace(array('<', '&'), array('<', '&'), $introduction); } // add to the list $content .= ' <event start="' . $first . '"' . $last . ' title="' . encode_field(str_replace(array(" ", '"'), ' ', $title)) . '" link="' . $url . '"' . $image . '>' . "\n" . ' ' . $introduction . "\n" . ' </event>' . "\n"; } // finalize slideshow content $content .= '</data>'; // put in cache Safe::file_put_contents($cache_id, $content); } // allow multiple instances static $count; if (!isset($count)) { $count = 1; } else { $count++; } // 1 week ago $now = gmdate('M d Y H:i:s', time() - 7 * 24 * 60 * 60); // load the right file $text = '<div id="articles_as_simile_' . $count . '" style="height: 300px; border: 1px solid #aaa; font-size: 10px"></div>' . "\n"; Page::insert_script('var simile_handle_' . $count . ';' . "\n" . 'function onLoad' . $count . '() {' . "\n" . ' var eventSource = new Timeline.DefaultEventSource();' . "\n" . ' var bandInfos = [' . "\n" . ' Timeline.createBandInfo({' . "\n" . ' eventSource: eventSource,' . "\n" . ' date: "' . $now . '",' . "\n" . ' width: "80%",' . "\n" . ' intervalUnit: Timeline.DateTime.WEEK,' . "\n" . ' intervalPixels: 200' . "\n" . ' }),' . "\n" . ' Timeline.createBandInfo({' . "\n" . ' showEventText: false,' . "\n" . ' trackHeight: 0.5,' . "\n" . ' trackGap: 0.2,' . "\n" . ' eventSource: eventSource,' . "\n" . ' date: "' . $now . '",' . "\n" . ' width: "20%",' . "\n" . ' intervalUnit: Timeline.DateTime.MONTH,' . "\n" . ' intervalPixels: 50' . "\n" . ' })' . "\n" . ' ];' . "\n" . ' bandInfos[1].syncWith = 0;' . "\n" . ' bandInfos[1].highlight = true;' . "\n" . ' bandInfos[1].eventPainter.setLayout(bandInfos[0].eventPainter.getLayout());' . "\n" . ' simile_handle_' . $count . ' = Timeline.create(document.getElementById("articles_as_simile_' . $count . '"), bandInfos);' . "\n" . ' Timeline.loadXML("' . $context['url_to_home'] . $context['url_to_root'] . $cache_id . '", function(xml, url) { eventSource.loadXML(xml, url); });' . "\n" . '}' . "\n" . "\n" . 'var resizeTimerID' . $count . ' = null;' . "\n" . 'function onResize' . $count . '() {' . "\n" . ' if (resizeTimerID' . $count . ' == null) {' . "\n" . ' resizeTimerID' . $count . ' = window.setTimeout(function() {' . "\n" . ' resizeTimerID' . $count . ' = null;' . "\n" . ' simile_handle_' . $count . '.layout();' . "\n" . ' }, 500);' . "\n" . ' }' . "\n" . '}' . "\n" . "\n" . '// observe page major events' . "\n" . '$(document).ready( onLoad' . $count . ');' . "\n" . '$(window).resize(onResize' . $count . ');' . "\n"); // end of processing SQL::free($result); return $text; }
Safe::header('Status: 401 Unauthorized', TRUE, 401); // only available to site associates } elseif (!Surfer::is_associate()) { Safe::header('Status: 401 Unauthorized', TRUE, 401); Logger::error(i18n::s('You are not allowed to perform this operation.')); // provide requested data } else { // loads feeding parameters Safe::load('parameters/feeds.include.php'); // set preamble strings $title = sprintf(i18n::s('Event log at %s'), strip_tags($context['site_name'])); // provide shortcuts for this site $splash = sprintf(i18n::s('Most recent events at %s'), $context['host_name']); // the preamble $text = '<?xml version="1.0" encoding="' . $context['charset'] . '"?>' . "\n" . '<rss version="2.0">' . "\n" . '<channel>' . "\n" . ' <title>' . encode_field($title) . '</title>' . "\n" . ' <link>' . $context['url_to_home'] . $context['url_to_root'] . 'agents/</link>' . "\n" . ' <description><![CDATA[ ' . $splash . ' ]]></description>' . "\n"; if (isset($context['powered_by_image']) && $context['powered_by_image'] && ($size = Safe::GetImageSize($context['path_to_root'] . $context['powered_by_image']))) { $text .= ' <image>' . "\n" . ' <url>' . $context['url_to_home'] . $context['url_to_root'] . $context['powered_by_image'] . '</url>' . "\n" . ' <width>' . $size[0] . '</width>' . "\n" . ' <height>' . $size[1] . '</height>' . "\n" . ' <title>' . encode_field($title) . '</title>' . "\n" . ' <link>' . $context['url_to_home'] . $context['url_to_root'] . 'agents/</link>' . "\n" . ' </image>' . "\n"; } if ($context['preferred_language']) { $text .= ' <language>' . encode_field($context['preferred_language']) . '</language>' . "\n"; } $text .= ' <lastBuildDate>' . gmdate('D, d M Y H:i:s') . ' GMT</lastBuildDate>' . "\n" . ' <generator>yacs</generator>' . "\n" . ' <docs>http://blogs.law.harvard.edu/tech/rss</docs>' . "\n" . ' <ttl>5</ttl>' . "\n"; // list last events $events = Logger::get_tail(50, 'all'); if (is_array($events)) { // the actual list of events foreach ($events as $event) { list($stamp, $surfer, $script, $label, $description) = $event; // formatting patterns $search = array("|\r\n|", "|<br\\s*/>\n+|i", "|\n\n+[ \t]*-\\s+|i", "|\n[ \t]*-\\s+|i", "|\n\n+[ \t]*\\.\\s+|i", "|\n[ \t]*\\.\\s+|i", "|\n\n+[ \t]*\\*\\s+|i", "|\n[ \t]*\\*\\s+|i", "|\n\n+[ \t]*¤\\s+|i", "|\n[ \t]*¤\\s+|i", "|\n\n+[ \t]*\\•\\s+|i", "|\n[ \t]*\\•\\s+|i", "/\n[ \t]*(From|To|cc|bcc|Subject|Date):(\\s*)/i", "|\n[ \t]*>(\\s*)|i", "|\n[ \t]*\\|(\\s*)|i", "#([\n\t ])([a-z]+?)://([^, <>{}\n\r]+)#is", "#^([a-z]+?)://([^, <>{}\n\r]+)#is", "#([\n\t ])www\\.([a-z0-9\\-]+)\\.([a-z0-9\\-.\\~]+)((?:/[^,< \n\r]*)?)#is", "#([\n\t ])([a-z0-9\\-_.]+?)@([^,< \\.\n\r]+\\.[^,< \n\r]+)#is", "|\n\n|i"); $replace = array("\n", BR, BR . BR . "- ", BR . "- ", BR . BR . "- ", BR . "- ", BR . BR . "- ", BR . "- ", BR . BR . "- ", BR . "- ", BR . BR . "• ", BR . "• ", BR . "\$1:\$2", BR . ">\$1", BR . "|\$1", "\$1<a href=\"\$2://\$3\">\$2://\$3</a>", "<a href=\"\$1://\$2\">\$1://\$2</a>", "\$1<a href=\"http://www.\$2.\$3\$4\">http://www.\$2.\$3\$4</a>", "\$1<a href=\"mailto:\$2@\$3\">\$2@\$3</a>", BR . BR);
/** * encode PHP data into RSS * * Accept following values: * - $values['channel']['title'] is a string * - $values['channel']['link'] is a string * - $values['channel']['description'] is a string * - $values['channel']['image'] is a string to a channel image, if any * - $values['items'] is an array of $url => array($time, $title, $author, $section, $image, $introduction, $description, $comments, $trackback, $comment_post, $comment_rss) * * @param mixed the parameter to encode * @return some XML */ public static function encode(&$values) { global $context; // ensure we have a channel title if (isset($values['channel']['title']) && $values['channel']['title']) { $channel_title = $values['channel']['title']; } elseif (isset($context['server_title']) && $context['server_title']) { $channel_title = $context['server_title']; } else { $channel_title = $context['host_name']; } // ensure we have a channel link if (isset($values['channel']['link']) && $values['channel']['link']) { $channel_link = $values['channel']['link']; } else { $channel_link = $context['url_to_home'] . $context['url_to_root']; } // allowed HTML in description $allowed = '<a><b><blockquote><form><hr><input><li><ol><p><strong><u><ul>'; // the preamble $text = '<?xml version="1.0" encoding="' . $context['charset'] . '"?>' . "\n" . '<rss version="2.0" ' . "\n" . ' xmlns:atom="http://www.w3.org/2005/Atom" ' . "\n" . ' xmlns:content="http://purl.org/rss/1.0/modules/content/" ' . "\n" . ' xmlns:dc="http://purl.org/dc/elements/1.1/" ' . "\n" . ' xmlns:georss="http://www.georss.org/georss" ' . "\n" . ' xmlns:icbm="http://postneo.com/icbm" ' . "\n" . ' xmlns:slash="http://purl.org/rss/1.0/modules/slash/" ' . "\n" . ' xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" ' . "\n" . ' xmlns:wfw="http://wellformedweb.org/CommentAPI/" >' . "\n" . "\n" . '<channel>' . "\n" . ' <title>' . rss_codec::clean($channel_title) . '</title>' . "\n" . ' <link>' . encode_link($channel_link) . '</link>' . "\n" . ' <atom:link href="' . encode_link($context['self_url']) . '" rel="self" type="application/rss+xml" />' . "\n" . ' <description>' . rss_codec::clean($values['channel']['description'], $allowed) . '</description>' . "\n"; if (isset($values['channel']['image']) && $values['channel']['image'] && ($size = Safe::GetImageSize($values['channel']['image']))) { $text .= ' <image>' . "\n" . ' <url>' . encode_link($context['url_to_home'] . $context['url_to_root'] . $values['channel']['image']) . '</url>' . "\n" . ' <width>' . $size[0] . '</width>' . "\n" . ' <height>' . $size[1] . '</height>' . "\n" . ' <title>' . rss_codec::clean($channel_title) . '</title>' . "\n" . ' <link>' . encode_link($channel_link) . '</link>' . "\n" . ' </image>' . "\n"; } if (isset($context['preferred_language']) && $context['preferred_language']) { $text .= ' <language>' . $context['preferred_language'] . '</language>' . "\n"; } if (isset($context['site_copyright']) && $context['site_copyright']) { $text .= ' <copyright>' . rss_codec::clean($context['site_copyright']) . '</copyright>' . "\n"; } if (isset($context['site_email']) && $context['site_email']) { $text .= ' <managingEditor>' . rss_codec::clean($context['site_email']) . '</managingEditor>' . "\n"; } if (isset($context['webmaster_address']) && $context['webmaster_address']) { $text .= ' <webMaster>' . rss_codec::clean($context['site_email']) . '</webMaster>' . "\n"; } // encode icbm position if (isset($context['site_position']) && $context['site_position']) { list($latitude, $longitude) = preg_split('/[ ,\\t]+/', $context['site_position']); $text .= ' <icbm:latitude>' . rss_codec::clean($latitude) . '</icbm:latitude>' . "\n"; $text .= ' <icbm:longitude>' . rss_codec::clean($longitude) . '</icbm:longitude>' . "\n"; $text .= ' <georss:point>' . str_replace(',', ' ', $context['site_position']) . '</georss:point>' . "\n"; } $text .= ' <lastBuildDate>' . gmdate('D, d M Y H:i:s') . ' GMT</lastBuildDate>' . "\n" . ' <generator>yacs</generator>' . "\n" . ' <docs>http://blogs.law.harvard.edu/tech/rss</docs>' . "\n"; if (isset($context['time_to_live']) && $context['time_to_live'] > 0) { $text .= ' <ttl>' . $context['time_to_live'] . '</ttl>' . "\n"; } else { $text .= ' <ttl>70</ttl>' . "\n"; } // process rows, if any if (isset($values['items']) && is_array($values['items'])) { // for each item foreach ($values['items'] as $url => $attributes) { $time = $attributes[0]; $title = $attributes[1]; $author = $attributes[2]; $section = $attributes[3]; $image = $attributes[4]; $introduction = $attributes[5]; $description = $attributes[6]; $extensions = $attributes[7]; // output one story $text .= "\n" . ' <item>' . "\n"; if ($title) { $text .= ' <title>' . rss_codec::clean($title) . "</title>\n"; } if ($url) { $text .= ' <link>' . encode_link($url) . "</link>\n" . ' <guid isPermaLink="true">' . encode_link($url) . "</guid>\n"; } if ($introduction) { $text .= ' <description>' . rss_codec::clean($introduction) . "</description>\n"; } elseif ($description) { $text .= ' <description>' . rss_codec::clean($description) . "</description>\n"; } // use unicode entities, and escape & chars that are not part of an entity if ($description) { $text .= ' <content:encoded><![CDATA[ ' . str_replace(']]>', ']]]]><![CDATA[>', $description) . " ]]></content:encoded>\n"; } // do not express mail addresses, but only creator name, which is between () if (preg_match('/\\((.*?)\\)/', $author, $matches)) { $text .= ' <dc:creator>' . rss_codec::clean($matches[1]) . "</dc:creator>\n"; } // do not put any attribute, it would kill FeedReader if ($section) { $text .= ' <category>' . encode_field(strip_tags($section)) . "</category>\n"; } if (intval($time)) { $text .= ' <pubDate>' . gmdate('D, d M Y H:i:s', intval($time)) . " GMT</pubDate>\n"; } // add any extension (eg, slash:comments, wfw:commentRss, trackback:ping) if (isset($extensions)) { if (is_array($extensions)) { foreach ($extensions as $extension) { $text .= ' ' . $extension . "\n"; } } else { $text .= ' ' . $extensions . "\n"; } } $text .= "\t</item>\n"; } } // the postamble $text .= "\n</channel>\n" . '</rss>'; return array(TRUE, $text); }
/** * fully describe a poll in its main page * * This also features a voting form, to let people vote from permalinks. * * @link http://www.slashdot.org/ Slashdot has been copied for the layout, and for the bar images as well * * @param array attributes of the containing page * @param boolean TRUE if votes are enabled, FALSE otherwise * @return some HTML to be inserted into the resulting page */ function get_text_to_view($host = NULL, $enable_votes = TRUE) { global $context; if (!isset($this->attributes['answers'])) { return ''; } if (!is_array($this->attributes['answers'])) { return ''; } // use images either from the skin, or from the polls directory if ($size = Safe::GetImageSize($context['path_to_root'] . $context['skin'] . '/images/poll_left.gif')) { $left_img = '<img src="' . $context['url_to_root'] . $context['skin'] . '/images/poll_left.gif" ' . $size[3] . ' alt="" />'; } elseif ($size = Safe::GetImageSize($context['path_to_root'] . 'overlays/polls/bar_left.gif')) { $left_img = '<img src="' . $context['url_to_root'] . 'overlays/polls/bar_left.gif" ' . $size[3] . ' alt="" />'; } if ($size = Safe::GetImageSize($context['path_to_root'] . $context['skin'] . '/images/poll_main.gif')) { $main_img = '<img src="' . $context['url_to_root'] . $context['skin'] . '/images/poll_main.gif" ' . $size[3] . ' alt="" />'; } elseif ($size = Safe::GetImageSize($context['path_to_root'] . 'overlays/polls/bar_main.gif')) { $main_img = '<img src="' . $context['url_to_root'] . 'overlays/polls/bar_main.gif" ' . $size[3] . ' alt="" />'; } if ($size = Safe::GetImageSize($context['path_to_root'] . $context['skin'] . '/images/poll_right.gif')) { $right_img = '<img src="' . $context['url_to_root'] . $context['skin'] . '/images/poll_right.gif" ' . $size[3] . ' alt="" />'; } elseif ($size = Safe::GetImageSize($context['path_to_root'] . 'overlays/polls/bar_right.gif')) { $right_img = '<img src="' . $context['url_to_root'] . 'overlays/polls/bar_right.gif" ' . $size[3] . ' alt="" />'; } // compute totals $total = 0; $maximum = 0; foreach ($this->attributes['answers'] as $answer) { list($label, $count) = $answer; $total += $count; $maximum = max($maximum, strlen($label)); } // empty form when votes are disallowed $text = '<form method="post" action="' . $context['url_to_root'] . 'overlays/polls/vote.php">'; // layout poll elements $text .= '<dl class="poll">'; // one row per answer $index = 1; foreach ($this->attributes['answers'] as $answer) { list($label, $count) = $answer; $text .= '<dt>'; if ($enable_votes) { $text .= '<input type="radio" name="vote" value="' . $index++ . '" /> '; } $text .= $label . '</dt>' . "\n"; $text .= '<dd>'; if ($total > 0) { $size = (int) ($count * 350 / $total) + 2; } else { $size = 2; } $text .= $left_img . preg_replace('/width=".+?"/i', 'width="' . $size . '"', $main_img) . $right_img . ' ' . number_format($count); if ($total > 0) { $text .= ' / <b>' . (int) ($count * 100 / $total) . '%</b>'; } $text .= '<br style="clear: left;" /></dd>' . "\n"; } $text .= '</dl>' . "\n"; // votes are allowed if ($enable_votes) { $text .= '<p>'; // a button to vote $text .= Skin::build_submit_button(i18n::s('Cast your vote')); // summarize votes if ($total > 1) { $text .= ' ' . sprintf(i18n::s('%d votes up to now'), $total); } $text .= '</p>' . "\n"; } // end of the form $text .= '<input type="hidden" name="id" value="' . $host['id'] . '" />' . '</form>' . "\n"; return $text; }