Ejemplo n.º 1
0
 if (isset($item['language']) && $item['language'] && $item['language'] != 'none') {
     $text .= '		<dc:language>' . $item['language'] . '</dc:language>' . "\n";
 }
 if (is_object($anchor)) {
     $text .= '	<dc:subject>' . encode_field($anchor->get_title()) . '</dc:subject>' . "\n";
 }
 $text .= '	</rdf:Description>' . "\n" . '</rdf:RDF>';
 //
 // transfer to the user agent
 //
 // handle the output correctly
 render_raw('text/xml; charset=' . $context['charset']);
 // suggest a name on download
 if (!headers_sent()) {
     $file_name = Skin::strip($context['page_title']) . '.opml.xml';
     $file_name =& utf8::to_ascii($file_name);
     Safe::header('Content-Disposition: inline; filename="' . str_replace('"', '', $file_name) . '"');
 }
 // enable 30-minute caching (30*60 = 1800), even through https, to help IE6 on download
 http::expire(1800);
 // strong validator
 $etag = '"' . md5($text) . '"';
 // manage web cache
 if (http::validate(NULL, $etag)) {
     return;
 }
 // actual transmission except on a HEAD request
 if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'HEAD') {
     echo $text;
 }
 // the post-processing hook, then exit
Ejemplo n.º 2
0
     $description = Skin::strip(Codes::beautify($item['description']), 50);
 }
 // prepare the response
 $text = '<?xml version="1.0" encoding="' . $context['charset'] . '"?>' . "\n" . '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">' . "\n" . '	<rdf:Description rdf:about="' . $url . '">' . "\n" . '		<dc:title>' . encode_field($item['title']) . '</dc:title>' . "\n" . '		<dc:description>' . encode_field(Skin::strip($description)) . '</dc:description>' . "\n" . '		<dc:date>' . gmdate('Y-m-d') . '</dc:date>' . "\n" . '		<dc:format>text/html</dc:format>' . "\n";
 if (isset($item['language']) && $item['language'] && $item['language'] != 'none') {
     $text .= '		<dc:language>' . $item['language'] . '</dc:language>' . "\n";
 }
 $text .= '	</rdf:Description>' . "\n" . '</rdf:RDF>';
 //
 // transfer to the user agent
 //
 // handle the output correctly
 render_raw('text/xml; charset=' . $context['charset']);
 // suggest a name on download
 if (!headers_sent()) {
     $file_name = utf8::to_ascii(Skin::strip($context['page_title']) . '.opml.xml');
     Safe::header('Content-Disposition: inline; filename="' . str_replace('"', '', $file_name) . '"');
 }
 // enable 30-minute caching (30*60 = 1800), even through https, to help IE6 on download
 http::expire(1800);
 // strong validator
 $etag = '"' . md5($text) . '"';
 // manage web cache
 if (http::validate(NULL, $etag)) {
     return;
 }
 // actual transmission except on a HEAD request
 if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'HEAD') {
     echo $text;
 }
 // the post-processing hook, then exit
Ejemplo n.º 3
0
Archivo: fetch.php Proyecto: rair/yacs
         $text .= $separator;
     }
     $text .= $content;
 }
 // only one script has been asked
 if (count($script) == 1) {
     // compress the page if possible, but no transcoding -- the bare handler
     $context['charset'] = 'ASCII';
     render_raw('text/x-httpd-php');
     // send the response to the caller
     if (!headers_sent()) {
         Safe::header('Content-Description: Reference file from YACS environment');
     }
     // suggest a download
     if (!headers_sent()) {
         $file_name = utf8::to_ascii(basename($script[0]));
         Safe::header('Content-Disposition: attachment; filename="' . str_replace('"', '', $file_name) . '"');
     }
     // several scripts at one
 } else {
     // multi-part separator on the first line
     $text = $separator . $text;
     // compress the page if possible, but no transcoding -- the bare handler
     $context['charset'] = 'ASCII';
     render_raw('text/html');
     // send the response to the caller
     if (!headers_sent()) {
         Safe::header('Content-Description: Reference files from YACS environment');
     }
 }
 // enable 30-minute caching (30*60 = 1800), even through https, to help IE6 on download
Ejemplo n.º 4
0
Archivo: tables.php Proyecto: rair/yacs
 /**
  * build one table
  *
  * Accept following variants:
  * - csv - to provide a downloadable csv page
  * - json - to provide all values in one column
  * - inline - to render tables within articles
  * - simple - the legacy fixed table
  * - sortable - click on column to sort the row
  *
  * @param the id of the table to build
  * @param string the variant to provide - default is 'simple'
  * @return a displayable string
  */
 public static function build($id, $variant = 'simple')
 {
     global $context;
     // split parameters
     $attributes = preg_split("/\\s*,\\s*/", $id, 3);
     $id = $attributes[0];
     // get the table object
     if (!($table = Tables::get($id))) {
         return NULL;
     }
     // do the SELECT statement
     if (!($rows = SQL::query($table['query']))) {
         Logger::error(sprintf(i18n::s('Error in table query %s'), $id) . BR . htmlspecialchars($table['query']) . BR . SQL::error());
         return NULL;
     }
     // build the resulting string
     $text = '';
     switch ($variant) {
         // produce a table readable into MS-Excel
         case 'csv':
             // comma separated values
             $separator = ",";
             // one row for the title
             if ($table['title']) {
                 $label = preg_replace('/\\s/', ' ', $table['title']);
                 // encode to ASCII
                 $label = utf8::to_ascii($label, PRINTABLE_SAFE_ALPHABET);
                 // escape quotes to preserve them in the data
                 $label = str_replace('"', '""', $label);
                 $text .= '"' . $label . '"';
                 $text .= "\n";
             }
             // one row for header fields
             $index = 0;
             while ($field = SQL::fetch_field($rows)) {
                 if ($index++) {
                     $text .= $separator;
                 }
                 $label = trim(preg_replace('/\\s/', ' ', ucfirst($field->name)));
                 // encode
                 $label = utf8::to_ascii($label, PRINTABLE_SAFE_ALPHABET);
                 // escape quotes to preserve them in the data
                 $label = str_replace('"', '""', $label);
                 $text .= '"' . $label . '"';
             }
             $text .= "\n";
             // process every table row
             $row_index = 0;
             while ($row = SQL::fetch($rows)) {
                 // one cell at a time
                 $index = 0;
                 foreach ($row as $name => $value) {
                     // glue cells
                     if ($index++) {
                         $text .= $separator;
                     }
                     // remove HTML tags
                     $value = strip_tags(str_replace('</', ' </', str_replace(BR, ' / ', $value)));
                     // clean spaces
                     $label = trim(preg_replace('/\\s+/', ' ', $value));
                     // encode
                     $label = utf8::to_ascii($label, PRINTABLE_SAFE_ALPHABET);
                     // escape quotes to preserve them in the data
                     $label = str_replace('"', '""', $label);
                     // make a link if this is a reference
                     if ($index == 1 && $table['with_zoom'] == 'Y') {
                         $label = $context['url_to_home'] . $context['url_to_root'] . $label;
                     }
                     // quote data
                     $text .= '"' . $label . '"';
                 }
                 // new line
                 $text .= "\n";
             }
             return $text;
             // a JSON set of values
         // a JSON set of values
         case 'json':
             // get header labels
             $labels = array();
             while ($field = SQL::fetch_field($rows)) {
                 $labels[] = trim(preg_replace('/[^\\w]+/', '', ucfirst($field->name)));
             }
             // all items
             $data = array();
             $data['items'] = array();
             while ($row = SQL::fetch_row($rows)) {
                 // all rows
                 $datum = array();
                 $label = FALSE;
                 $index = 0;
                 $link = NULL;
                 foreach ($row as $name => $value) {
                     $index++;
                     // first column is only a link
                     if ($index == 1 && $table['with_zoom'] == 'Y') {
                         $link = $context['url_to_home'] . $context['url_to_root'] . ltrim($value, '/');
                         continue;
                     }
                     // adjust types to not fool the json encoder
                     if (preg_match('/^(\\+|-){0,1}[0-9]+$/', $value)) {
                         $value = intval($value);
                     } elseif (preg_match('/^(\\+|-){0,1}[0-9\\.,]+$/', $value)) {
                         $value = floatval($value);
                     } elseif (preg_match('/^(true|false)$/i', $value)) {
                         $value = intval($value);
                     }
                     // ensure we have some label for SIMILE Exhibit
                     if (!$label) {
                         $label = $value;
                     }
                     // combine first and second columns
                     if ($index == 2 && $link) {
                         $value = Skin::build_link($link, $value, 'basic');
                     }
                     // save this value
                     $datum[$labels[$name]] = utf8::to_ascii($value, PRINTABLE_SAFE_ALPHABET);
                 }
                 if ($label && !in_array('label', $labels)) {
                     $datum['label'] = utf8::to_ascii($label, PRINTABLE_SAFE_ALPHABET);
                 }
                 // add a tip, if any
                 $data['items'][] = $datum;
             }
             include_once $context['path_to_root'] . 'included/json.php';
             $text .= json_encode2($data);
             return $text;
             // list of facets for SIMILE Exhibit
         // list of facets for SIMILE Exhibit
         case 'json-facets':
             // columns are actual facets
             $facets = array();
             $index = 0;
             while ($field = SQL::fetch_field($rows)) {
                 $index++;
                 // first column is only a link
                 if ($index == 1 && $table['with_zoom'] == 'Y') {
                     continue;
                 }
                 // first column has a link
                 if ($index == 2 && $table['with_zoom'] == 'Y') {
                     continue;
                 }
                 // column is a facet
                 $label = '.' . trim(preg_replace('/[^\\w]+/', '', ucfirst($field->name)));
                 $title = trim(str_replace(',', '', ucfirst($field->name)));
                 $facets[] = '<div ex:role="facet" ex:expression="' . $label . '" ex:facetLabel="' . $title . '"></div>';
                 // only last columns can be faceted
                 if (count($facets) > 7) {
                     array_shift($facets);
                 }
             }
             // reverse facet order
             $facets = array_reverse($facets);
             // job done
             $text = join("\n", $facets);
             return $text;
             // list of columns for SIMILE Exhibit
         // list of columns for SIMILE Exhibit
         case 'json-labels':
             // get header labels
             $labels = array();
             $index = 0;
             while ($field = SQL::fetch_field($rows)) {
                 $index++;
                 // first column is only a link
                 if ($index == 1 && $table['with_zoom'] == 'Y') {
                     continue;
                 }
                 // column id
                 $labels[] = '.' . trim(preg_replace('/[^\\w]+/', '', ucfirst($field->name)));
                 // limit the number of columns put on screen
                 if (count($labels) >= 7) {
                     break;
                 }
             }
             // job done
             $text = join(', ', $labels);
             return $text;
             // titles of columns for SIMILE Exhibit
         // titles of columns for SIMILE Exhibit
         case 'json-titles':
             // get header labels
             $labels = array();
             $index = 0;
             while ($field = SQL::fetch_field($rows)) {
                 $index++;
                 // first column is only a link
                 if ($index == 1 && $table['with_zoom'] == 'Y') {
                     continue;
                 }
                 // column header
                 $labels[] = trim(str_replace(',', '', ucfirst($field->name)));
             }
             $text = join(', ', $labels);
             return $text;
             // produce an HTML table
         // produce an HTML table
         default:
         case 'inline':
         case 'sortable':
             // a table with a grid
             $text .= Skin::table_prefix('grid');
             // the title, with a menu to download the table into Excel
             if ($variant == 'inline') {
                 $item_bar = array();
                 $item_bar += array(Tables::get_url($id) => $table['title']);
                 $item_bar += array(Tables::get_url($id, 'fetch_as_csv') => 'CSV (Excel)');
                 if (Surfer::is_associate()) {
                     $item_bar += array(Tables::get_url($id, 'edit') => i18n::s('edit'));
                 }
                 if (count($item_bar)) {
                     $text .= '<caption>' . Skin::build_list($item_bar, 'menu') . "</caption>\n";
                 }
             }
             // column headers are clickable links
             $cells = array();
             $index = 0;
             while ($field = SQL::fetch_field($rows)) {
                 if ($index++ != 0 || $table['with_zoom'] != 'Y') {
                     $cells[] = ucfirst($field->name);
                 }
             }
             $text .= "\t\t" . Skin::table_row($cells, 'sortable');
             // the table body
             $count = 0;
             $row_index = 0;
             while ($row = SQL::fetch_row($rows)) {
                 $cells = array();
                 $link = '';
                 for ($index = 0; $index < count($row); $index++) {
                     if ($index == 0 && $table['with_zoom'] == 'Y') {
                         $link = $row[$index];
                     } elseif ($link) {
                         $cells[] = Skin::build_link($link, $row[$index]);
                         $link = '';
                     } else {
                         $cells[] = $row[$index];
                     }
                 }
                 $text .= "\t\t" . Skin::table_row($cells, $count++);
             }
             $text .= Skin::table_suffix();
             return $text;
             // adapted to open chart flash
         // adapted to open chart flash
         case 'chart':
             // get title for y series
             $y_title = $y2_title = $y3_title = NULL;
             $y_index = $y2_index = $y3_index = 0;
             $index = 0;
             while ($field = SQL::fetch_field($rows)) {
                 // time will be used for x labels
                 if ($index == 0 && $table['with_zoom'] == 'T') {
                 } elseif ($index == 0 && $table['with_zoom'] == 'Y') {
                 } elseif (!$y_title) {
                     $y_title = '"' . ucfirst($field->name) . '"';
                     $y_index = $index;
                 } elseif (!$y2_title) {
                     $y2_title = '"' . ucfirst($field->name) . '"';
                     $y2_index = $index;
                 } elseif (!$y3_title) {
                     $y3_title = '"' . ucfirst($field->name) . '"';
                     $y3_index = $index;
                     break;
                 }
                 $index++;
             }
             // process every table row
             $x_labels = array();
             $y_values = array();
             $y2_values = array();
             $y3_values = array();
             $y_min = $y_max = NULL;
             $count = 1;
             while ($row = SQL::fetch($rows)) {
                 // one cell at a time
                 $index = 0;
                 foreach ($row as $name => $value) {
                     // clean spaces
                     $label = trim(preg_replace('/\\s/', ' ', $value));
                     // encode in iso8859
                     $label = utf8::to_iso8859($label);
                     // escape quotes to preserve them in the data
                     $label = str_replace('"', '""', $label);
                     // quote data
                     if (preg_match('/-*[^0-9\\,\\.]/', $label)) {
                         $label = '"' . $label . '"';
                     }
                     // x labels
                     if ($index == 0) {
                         if ($table['with_zoom'] == 'T') {
                             array_unshift($x_labels, $label);
                         } else {
                             $x_labels[] = $count++;
                         }
                         // y value
                     } elseif ($index == $y_index) {
                         if ($table['with_zoom'] == 'T') {
                             array_unshift($y_values, $label);
                         } else {
                             $y_values[] = $label;
                         }
                         if (!isset($y_min) || intval($label) < $y_min) {
                             $y_min = intval($label);
                         }
                         if (!isset($y_max) || intval($label) > $y_max) {
                             $y_max = intval($label);
                         }
                         // y2 value
                     } elseif ($index == $y2_index) {
                         if ($table['with_zoom'] == 'T') {
                             array_unshift($y2_values, $label);
                         } else {
                             $y_values[] = $label;
                         }
                         if (!isset($y_min) || intval($label) < $y_min) {
                             $y_min = intval($label);
                         }
                         if (!isset($y_max) || intval($label) > $y_max) {
                             $y_max = intval($label);
                         }
                         // y3 value
                     } elseif ($index == $y3_index) {
                         if ($table['with_zoom'] == 'T') {
                             array_unshift($y3_values, $label);
                         } else {
                             $y_values[] = $label;
                         }
                         if (!isset($y_min) || intval($label) < $y_min) {
                             $y_min = intval($label);
                         }
                         if (!isset($y_max) || intval($label) > $y_max) {
                             $y_max = intval($label);
                         }
                         // we won't process the rest
                         break;
                     }
                     // next column
                     $index++;
                 }
             }
             // y minimum
             if ($y_min > 0) {
                 $y_min = 0;
             }
             // y maximum
             $y_max = strval($y_max);
             if (strlen($y_max) == 1) {
                 $y_max = 10;
             } elseif (strlen($y_max) == 2) {
                 $y_max = (intval(substr($y_max, 0, 1)) + 1) * 10;
             } elseif (strlen($y_max) == 3) {
                 $y_max = (intval(substr($y_max, 0, 2)) + 1) * 10;
             } else {
                 $y_max = strval(intval(substr($y_max, 0, 2)) + 1) . substr('0000000000000000000000000000000000000000000000000000', 0, strlen($y_max) - 2);
             }
             // data series
             $elements = array();
             if (count($y_values)) {
                 $elements[] = '{ "type":"bar_glass", "colour":"#BF3B69", "values": [ ' . join(',', $y_values) . ' ], "text": ' . $y_title . ', "font-size": 12 }';
             }
             if (count($y2_values)) {
                 $elements[] = '{ "type": "line", "width": 1, "colour": "#5E4725", "values": [ ' . join(',', $y2_values) . ' ], "text": ' . $y2_title . ', "font-size": 12 }';
             }
             if (count($y3_values)) {
                 $elements[] = '{ "type":"bar_glass", "colour":"#5E0722", "values": [ ' . join(',', $y3_values) . ' ], "text": ' . $y3_title . ', "font-size": 12 }';
             }
             // the full setup
             $text = '{ "elements": [ ' . join(',', $elements) . ' ], "x_axis": { "offset": false, "steps": 1, "labels": { "steps": 3, "rotate": 310, "labels": [ ' . join(',', $x_labels) . ' ] } }, "y_axis": { "min": ' . $y_min . ', "max": ' . $y_max . ' } }';
             return $text;
             // first number
         // first number
         case 'column':
             // comma separated values
             $separator = ",";
             // process every table row
             while ($row = SQL::fetch($rows)) {
                 // not always the first column
                 $index = 0;
                 foreach ($row as $name => $value) {
                     $index++;
                     // skip dates and links
                     if ($index == 1 && $table['with_zoom'] != 'N') {
                         continue;
                     }
                     // glue cells
                     if ($text) {
                         $text .= $separator;
                     }
                     // clean spaces
                     $label = trim(preg_replace('/\\s/', ' ', $value));
                     // encode in iso8859
                     $label = utf8::to_iso8859($label);
                     // escape quotes to preserve them in the data
                     $label = str_replace('"', '""', $label);
                     // quote data
                     if (preg_match('/[^a-zA-Z0-9\\,\\.\\-_]/', $label)) {
                         $text .= '"' . $label . '"';
                     } else {
                         $text .= $label;
                     }
                     // only first column
                     break;
                 }
             }
             return $text;
             // produce a raw table
         // produce a raw table
         case 'raw':
             // comma separated values
             $separator = ",";
             // process every table row
             while ($row = SQL::fetch($rows)) {
                 // one cell at a time
                 $index = 0;
                 foreach ($row as $name => $value) {
                     // glue cells
                     if ($index++) {
                         $text .= $separator;
                     }
                     // clean spaces
                     $label = trim(preg_replace('/\\s/', ' ', $value));
                     // encode in iso8859
                     $label = utf8::to_iso8859($label);
                     // escape quotes to preserve them in the data
                     $label = str_replace('"', '""', $label);
                     // make a link if this is a reference
                     if ($index == 0 && $table['with_zoom'] == 'Y') {
                         $label = $context['url_to_home'] . $context['url_to_root'] . $label;
                     }
                     // quote data
                     if (preg_match('/[^a-zA-Z0-9\\-_]/', $label)) {
                         $text .= '"' . $label . '"';
                     } else {
                         $text .= $label;
                     }
                 }
                 // new line
                 $text .= "\n";
             }
             return $text;
             // a simple table
         // a simple table
         case 'simple':
             $text .= Skin::table_prefix('table');
             // columns headers
             $index = 0;
             while ($field = SQL::fetch_field($rows)) {
                 $cells[] = ucfirst($field->name);
             }
             $text .= Skin::table_row($cells, 'header');
             // other rows
             while ($row = SQL::fetch_row($rows)) {
                 $text .= Skin::table_row($row, $count++);
             }
             $text .= Skin::table_suffix();
             return $text;
             // xml table
         // xml table
         case 'xml':
             $text = '';
             while ($row = SQL::fetch($rows)) {
                 $text .= '	<item>' . "\n";
                 foreach ($row as $name => $value) {
                     $type = preg_replace('/[^a-z0-9]+/i', '_', $name);
                     if (preg_match('/^[^a-z]/i', $type)) {
                         $type = '_' . $type;
                     }
                     $text .= '		<' . $type . '>' . preg_replace('/&(?!(amp|#\\d+);)/i', '&amp;', utf8::transcode(str_replace(array('left=', 'right='), '', $value))) . '</' . $type . '>' . "\n";
                 }
                 $text .= '	</item>' . "\n\n";
             }
             return '<?xml version="1.0" encoding="' . $context['charset'] . '"?>' . "\n" . '<items>' . "\n" . $text . '</items>' . "\n";
     }
 }
Ejemplo n.º 5
0
     // make a text
     include_once '../services/codec.php';
     include_once '../services/rss_codec.php';
     $result = rss_Codec::encode($values);
     $text = @$result[1];
     // save in cache for the next request
     Cache::put($cache_id, $text, 'articles');
 }
 //
 // transfer to the user agent
 //
 // handle the output correctly
 render_raw('text/xml; charset=' . $context['charset']);
 // suggest a name on download
 if (!headers_sent()) {
     $file_name = utf8::to_ascii($context['site_name'] . '.category.' . $item['id'] . '.rss.xml');
     Safe::header('Content-Disposition: inline; filename="' . str_replace('"', '', $file_name) . '"');
 }
 // enable 30-minute caching (30*60 = 1800), even through https, to help IE6 on download
 http::expire(1800);
 // strong validator
 $etag = '"' . md5($text) . '"';
 // manage web cache
 if (http::validate(NULL, $etag)) {
     return;
 }
 // actual transmission except on a HEAD request
 if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'HEAD') {
     echo $text;
 }
 // the post-processing hook, then exit
Ejemplo n.º 6
0
Archivo: fetch.php Proyecto: rair/yacs
     }
     // genre
     if ($value = implode(', ', @$data['comments_html']['genre'])) {
         Safe::header("icy-genre: " . utf8::to_iso8859(utf8::transcode($value)));
     }
     // audio bitrate
     if ($value = @$data['audio']['bitrate']) {
         Safe::header("icy-br: " . substr($value, 0, -3));
     }
     // this server
     Safe::header("icy-url: " . $context['url_to_home'] . $context['url_to_root']);
 }
 // serve the right type
 Safe::header('Content-Type: ' . Files::get_mime_type($item['file_name']));
 // suggest a name for the saved file
 $file_name = utf8::to_ascii($item['file_name']);
 Safe::header('Content-Disposition: attachment; filename="' . str_replace('"', '', $file_name) . '"');
 // we accepted (limited) range requests
 Safe::header('Accept-Ranges: bytes');
 // provide only a slice of the file
 if (isset($_SERVER['HTTP_RANGE']) && !strncmp('bytes=', $_SERVER['HTTP_RANGE'], 6)) {
     // maybe several ranges
     $range = substr($_SERVER['HTTP_RANGE'], 6);
     // process only the first range, if several are specified
     if ($position = strpos($range, ',')) {
         $range = substr($range, 0, $position);
     }
     // beginning and end of the range
     list($offset, $end) = explode('-', $range);
     $offset = intval($offset);
     if (!$end) {
Ejemplo n.º 7
0
$scope = '';
if ($id) {
    $scope = '?id=' . urlencode($id);
}
// available blogging api
$text .= '	<apis>' . "\n" . '		<api name="MovableType" preferred="true" apiLink="' . $context['url_to_home'] . $context['url_to_root'] . 'services/blog.php' . $scope . '" blogID="' . encode_field($id) . '" />' . "\n" . '		<api name="MetaWeblog" preferred="false" apiLink="' . $context['url_to_home'] . $context['url_to_root'] . 'services/blog.php' . $scope . '" blogID="' . encode_field($id) . '" />' . "\n" . '		<api name="Blogger" preferred="false" apiLink="' . $context['url_to_home'] . $context['url_to_root'] . 'services/blog.php' . $scope . '" blogID="' . encode_field($id) . '" />' . "\n" . '	</apis>' . "\n";
// the postamble
$text .= '</service>' . "\n" . '</rsd>' . "\n";
//
// transfer to the user agent
//
// handle the output correctly
render_raw('application/rsd+xml; charset=' . $context['charset']);
// suggest a name on download
if (!headers_sent()) {
    $file_name = utf8::to_ascii($context['site_name'] . '.rsd.xml');
    Safe::header('Content-Disposition: inline; filename="' . str_replace('"', '', $file_name) . '"');
}
// enable 30-minute caching (30*60 = 1800), even through https, to help IE6 on download
http::expire(1800);
// strong validator
$etag = '"' . md5($text) . '"';
// manage web cache
if (http::validate(NULL, $etag)) {
    return;
}
// actual transmission except on a HEAD request
if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'HEAD') {
    echo $text;
}
// the post-processing hook
Ejemplo n.º 8
0
    // an error occured
} elseif (count($context['error'])) {
} else {
    // put in the calendar, no more
    $method = 'PUBLISH';
    // get the full text of the event invitation
    $text = $overlay->get_ics($method);
    // no encoding, no compression and no yacs handler...
    if (!headers_sent()) {
        Safe::header('Content-Type: text/calendar; method="' . $method . '"; charset="UTF-8"');
        Safe::header('Content-Transfer-Encoding: binary');
        Safe::header('Content-Length: ' . strlen($text));
    }
    // suggest a download
    if (!headers_sent()) {
        $file_name = utf8::to_ascii(Skin::strip($anchor->get_title(false)) . '.ics');
        Safe::header('Content-Disposition: attachment; filename="' . str_replace('"', '', $file_name) . '"');
    }
    // enable 30-minute caching (30*60 = 1800), even through https, to help IE6 on download
    http::expire(1800);
    // strong validator
    $etag = '"' . md5($text) . '"';
    // manage web cache
    if (http::validate(NULL, $etag)) {
        return;
    }
    // actual transmission except on a HEAD request
    if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'HEAD') {
        echo $text;
    }
    // the post-processing hook, then exit
Ejemplo n.º 9
0
Archivo: view.php Proyecto: rair/yacs
     $rows[] = array(i18n::s('Source'), $item['source']);
 }
 // keywords
 if ($item['keywords']) {
     $rows[] = array(i18n::s('Keywords'), $item['keywords']);
 }
 // display these details
 $context['text'] .= Skin::table(NULL, $rows);
 // insert anchor prefix
 if (is_object($anchor)) {
     $context['text'] .= $anchor->get_prefix();
 }
 // if we have a local file
 if (!isset($item['file_href']) || !$item['file_href']) {
     // where the file is
     $path = $context['path_to_root'] . Files::get_path($item['anchor']) . '/' . rawurlencode(utf8::to_ascii($item['file_name']));
     //load some file parser if one is available
     $analyzer = NULL;
     if (is_readable($context['path_to_root'] . 'included/getid3/getid3.php')) {
         include_once $context['path_to_root'] . 'included/getid3/getid3.php';
         $analyzer = new getid3();
     }
     // parse file content, and streamline information
     $data = array();
     if (is_object($analyzer) && Files::is_stream($item['file_name'])) {
         $data = $analyzer->analyze($path);
         getid3_lib::CopyTagsToComments($data);
     }
     // details
     $rows = array();
     // artist
Ejemplo n.º 10
0
Archivo: edit.php Proyecto: rair/yacs
     Versions::save($item, 'file:' . $item['id']);
 }
 // assume this is just an update of the record
 $action = 'file:update';
 // true when several files are uploaded at once
 $exploded = FALSE;
 // this record is a reference to an external file -- do not take upload into account, if any
 if (isset($_REQUEST['file_href']) && $_REQUEST['file_href']) {
     // protect from hackers -- encode_link() would introduce &amp;
     $_REQUEST['file_href'] = trim(preg_replace(FORBIDDEN_IN_URLS, '_', $_REQUEST['file_href']), ' _');
     // ensure we have a title
     if (!$_REQUEST['title']) {
         $_REQUEST['title'] = str_replace('%20', ' ', basename($_REQUEST['file_href']));
     }
     // ensure we have a file name
     $_REQUEST['file_name'] = utf8::to_ascii(str_replace('%20', ' ', basename($_REQUEST['file_href'])));
     // change has been documented
     if (!isset($_REQUEST['version']) || !$_REQUEST['version']) {
         $_REQUEST['version'] = '';
     } else {
         $_REQUEST['version'] = ' - ' . $_REQUEST['version'];
     }
     // always remember file uploads, for traceability
     $_REQUEST['version'] = $_REQUEST['file_name'] . ' (' . Skin::build_number($_REQUEST['file_size'], i18n::s('bytes')) . ')' . $_REQUEST['version'];
     // add to file history
     $_REQUEST['description'] = Files::add_to_history($item, $_REQUEST['version']);
     // when the file has been overlaid
     if (is_object($overlay)) {
         // allow for change detection
         $overlay->snapshot();
         // update the overlay from form content
Ejemplo n.º 11
0
 foreach ($items as $id => $attributes) {
     // read file content
     if ($content = Safe::file_get_contents($file_path . '/' . $attributes['file_name'], 'rb')) {
         // add the binary data
         $zipfile->deflate($attributes['file_name'], Safe::filemtime($file_path . '/' . $attributes['file_name']), $content);
     }
 }
 //
 // transfer to the user agent
 //
 // send the archive content
 if ($archive = $zipfile->get()) {
     // suggest a download
     Safe::header('Content-Type: application/octet-stream');
     // suggest a name for the saved file
     $file_name = utf8::to_ascii($item['title']) . '.zip';
     Safe::header('Content-Disposition: attachment; filename="' . str_replace('"', '', $file_name) . '"');
     // file size
     Safe::header('Content-Length: ' . strlen($archive));
     // already encoded
     Safe::header('Content-Transfer-Encoding: binary');
     // enable 30-minute caching (30*60 = 1800), even through https, to help IE on download
     http::expire(1800);
     // strong validator
     $etag = '"' . md5($archive) . '"';
     // manage web cache
     if (http::validate(NULL, $etag)) {
         return;
     }
     // actual transmission except on a HEAD request
     if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'HEAD') {
Ejemplo n.º 12
0
    Safe::header('Status: 401 Unauthorized', TRUE, 401);
    Logger::error(i18n::s('You are not allowed to perform this operation.'));
    // display the table in CSV
} else {
    // force the character set
    $context['charset'] = 'iso-8859-15';
    // render actual table content
    $text = strip_tags(Tables::build($item['id'], 'raw'));
    //
    // transfer to the user agent
    //
    // handle the output correctly
    render_raw('text/csv; charset=' . $context['charset']);
    // suggest a download
    if (!headers_sent()) {
        $file_name = utf8::to_ascii(Skin::strip($item['title']) . '.csv');
        Safe::header('Content-Disposition: attachment; filename="' . str_replace('"', '', $file_name) . '"');
    }
    // enable 30-minute caching (30*60 = 1800), even through https, to help IE6 on download
    http::expire(1800);
    // strong validator
    $etag = '"' . md5($text) . '"';
    // manage web cache
    if (http::validate(NULL, $etag)) {
        return;
    }
    // actual transmission except on a HEAD request
    if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'HEAD') {
        echo $text;
    }
    // the post-processing hook, then exit
Ejemplo n.º 13
0
Archivo: files.php Proyecto: rair/yacs
 function explode_callback($name)
 {
     global $context;
     // reject all files put in sub-folders
     if (($path = substr($name, strlen($context['uploaded_path'] . '/'))) && strpos($path, '/') !== FALSE) {
         Safe::unlink($name);
     } elseif (!Files::is_authorized($name)) {
         Safe::unlink($name);
     } else {
         // make it easy to download
         $ascii = utf8::to_ascii(basename($name));
         Safe::rename($name, $context['uploaded_path'] . '/' . $ascii);
         // remember this name
         $context['uploaded_files'][] = $ascii;
     }
 }
Ejemplo n.º 14
0
 /**
  * embed an interactive object
  *
  * The id designates the target file.
  * It can also include width and height of the target canvas, as in: '12, 100%, 250px'
  *
  * @param string id of the target file
  * @return string the rendered string
  **/
 public static function render_embed($id)
 {
     global $context;
     // split parameters
     $attributes = preg_split("/\\s*,\\s*/", $id, 4);
     $id = $attributes[0];
     // get the file
     if (!($item = Files::get($id))) {
         $output = '[embed=' . $id . ']';
         return $output;
     }
     // stream in a separate page
     if (isset($attributes[1]) && preg_match('/window/i', $attributes[1])) {
         if (!isset($attributes[2])) {
             $attributes[2] = i18n::s('Play in a separate window');
         }
         $output = '<a href="' . $context['url_to_home'] . $context['url_to_root'] . Files::get_url($item['id'], 'stream', $item['file_name']) . '" onclick="window.open(this.href); return false;" class="button"><span>' . $attributes[2] . '</span></a>';
         return $output;
     }
     // file extension
     $extension = strtolower(substr($item['file_name'], -3));
     // set a default size
     if (!isset($attributes[1])) {
         if (!strcmp($extension, 'gan')) {
             $attributes[1] = '98%';
         } elseif (!strcmp($extension, 'mm') && isset($context['skins_freemind_canvas_width'])) {
             $attributes[1] = $context['skins_freemind_canvas_width'];
         } else {
             $attributes[1] = 480;
         }
     }
     if (!isset($attributes[2])) {
         if (!strcmp($extension, 'gan')) {
             $attributes[2] = '300px';
         } elseif (!strcmp($extension, 'mm') && isset($context['skins_freemind_canvas_height'])) {
             $attributes[2] = $context['skins_freemind_canvas_height'];
         } else {
             $attributes[2] = 360;
         }
     }
     // object attributes
     $width = $attributes[1];
     $height = $attributes[2];
     $flashvars = '';
     if (isset($attributes[3])) {
         $flashvars = $attributes[3];
     }
     // rendering depends on file extension
     switch ($extension) {
         // stream a video
         case '3gp':
         case 'flv':
         case 'm4v':
         case 'mov':
         case 'mp4':
             // a flash player to stream a flash video
             $flvplayer_url = $context['url_to_home'] . $context['url_to_root'] . 'included/browser/player_flv_maxi.swf';
             // file is elsewhere
             if (isset($item['file_href']) && $item['file_href']) {
                 $url = $item['file_href'];
             } else {
                 $url = $context['url_to_home'] . $context['url_to_root'] . Files::get_url($item['id'], 'fetch', $item['file_name']);
             }
             // pass parameters to the player
             if ($flashvars) {
                 $flashvars = str_replace('autostart=true', 'autoplay=1', $flashvars) . '&';
             }
             $flashvars .= 'width=' . $width . '&height=' . $height;
             // if there is a static image for this video, use it
             if (isset($item['icon_url']) && $item['icon_url']) {
                 $flashvars .= '&startimage=' . urlencode($item['icon_url']);
             }
             // if there is a subtitle file for this video, use it
             if (isset($item['file_name']) && ($srt = 'files/' . str_replace(':', '/', $item['anchor']) . '/' . str_replace('.' . $extension, '.srt', $item['file_name'])) && file_exists($context['path_to_root'] . $srt)) {
                 $flashvars .= '&srt=1&srturl=' . urlencode($context['url_to_home'] . $context['url_to_root'] . $srt);
             }
             // if there is a logo file in the skin, use it
             Skin::define_img_href('FLV_IMG_HREF', 'codes/flvplayer_logo.png', '');
             if (FLV_IMG_HREF) {
                 $flashvars .= '&top1=' . urlencode(FLV_IMG_HREF . '|10|10');
             }
             // rely on Flash
             if (Surfer::has_flash()) {
                 // the full object is built in Javascript --see parameters at http://flv-player.net/players/maxi/documentation/
                 $output = '<div id="flv_' . $item['id'] . '" class="no_print">Flash plugin or Javascript are turned off. Activate both and reload to view the object</div>' . "\n";
                 Page::insert_script('var flashvars = { flv:"' . $url . '", ' . str_replace(array('&', '='), array('", ', ':"'), $flashvars) . '", autoload:0, margin:1, showiconplay:1, playeralpha:50, iconplaybgalpha:30, showfullscreen:1, showloading:"always", ondoubleclick:"fullscreen" }' . "\n" . 'var params = { allowfullscreen: "true", allowscriptaccess: "always" }' . "\n" . 'var attributes = { id: "file_' . $item['id'] . '", name: "file_' . $item['id'] . '"}' . "\n" . 'swfobject.embedSWF("' . $flvplayer_url . '", "flv_' . $item['id'] . '", "' . $width . '", "' . $height . '", "9", "' . $context['url_to_home'] . $context['url_to_root'] . 'included/browser/expressinstall.swf", flashvars, params);' . "\n");
                 // native support
             } else {
                 // <video> is HTML5, <object> is legacy
                 $output = '<video width="' . $width . '" height="' . $height . '" autoplay="" controls="" src="' . $url . '" >' . "\n" . '	<object width="' . $width . '" height="' . $height . '" data="' . $url . '" type="' . Files::get_mime_type($item['file_name']) . '">' . "\n" . '		<param value="' . $url . '" name="movie" />' . "\n" . '		<param value="true" name="allowFullScreen" />' . "\n" . '		<param value="always" name="allowscriptaccess" />' . "\n" . '		<a href="' . $url . '">No video playback capabilities, please download the file</a>' . "\n" . '	</object>' . "\n" . '</video>' . "\n";
             }
             // job done
             return $output;
             // a ganttproject timeline
         // a ganttproject timeline
         case 'gan':
             // where the file is
             $path = Files::get_path($item['anchor']) . '/' . rawurlencode($item['file_name']);
             // we actually use a transformed version of the file
             $cache_id = Cache::hash($path) . '.xml';
             // apply the transformation
             if (!file_exists($context['path_to_root'] . $cache_id) || filemtime($context['path_to_root'] . $cache_id) < filemtime($context['path_to_root'] . $path) || !($text = Safe::file_get_contents($context['path_to_root'] . $cache_id))) {
                 // transform from GanttProject to SIMILE Timeline
                 $text = Files::transform_gan_to_simile($path);
                 // put in cache
                 Safe::file_put_contents($cache_id, $text);
             }
             // load the SIMILE Timeline javascript library in shared/global.php
             $context['javascript']['timeline'] = TRUE;
             // cache would kill the loading of the library
             cache::poison();
             // 1 week ago
             $now = gmdate('M d Y H:i:s', time() - 7 * 24 * 60 * 60);
             // load the right file
             $output = '<div id="gantt" style="height: ' . $height . '; width: ' . $width . '; border: 1px solid #aaa; font-family: Trebuchet MS, Helvetica, Arial, sans serif; font-size: 8pt"></div>' . "\n";
             Page::insert_script('var simile_handle;' . "\n" . 'function onLoad() {' . "\n" . '  var eventSource = new Timeline.DefaultEventSource();' . "\n" . '	var theme = Timeline.ClassicTheme.create();' . "\n" . '            theme.event.bubble.width = 350;' . "\n" . '            theme.event.bubble.height = 300;' . "\n" . '  var bandInfos = [' . "\n" . '    Timeline.createBandInfo({' . "\n" . '        eventSource:    eventSource,' . "\n" . '        date:           "' . $now . '",' . "\n" . '        width:          "80%",' . "\n" . '        intervalUnit:   Timeline.DateTime.WEEK,' . "\n" . '        intervalPixels: 200,' . "\n" . '		  theme:          theme,' . "\n" . '        layout:         "original"  // original, overview, detailed' . "\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 = Timeline.create(document.getElementById("gantt"), bandInfos, Timeline.HORIZONTAL);' . "\n" . '	simile_handle.showLoadingMessage();' . "\n" . '  Timeline.loadXML("' . $context['url_to_home'] . $context['url_to_root'] . $cache_id . '", function(xml, url) { eventSource.loadXML(xml, url); });' . "\n" . '	simile_handle.hideLoadingMessage();' . "\n" . '}' . "\n" . "\n" . 'var resizeTimerID = null;' . "\n" . 'function onResize() {' . "\n" . '    if (resizeTimerID == null) {' . "\n" . '        resizeTimerID = window.setTimeout(function() {' . "\n" . '            resizeTimerID = null;' . "\n" . '            simile_handle.layout();' . "\n" . '        }, 500);' . "\n" . '    }' . "\n" . '}' . "\n" . "\n" . '// observe page major events' . "\n" . '$(document).ready( onLoad);' . "\n" . '$(window).resize(onResize);' . "\n");
             // job done
             return $output;
             // a Freemind map
         // a Freemind map
         case 'mm':
             // if we have an external reference, use it
             if (isset($item['file_href']) && $item['file_href']) {
                 $target_href = $item['file_href'];
                 // else redirect to ourself
             } else {
                 // ensure a valid file name
                 $file_name = utf8::to_ascii($item['file_name']);
                 // where the file is
                 $path = Files::get_path($item['anchor']) . '/' . rawurlencode($item['file_name']);
                 // map the file on the regular web space
                 $url_prefix = $context['url_to_home'] . $context['url_to_root'];
                 // redirect to the actual file
                 $target_href = $url_prefix . $path;
             }
             // allow several viewers to co-exist in the same page
             static $freemind_viewer_index;
             if (!isset($freemind_viewer_index)) {
                 $freemind_viewer_index = 1;
             } else {
                 $freemind_viewer_index++;
             }
             // load flash player
             $url = $context['url_to_home'] . $context['url_to_root'] . 'included/browser/visorFreemind.swf';
             // variables
             $flashvars = 'initLoadFile=' . $target_href . '&openUrl=_self';
             $output = '<div id="freemind_viewer_' . $freemind_viewer_index . '">Flash plugin or Javascript are turned off. Activate both and reload to view the object</div>' . "\n";
             Page::insert_script('var params = {};' . "\n" . 'params.base = "' . dirname($url) . '/";' . "\n" . 'params.quality = "high";' . "\n" . 'params.wmode = "transparent";' . "\n" . 'params.menu = "false";' . "\n" . 'params.flashvars = "' . $flashvars . '";' . "\n" . 'swfobject.embedSWF("' . $url . '", "freemind_viewer_' . $freemind_viewer_index . '", "' . $width . '", "' . $height . '", "6", "' . $context['url_to_home'] . $context['url_to_root'] . 'included/browser/expressinstall.swf", false, params);' . "\n");
             // offer to download a copy of the map
             $menu = array($target_href => i18n::s('Browse this map with Freemind'));
             // display menu commands below the viewer
             $output .= Skin::build_list($menu, 'menu_bar');
             // job done
             return $output;
             // native flash
         // native flash
         case 'swf':
             // where to get the file
             if (isset($item['file_href']) && $item['file_href']) {
                 $url = $item['file_href'];
             } else {
                 $url = $context['url_to_home'] . $context['url_to_root'] . 'files/' . str_replace(':', '/', $item['anchor']) . '/' . rawurlencode($item['file_name']);
             }
             $output = '<div id="swf_' . $item['id'] . '" class="no_print">Flash plugin or Javascript are turned off. Activate both and reload to view the object</div>' . "\n";
             Page::insert_script('var params = {};' . "\n" . 'params.base = "' . dirname($url) . '/";' . "\n" . 'params.quality = "high";' . "\n" . 'params.wmode = "transparent";' . "\n" . 'params.allowfullscreen = "true";' . "\n" . 'params.allowscriptaccess = "always";' . "\n" . 'params.flashvars = "' . $flashvars . '";' . "\n" . 'swfobject.embedSWF("' . $url . '", "swf_' . $item['id'] . '", "' . $width . '", "' . $height . '", "6", "' . $context['url_to_home'] . $context['url_to_root'] . 'included/browser/expressinstall.swf", false, params);' . "\n");
             return $output;
             // link to file page
         // link to file page
         default:
             // link label
             $text = Skin::strip($item['title'] ? $item['title'] : str_replace('_', ' ', $item['file_name']));
             // make a link to the target page
             $url = Files::get_permalink($item);
             // return a complete anchor
             $output =& Skin::build_link($url, $text);
             return $output;
     }
 }
Ejemplo n.º 15
0
Archivo: stream.php Proyecto: rair/yacs
 if (!$fetched) {
     // increment the count of downloads
     if (!Surfer::is_crawler()) {
         Files::increment_hits($item['id']);
     }
     // record surfer activity
     Activities::post('file:' . $item['id'], 'fetch');
 }
 // no encoding, no compression and no yacs handler...
 if (!headers_sent()) {
     Safe::header('Content-Type: ' . $mime);
     Safe::header('Content-Length: ' . strlen($text));
 }
 // suggest a download
 if (!headers_sent()) {
     $file_name = utf8::to_ascii($item['file_name'] . $type);
     Safe::header('Content-Disposition: inline; filename="' . str_replace('"', '', $file_name) . '"');
 }
 // enable 30-minute caching (30*60 = 1800), even through https, to help IE6 on download
 http::expire(1800);
 // strong validator
 $etag = '"' . md5($text) . '"';
 // manage web cache
 if (http::validate(NULL, $etag)) {
     return;
 }
 // actual transmission except on a HEAD request
 if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'HEAD') {
     echo $text;
 }
 // the post-processing hook, then exit
Ejemplo n.º 16
0
Archivo: feed.php Proyecto: rair/yacs
     include_once '../services/codec.php';
     include_once '../services/rss_codec.php';
     $result = rss_Codec::encode($values);
     $status = @$result[0];
     $text = @$result[1];
     // save in cache for the next request
     Cache::put($cache_id, $text, 'articles');
 }
 //
 // transfer to the user agent
 //
 // handle the output correctly
 render_raw('text/xml; charset=' . $context['charset']);
 // suggest a name on download
 if (!headers_sent()) {
     $file_name = utf8::to_ascii($context['site_name'] . '.section.' . $item['id'] . '.rss.xml');
     Safe::header('Content-Disposition: inline; filename="' . str_replace('"', '', $file_name) . '"');
 }
 // enable 30-minute caching (30*60 = 1800), even through https, to help IE6 on download
 http::expire(1800);
 // strong validator
 $etag = '"' . md5($text) . '"';
 // manage web cache
 if (http::validate(NULL, $etag)) {
     return;
 }
 // actual transmission except on a HEAD request
 if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'HEAD') {
     echo $text;
 }
 // the post-processing hook, then exit
Ejemplo n.º 17
0
Archivo: mailer.php Proyecto: rair/yacs
 /**
  * build and transmit a complex e-mail messages
  *
  * This function allows for individual posts, textual and HTML messages, and attached files.
  *
  * For this to work, e-mail service has to be explicitly activated in the
  * main configuration panel, at [script]control/configure.php[/script].
  *
  * You can refer to local images in HTML parts, and the function will automatically attach these
  * to the message, else mail clients would not display them correctly.
  *
  * The message actually sent has a complex structure, with several parts assembled together,
  * as [explained at altepeter.net|http://altepeter.net/tech/articles/html-emails].
  *
  * @link http://altepeter.net/tech/articles/html-emails
  *
  * Several recipients can be provided as a list of addresses separated by
  * commas. For bulk posts, recipients can be transmitted as an array of strings.
  * In all cases, this function sends one separate message per recipient.
  *
  * This function will ensure that only one mail message is send to a recipient,
  * by maintaining an internal list of addresses that have been processed.
  * Therefore, if this function is called several times, with some repeated recipients,
  * those will receive only the first message, and other messages to the same address
  * will be dropped.
  *
  * Bracketed recipients, such as ##Foo Bar <*****@*****.**>##, are handled properly,
  * meaning ##foo@bar.com## is transmitted to the mailing function, while
  * the string ##To: Foo Bar <*****@*****.**>## is added to headers.
  *
  * If an array of messages is provided to the function, it is turned to a multi-part
  * message, as in the following example:
  *
  * [php]
  * $message = array();
  * $message['text/plain; charset=utf-8'] = 'This is a plain message';
  * $message['text/html'] = '<html><head><body>This is an HTML message</body></html>';
  * Mailer::post($from, $to, $subject, $message);
  * [/php]
  *
  * It is recommended to begin with the bare text, and to have the rich format part coming
  * after, as in the example. Also, if you don't provide a charset, then UTF-8 is used.
  *
  * Long lines of text/plain parts are wrapped according to
  * [link=Dan's suggestion]http://mailformat.dan.info/body/linelength.html[/link].
  *
  * @link http://mailformat.dan.info/body/linelength.html Dan's Mail Format Site: Body: Line Length
  *
  * Message parts are encoded either as quoted-printable (textual entities) or as base-64 (others).
  *
  * A list of files to be attached to the message can be provided as in the following example:
  *
  * [php]
  * $attachments = array();
  * $attachments[] = 'special/report.pdf';
  * $attachments[] = 'skins/my_skin/newsletters/image.png';
  * Mailer::post($from, $to, $subject, $message, $attachments);
  * [/php]
  *
  * Files are named from the installation directory of yacs, as visible in the examples.
  *
  * This function returns the number of successful posts,
  * and populates the error context, where applicable.
  *
  * @param string sender address
  * @param mixed recipient address(es)
  * @param string subject
  * @param mixed actual message, either a string, or an array of message parts
  * @param array attachments, if any
  * @param mixed additional headers, if any
  * @return the number of actual posts, or 0
  *
  * @see articles/mail.php
  * @see letters/new.php
  * @see users/mail.php
  */
 public static function post($from, $to, $subject, $message, $attachments = NULL, $headers = '')
 {
     global $context;
     // ensure that we have a sender
     if (!$from) {
         $from = Mailer::get_from_recipient();
     }
     // email services have to be activated
     if (!isset($context['with_email']) || $context['with_email'] != 'Y') {
         Logger::error(i18n::s('E-mail has not been enabled on this system.'));
         return 0;
         // check sender address
     } elseif (!$from) {
         Logger::error(i18n::s('Empty sender address'));
         return 0;
         // check recipient address
     } elseif (!$to) {
         Logger::error(i18n::s('Empty recipient address'));
         return 0;
         // check mail subject
     } elseif (!$subject) {
         Logger::error(i18n::s('No subject'));
         return 0;
         // check mail content
     } elseif (!$message) {
         Logger::error(i18n::s('No message'));
         return 0;
     }
     // the end of line string for mail messages
     if (!defined('M_EOL')) {
         define('M_EOL', "\n");
     }
     // encode the subject line
     $subject = Mailer::encode_subject($subject);
     // make some text out of an array
     if (is_array($headers)) {
         $headers = implode(M_EOL, $headers);
     }
     // From: header
     if (!preg_match('/^From: /im', $headers)) {
         $headers .= M_EOL . 'From: ' . $from;
     }
     // Reply-To: header
     if (!preg_match('/^Reply-To: /im', $headers)) {
         $headers .= M_EOL . 'Reply-To: ' . $from;
     }
     // Return-Path: header --to process errors
     if (!preg_match('/^Return-Path: /im', $headers)) {
         $headers .= M_EOL . 'Return-Path: ' . $from;
     }
     // Message-ID: header --helps to avoid spam filters
     if (!preg_match('/^Message-ID: /im', $headers)) {
         $headers .= M_EOL . 'Message-ID: <uniqid.' . uniqid() . '@' . $context['host_name'] . '>';
     }
     // MIME-Version: header
     if (!preg_match('/^MIME-Version: /im', $headers)) {
         $headers .= M_EOL . 'MIME-Version: 1.0';
     }
     // arrays are easier to manage
     if (is_string($message)) {
         // turn HTML entities to UTF-8
         $message = Safe::html_entity_decode($message, ENT_QUOTES, 'UTF-8');
         $copy = $message;
         $message = array();
         $message['text/plain; charset=utf-8'] = $copy;
         unset($copy);
     }
     // turn attachments to some array too
     if (is_string($attachments)) {
         $attachments = array($attachments);
     } elseif (!is_array($attachments)) {
         $attachments = array();
     }
     // we only consider objects from this server
     $my_prefix = $context['url_to_home'] . $context['url_to_root'];
     // transcode objects that will be transmitted along the message (i.e., images)
     foreach ($message as $type => $part) {
         // search throughout the full text
         $head = 0;
         while ($head = strpos($part, ' src="', $head)) {
             $head += strlen(' src="');
             // a link has been found
             if ($tail = strpos($part, '"', $head + 1)) {
                 $reference = substr($part, $head, $tail - $head);
                 // remember local links only
                 if (!strncmp($reference, $my_prefix, strlen($my_prefix))) {
                     // local name
                     $name = urldecode(substr($reference, strlen($my_prefix)));
                     // content-id to be used instead of the link
                     $cid = sprintf('%u@%s', crc32($name), $context['host_name']);
                     // transcode the link in this part
                     $part = substr($part, 0, $head) . 'cid:' . $cid . substr($part, $tail);
                     // remember to put content in attachments of this message, if not done yet
                     if (!in_array($name, $attachments)) {
                         $attachments[] = $name;
                     }
                 }
             }
         }
         // remember the transcoded part
         $message[$type] = $part;
     }
     // we need some boundary string
     if (count($message) + count($attachments) > 1) {
         $boundary = md5(time());
     }
     // wrapping threshold
     if (!defined('WRAPPING_LENGTH')) {
         define('WRAPPING_LENGTH', 70);
     }
     // combine message parts
     $content_type = '';
     $body = '';
     foreach ($message as $type => $part) {
         // quote textual entities
         if (!strncmp($type, 'text/', 5)) {
             $content_encoding = 'quoted-printable';
             $part = quoted_printable_encode($part);
             // encode everything else
         } else {
             $content_encoding = 'base64';
             $part = chunk_split(base64_encode($content), 76, M_EOL);
         }
         // only one part
         if (count($message) == 1) {
             $content_type = $type;
             $body = $part;
             // one part among several
         } else {
             // let user agent select among various alternatives
             if (!$content_type) {
                 $content_type = 'multipart/alternative; boundary="' . $boundary . '-internal"';
             }
             // introduction to assembled parts
             if (!$body) {
                 $body = 'This is a multi-part message in MIME format.';
             }
             // this part only --second EOL is part of the boundary chain
             $body .= M_EOL . M_EOL . '--' . $boundary . '-internal' . M_EOL . 'Content-Type: ' . $type . M_EOL . 'Content-Transfer-Encoding: ' . $content_encoding . M_EOL . M_EOL . $part;
         }
     }
     // finalize the body
     if (count($message) > 1) {
         $body .= M_EOL . M_EOL . '--' . $boundary . '-internal--';
     }
     // a mix of things
     if (count($attachments)) {
         // encoding is irrelevant if there are multiple parts
         if (!strncmp($content_type, 'multipart/', 10)) {
             $content_encoding = '';
         } else {
             $content_encoding = M_EOL . 'Content-Transfer-Encoding: ' . $content_encoding;
         }
         // identify the main part of the overall message
         $content_start = 'mainpart';
         // the current body becomes the first part of a larger message
         $body = 'This is a multi-part message in MIME format.' . M_EOL . M_EOL . '--' . $boundary . '-external' . M_EOL . 'Content-Type: ' . $content_type . $content_encoding . M_EOL . 'Content-ID: <' . $content_start . '>' . M_EOL . M_EOL . $body;
         // message parts should be considered as an aggregate whole --see RFC 2387
         $content_type = 'multipart/related; type="multipart/alternative"; boundary="' . $boundary . '-external"';
         $content_encoding = '';
         // process every file
         foreach ($attachments as $name => $content) {
             // read external file content
             if (preg_match('/^[0-9]+$/', $name)) {
                 // only a file name has been provided
                 $name = $content;
                 // read file content from the file system
                 if (!($content = Safe::file_get_contents($name))) {
                     continue;
                 }
             }
             // file name is the file type
             if (preg_match('/name="(.+)?"/', $name, $matches)) {
                 $type = $name;
                 $name = $matches[1];
             } else {
                 $type = Files::get_mime_type($name);
             }
             // a unique id for for this file
             $cid = sprintf('%u@%s', crc32($name), $context['host_name']);
             // set a name that avoids problems
             $basename = utf8::to_ascii(basename($name));
             // headers for one file
             $body .= M_EOL . M_EOL . '--' . $boundary . '-external' . M_EOL . 'Content-Type: ' . $type . M_EOL . 'Content-Disposition: inline; filename="' . str_replace('"', '', $basename) . '"' . M_EOL . 'Content-ID: <' . $cid . '>';
             // transfer textual entities as they are
             if (!strncmp($type, 'text/', 5)) {
                 $body .= M_EOL . 'Content-Transfer-Encoding: quoted-printable' . M_EOL . M_EOL . quoted_printable_encode($content);
                 // encode everything else
             } else {
                 $body .= M_EOL . 'Content-Transfer-Encoding: base64' . M_EOL . M_EOL . chunk_split(base64_encode($content), 76, M_EOL);
             }
         }
         // the closing boundary
         $body .= M_EOL . M_EOL . '--' . $boundary . '-external--';
     }
     // Content-Type: header
     if ($content_type && !preg_match('/^Content-Type: /im', $headers)) {
         $headers .= M_EOL . 'Content-Type: ' . $content_type;
     }
     // Content-Transfer-Encoding: header
     if (!isset($boundary) && $content_encoding && !preg_match('/^Content-Transfer-Encoding: /im', $headers)) {
         $headers .= M_EOL . 'Content-Transfer-Encoding: ' . $content_encoding;
     }
     // Start: header
     if (isset($boundary) && isset($content_start) && $content_start && !preg_match('/^Start: /im', $headers)) {
         $headers .= M_EOL . 'Start: ' . $content_start;
     }
     // X-Mailer: header --helps to avoid spam filters
     if (!preg_match('/^X-Mailer: /im', $headers)) {
         $headers .= M_EOL . 'X-Mailer: yacs';
     }
     // strip leading spaces and newlines
     $headers = trim($headers);
     // make an array of recipients
     if (!is_array($to)) {
         $to = Mailer::explode_recipients($to);
     }
     // the list of recipients contacted during overall script execution
     if (!isset($context['mailer_recipients'])) {
         $context['mailer_recipients'] = array();
     }
     // process every recipient
     $posts = 0;
     foreach ($to as $recipient) {
         // clean the provided string
         $recipient = trim(str_replace(array("\r\n", "\r", "\n", "\t"), ' ', $recipient));
         // this e-mail address has already been processed
         if (in_array($recipient, $context['mailer_recipients'])) {
             if (isset($context['debug_mail']) && $context['debug_mail'] == 'Y') {
                 Logger::remember('shared/mailer.php: Skipping recipient already processed', $recipient, 'debug');
             }
             continue;
             // remember this recipient
         } else {
             $context['mailer_recipients'][] = $recipient;
         }
         // queue the message
         Mailer::queue($recipient, $subject, $body, $headers);
         $posts++;
     }
     // track last submission
     include_once $context['path_to_root'] . 'shared/values.php';
     Values::set('mailer.last.queued', $subject . ' (' . $posts . ' recipients)');
     // return the number of actual posts
     return $posts;
 }