/', '', $data);
- $data = preg_replace('/<\/div>$/', '', $data);
- }
- else
- {
- $data = preg_replace('/^
/', '
', $data);
- }
- }
-
- if ($type & SIMPLEPIE_CONSTRUCT_IRI)
- {
- $absolute = $this->registry->call('Misc', 'absolutize_url', array($data, $base));
- if ($absolute !== false)
- {
- $data = $absolute;
- }
- }
-
- if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
- {
- $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
- }
-
- if ($this->output_encoding !== 'UTF-8')
- {
- $data = $this->registry->call('Misc', 'change_encoding', array($data, 'UTF-8', $this->output_encoding));
- }
- }
- return $data;
- }
-
- protected function preprocess($html, $type)
- {
- $ret = '';
- if ($type & ~SIMPLEPIE_CONSTRUCT_XHTML)
- {
- // Atom XHTML constructs are wrapped with a div by default
- // Note: No protection if $html contains a stray
!
- $html = '
' . $html . '
';
- $ret .= '';
- $content_type = 'text/html';
- }
- else
- {
- $ret .= '';
- $content_type = 'application/xhtml+xml';
- }
-
- $ret .= '';
- $ret .= '
';
- $ret .= '' . $html . '';
- return $ret;
- }
-
- public function replace_urls($document, $tag, $attributes)
- {
- if (!is_array($attributes))
- {
- $attributes = array($attributes);
- }
-
- if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
- {
- $elements = $document->getElementsByTagName($tag);
- foreach ($elements as $element)
- {
- foreach ($attributes as $attribute)
- {
- if ($element->hasAttribute($attribute))
- {
- $value = $this->registry->call('Misc', 'absolutize_url', array($element->getAttribute($attribute), $this->base));
- if ($value !== false)
- {
- $element->setAttribute($attribute, $value);
- }
- }
- }
- }
- }
- }
-
- public function do_strip_htmltags($match)
- {
- if ($this->encode_instead_of_strip)
- {
- if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
- {
- $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
- $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
- return "<$match[1]$match[2]>$match[3]</$match[1]>";
- }
- else
- {
- return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
- }
- }
- elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
- {
- return $match[4];
- }
- else
- {
- return '';
- }
- }
-
- protected function strip_tag($tag, $document, $type)
- {
- $xpath = new DOMXPath($document);
- $elements = $xpath->query('body//' . $tag);
- if ($this->encode_instead_of_strip)
- {
- foreach ($elements as $element)
- {
- $fragment = $document->createDocumentFragment();
-
- // For elements which aren't script or style, include the tag itself
- if (!in_array($tag, array('script', 'style')))
- {
- $text = '<' . $tag;
- if ($element->hasAttributes())
- {
- $attrs = array();
- foreach ($element->attributes as $name => $attr)
- {
- $value = $attr->value;
-
- // In XHTML, empty values should never exist, so we repeat the value
- if (empty($value) && ($type & SIMPLEPIE_CONSTRUCT_XHTML))
- {
- $value = $name;
- }
- // For HTML, empty is fine
- elseif (empty($value) && ($type & SIMPLEPIE_CONSTRUCT_HTML))
- {
- $attrs[] = $name;
- continue;
- }
-
- // Standard attribute text
- $attrs[] = $name . '="' . $attr->value . '"';
- }
- $text .= ' ' . implode(' ', $attrs);
- }
- $text .= '>';
- $fragment->appendChild(new DOMText($text));
- }
-
- $number = $element->childNodes->length;
- for ($i = $number; $i > 0; $i--)
- {
- $child = $element->childNodes->item(0);
- $fragment->appendChild($child);
- }
-
- if (!in_array($tag, array('script', 'style')))
- {
- $fragment->appendChild(new DOMText('' . $tag . '>'));
- }
-
- $element->parentNode->replaceChild($fragment, $element);
- }
-
- return;
- }
- elseif (in_array($tag, array('script', 'style')))
- {
- foreach ($elements as $element)
- {
- $element->parentNode->removeChild($element);
- }
-
- return;
- }
- else
- {
- foreach ($elements as $element)
- {
- $fragment = $document->createDocumentFragment();
- $number = $element->childNodes->length;
- for ($i = $number; $i > 0; $i--)
- {
- $child = $element->childNodes->item(0);
- $fragment->appendChild($child);
- }
-
- $element->parentNode->replaceChild($fragment, $element);
- }
- }
- }
-
- protected function strip_attr($attrib, $document)
- {
- $xpath = new DOMXPath($document);
- $elements = $xpath->query('//*[@' . $attrib . ']');
-
- foreach ($elements as $element)
- {
- $element->removeAttribute($attrib);
- }
- }
-}
-
-/**
- * Handles `
`
- *
- * Used by {@see SimplePie_Item::get_source()}
- *
- * This class can be overloaded with {@see SimplePie::set_source_class()}
- *
- * @package SimplePie
- * @subpackage API
- */
-class SimplePie_Source
-{
- var $item;
- var $data = array();
- protected $registry;
-
- public function __construct($item, $data)
- {
- $this->item = $item;
- $this->data = $data;
- }
-
- public function set_registry(SimplePie_Registry $registry)
- {
- $this->registry = $registry;
- }
-
- public function __toString()
- {
- return md5(serialize($this->data));
- }
-
- public function get_source_tags($namespace, $tag)
- {
- if (isset($this->data['child'][$namespace][$tag]))
- {
- return $this->data['child'][$namespace][$tag];
- }
- else
- {
- return null;
- }
- }
-
- public function get_base($element = array())
- {
- return $this->item->get_base($element);
- }
-
- public function sanitize($data, $type, $base = '')
- {
- return $this->item->sanitize($data, $type, $base);
- }
-
- public function get_item()
- {
- return $this->item;
- }
-
- public function get_title()
- {
- if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
- {
- return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
- {
- return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- else
- {
- return null;
- }
- }
-
- public function get_category($key = 0)
- {
- $categories = $this->get_categories();
- if (isset($categories[$key]))
- {
- return $categories[$key];
- }
- else
- {
- return null;
- }
- }
-
- public function get_categories()
- {
- $categories = array();
-
- foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
- {
- $term = null;
- $scheme = null;
- $label = null;
- if (isset($category['attribs']['']['term']))
- {
- $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- if (isset($category['attribs']['']['scheme']))
- {
- $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- if (isset($category['attribs']['']['label']))
- {
- $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
- }
- foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
- {
- // This is really the label, but keep this as the term also for BC.
- // Label will also work on retrieving because that falls back to term.
- $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- if (isset($category['attribs']['']['domain']))
- {
- $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- else
- {
- $scheme = null;
- }
- $categories[] = $this->registry->create('Category', array($term, $scheme, null));
- }
- foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
- {
- $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
- }
- foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
- {
- $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
- }
-
- if (!empty($categories))
- {
- return array_unique($categories);
- }
- else
- {
- return null;
- }
- }
-
- public function get_author($key = 0)
- {
- $authors = $this->get_authors();
- if (isset($authors[$key]))
- {
- return $authors[$key];
- }
- else
- {
- return null;
- }
- }
-
- public function get_authors()
- {
- $authors = array();
- foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
- {
- $name = null;
- $uri = null;
- $email = null;
- if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
- {
- $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
- {
- $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
- }
- if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
- {
- $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- if ($name !== null || $email !== null || $uri !== null)
- {
- $authors[] = $this->registry->create('Author', array($name, $uri, $email));
- }
- }
- if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
- {
- $name = null;
- $url = null;
- $email = null;
- if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
- {
- $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
- {
- $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
- }
- if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
- {
- $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- if ($name !== null || $email !== null || $url !== null)
- {
- $authors[] = $this->registry->create('Author', array($name, $url, $email));
- }
- }
- foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
- {
- $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
- }
- foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
- {
- $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
- }
- foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
- {
- $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
- }
-
- if (!empty($authors))
- {
- return array_unique($authors);
- }
- else
- {
- return null;
- }
- }
-
- public function get_contributor($key = 0)
- {
- $contributors = $this->get_contributors();
- if (isset($contributors[$key]))
- {
- return $contributors[$key];
- }
- else
- {
- return null;
- }
- }
-
- public function get_contributors()
- {
- $contributors = array();
- foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
- {
- $name = null;
- $uri = null;
- $email = null;
- if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
- {
- $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
- {
- $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
- }
- if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
- {
- $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- if ($name !== null || $email !== null || $uri !== null)
- {
- $contributors[] = $this->registry->create('Author', array($name, $uri, $email));
- }
- }
- foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
- {
- $name = null;
- $url = null;
- $email = null;
- if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
- {
- $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
- {
- $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
- }
- if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
- {
- $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- if ($name !== null || $email !== null || $url !== null)
- {
- $contributors[] = $this->registry->create('Author', array($name, $url, $email));
- }
- }
-
- if (!empty($contributors))
- {
- return array_unique($contributors);
- }
- else
- {
- return null;
- }
- }
-
- public function get_link($key = 0, $rel = 'alternate')
- {
- $links = $this->get_links($rel);
- if (isset($links[$key]))
- {
- return $links[$key];
- }
- else
- {
- return null;
- }
- }
-
- /**
- * Added for parity between the parent-level and the item/entry-level.
- */
- public function get_permalink()
- {
- return $this->get_link(0);
- }
-
- public function get_links($rel = 'alternate')
- {
- if (!isset($this->data['links']))
- {
- $this->data['links'] = array();
- if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
- {
- foreach ($links as $link)
- {
- if (isset($link['attribs']['']['href']))
- {
- $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
- $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
- }
- }
- }
- if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
- {
- foreach ($links as $link)
- {
- if (isset($link['attribs']['']['href']))
- {
- $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
- $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
-
- }
- }
- }
- if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
- {
- $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
- }
- if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
- {
- $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
- }
- if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
- {
- $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
- }
-
- $keys = array_keys($this->data['links']);
- foreach ($keys as $key)
- {
- if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
- {
- if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
- {
- $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
- $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
- }
- else
- {
- $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
- }
- }
- elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
- {
- $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
- }
- $this->data['links'][$key] = array_unique($this->data['links'][$key]);
- }
- }
-
- if (isset($this->data['links'][$rel]))
- {
- return $this->data['links'][$rel];
- }
- else
- {
- return null;
- }
- }
-
- public function get_description()
- {
- if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
- {
- return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
- {
- return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
- }
- else
- {
- return null;
- }
- }
-
- public function get_copyright()
- {
- if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
- {
- return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
- {
- return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- else
- {
- return null;
- }
- }
-
- public function get_language()
- {
- if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- elseif (isset($this->data['xml_lang']))
- {
- return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
- }
- else
- {
- return null;
- }
- }
-
- public function get_latitude()
- {
- if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
- {
- return (float) $return[0]['data'];
- }
- elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
- {
- return (float) $match[1];
- }
- else
- {
- return null;
- }
- }
-
- public function get_longitude()
- {
- if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
- {
- return (float) $return[0]['data'];
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
- {
- return (float) $return[0]['data'];
- }
- elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
- {
- return (float) $match[2];
- }
- else
- {
- return null;
- }
- }
-
- public function get_image_url()
- {
- if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
- {
- return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
- }
- elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
- {
- return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
- }
- else
- {
- return null;
- }
- }
-}
-
-/**
- * Parses the XML Declaration
- *
- * @package SimplePie
- * @subpackage Parsing
- */
-class SimplePie_XML_Declaration_Parser
-{
- /**
- * XML Version
- *
- * @access public
- * @var string
- */
- var $version = '1.0';
-
- /**
- * Encoding
- *
- * @access public
- * @var string
- */
- var $encoding = 'UTF-8';
-
- /**
- * Standalone
- *
- * @access public
- * @var bool
- */
- var $standalone = false;
-
- /**
- * Current state of the state machine
- *
- * @access private
- * @var string
- */
- var $state = 'before_version_name';
-
- /**
- * Input data
- *
- * @access private
- * @var string
- */
- var $data = '';
-
- /**
- * Input data length (to avoid calling strlen() everytime this is needed)
- *
- * @access private
- * @var int
- */
- var $data_length = 0;
-
- /**
- * Current position of the pointer
- *
- * @var int
- * @access private
- */
- var $position = 0;
-
- /**
- * Create an instance of the class with the input data
- *
- * @access public
- * @param string $data Input data
- */
- public function __construct($data)
- {
- $this->data = $data;
- $this->data_length = strlen($this->data);
- }
-
- /**
- * Parse the input data
- *
- * @access public
- * @return bool true on success, false on failure
- */
- public function parse()
- {
- while ($this->state && $this->state !== 'emit' && $this->has_data())
- {
- $state = $this->state;
- $this->$state();
- }
- $this->data = '';
- if ($this->state === 'emit')
- {
- return true;
- }
- else
- {
- $this->version = '';
- $this->encoding = '';
- $this->standalone = '';
- return false;
- }
- }
-
- /**
- * Check whether there is data beyond the pointer
- *
- * @access private
- * @return bool true if there is further data, false if not
- */
- public function has_data()
- {
- return (bool) ($this->position < $this->data_length);
- }
-
- /**
- * Advance past any whitespace
- *
- * @return int Number of whitespace characters passed
- */
- public function skip_whitespace()
- {
- $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
- $this->position += $whitespace;
- return $whitespace;
- }
-
- /**
- * Read value
- */
- public function get_value()
- {
- $quote = substr($this->data, $this->position, 1);
- if ($quote === '"' || $quote === "'")
- {
- $this->position++;
- $len = strcspn($this->data, $quote, $this->position);
- if ($this->has_data())
- {
- $value = substr($this->data, $this->position, $len);
- $this->position += $len + 1;
- return $value;
- }
- }
- return false;
- }
-
- public function before_version_name()
- {
- if ($this->skip_whitespace())
- {
- $this->state = 'version_name';
- }
- else
- {
- $this->state = false;
- }
- }
-
- public function version_name()
- {
- if (substr($this->data, $this->position, 7) === 'version')
- {
- $this->position += 7;
- $this->skip_whitespace();
- $this->state = 'version_equals';
- }
- else
- {
- $this->state = false;
- }
- }
-
- public function version_equals()
- {
- if (substr($this->data, $this->position, 1) === '=')
- {
- $this->position++;
- $this->skip_whitespace();
- $this->state = 'version_value';
- }
- else
- {
- $this->state = false;
- }
- }
-
- public function version_value()
- {
- if ($this->version = $this->get_value())
- {
- $this->skip_whitespace();
- if ($this->has_data())
- {
- $this->state = 'encoding_name';
- }
- else
- {
- $this->state = 'emit';
- }
- }
- else
- {
- $this->state = false;
- }
- }
-
- public function encoding_name()
- {
- if (substr($this->data, $this->position, 8) === 'encoding')
- {
- $this->position += 8;
- $this->skip_whitespace();
- $this->state = 'encoding_equals';
- }
- else
- {
- $this->state = 'standalone_name';
- }
- }
-
- public function encoding_equals()
- {
- if (substr($this->data, $this->position, 1) === '=')
- {
- $this->position++;
- $this->skip_whitespace();
- $this->state = 'encoding_value';
- }
- else
- {
- $this->state = false;
- }
- }
-
- public function encoding_value()
- {
- if ($this->encoding = $this->get_value())
- {
- $this->skip_whitespace();
- if ($this->has_data())
- {
- $this->state = 'standalone_name';
- }
- else
- {
- $this->state = 'emit';
- }
- }
- else
- {
- $this->state = false;
- }
- }
-
- public function standalone_name()
- {
- if (substr($this->data, $this->position, 10) === 'standalone')
- {
- $this->position += 10;
- $this->skip_whitespace();
- $this->state = 'standalone_equals';
- }
- else
- {
- $this->state = false;
- }
- }
-
- public function standalone_equals()
- {
- if (substr($this->data, $this->position, 1) === '=')
- {
- $this->position++;
- $this->skip_whitespace();
- $this->state = 'standalone_value';
- }
- else
- {
- $this->state = false;
- }
- }
-
- public function standalone_value()
- {
- if ($standalone = $this->get_value())
- {
- switch ($standalone)
- {
- case 'yes':
- $this->standalone = true;
- break;
-
- case 'no':
- $this->standalone = false;
- break;
-
- default:
- $this->state = false;
- return;
- }
-
- $this->skip_whitespace();
- if ($this->has_data())
- {
- $this->state = false;
- }
- else
- {
- $this->state = 'emit';
- }
- }
- else
- {
- $this->state = false;
- }
- }
-}
-
diff --git a/sources/inc/Sitemapper.php b/sources/inc/Sitemapper.php
deleted file mode 100644
index 037990e..0000000
--- a/sources/inc/Sitemapper.php
+++ /dev/null
@@ -1,220 +0,0 @@
-
- */
-
-if(!defined('DOKU_INC')) die('meh.');
-
-/**
- * A class for building sitemaps and pinging search engines with the sitemap URL.
- *
- * @author Michael Hamann
- */
-class Sitemapper {
- /**
- * Builds a Google Sitemap of all public pages known to the indexer
- *
- * The map is placed in the cache directory named sitemap.xml.gz - This
- * file needs to be writable!
- *
- * @author Michael Hamann
- * @author Andreas Gohr
- * @link https://www.google.com/webmasters/sitemaps/docs/en/about.html
- * @link http://www.sitemaps.org/
- *
- * @return bool
- */
- public static function generate(){
- global $conf;
- if($conf['sitemap'] < 1 || !is_numeric($conf['sitemap'])) return false;
-
- $sitemap = Sitemapper::getFilePath();
-
- if(file_exists($sitemap)){
- if(!is_writable($sitemap)) return false;
- }else{
- if(!is_writable(dirname($sitemap))) return false;
- }
-
- if(@filesize($sitemap) &&
- @filemtime($sitemap) > (time()-($conf['sitemap']*86400))){ // 60*60*24=86400
- dbglog('Sitemapper::generate(): Sitemap up to date');
- return false;
- }
-
- dbglog("Sitemapper::generate(): using $sitemap");
-
- $pages = idx_get_indexer()->getPages();
- dbglog('Sitemapper::generate(): creating sitemap using '.count($pages).' pages');
- $items = array();
-
- // build the sitemap items
- foreach($pages as $id){
- //skip hidden, non existing and restricted files
- if(isHiddenPage($id)) continue;
- if(auth_aclcheck($id,'',array()) < AUTH_READ) continue;
- $item = SitemapItem::createFromID($id);
- if ($item !== null)
- $items[] = $item;
- }
-
- $eventData = array('items' => &$items, 'sitemap' => &$sitemap);
- $event = new Doku_Event('SITEMAP_GENERATE', $eventData);
- if ($event->advise_before(true)) {
- //save the new sitemap
- $event->result = io_saveFile($sitemap, Sitemapper::getXML($items));
- }
- $event->advise_after();
-
- return $event->result;
- }
-
- /**
- * Builds the sitemap XML string from the given array auf SitemapItems.
- *
- * @param $items array The SitemapItems that shall be included in the sitemap.
- * @return string The sitemap XML.
- *
- * @author Michael Hamann
- */
- private static function getXML($items) {
- ob_start();
- echo ''.NL;
- echo ''.NL;
- foreach ($items as $item) {
- /** @var SitemapItem $item */
- echo $item->toXML();
- }
- echo ''.NL;
- $result = ob_get_contents();
- ob_end_clean();
- return $result;
- }
-
- /**
- * Helper function for getting the path to the sitemap file.
- *
- * @return string The path to the sitemap file.
- *
- * @author Michael Hamann
- */
- public static function getFilePath() {
- global $conf;
-
- $sitemap = $conf['cachedir'].'/sitemap.xml';
- if (self::sitemapIsCompressed()) {
- $sitemap .= '.gz';
- }
-
- return $sitemap;
- }
-
- /**
- * Helper function for checking if the sitemap is compressed
- *
- * @return bool If the sitemap file is compressed
- */
- public static function sitemapIsCompressed() {
- global $conf;
- return $conf['compression'] === 'bz2' || $conf['compression'] === 'gz';
- }
-
- /**
- * Pings search engines with the sitemap url. Plugins can add or remove
- * urls to ping using the SITEMAP_PING event.
- *
- * @author Michael Hamann
- *
- * @return bool
- */
- public static function pingSearchEngines() {
- //ping search engines...
- $http = new DokuHTTPClient();
- $http->timeout = 8;
-
- $encoded_sitemap_url = urlencode(wl('', array('do' => 'sitemap'), true, '&'));
- $ping_urls = array(
- 'google' => 'http://www.google.com/webmasters/sitemaps/ping?sitemap='.$encoded_sitemap_url,
- 'microsoft' => 'http://www.bing.com/webmaster/ping.aspx?siteMap='.$encoded_sitemap_url,
- 'yandex' => 'http://blogs.yandex.ru/pings/?status=success&url='.$encoded_sitemap_url
- );
-
- $data = array('ping_urls' => $ping_urls,
- 'encoded_sitemap_url' => $encoded_sitemap_url
- );
- $event = new Doku_Event('SITEMAP_PING', $data);
- if ($event->advise_before(true)) {
- foreach ($data['ping_urls'] as $name => $url) {
- dbglog("Sitemapper::PingSearchEngines(): pinging $name");
- $resp = $http->get($url);
- if($http->error) dbglog("Sitemapper:pingSearchengines(): $http->error");
- dbglog('Sitemapper:pingSearchengines(): '.preg_replace('/[\n\r]/',' ',strip_tags($resp)));
- }
- }
- $event->advise_after();
-
- return true;
- }
-}
-
-/**
- * An item of a sitemap.
- *
- * @author Michael Hamann
- */
-class SitemapItem {
- public $url;
- public $lastmod;
- public $changefreq;
- public $priority;
-
- /**
- * Create a new item.
- *
- * @param string $url The url of the item
- * @param int $lastmod Timestamp of the last modification
- * @param string $changefreq How frequently the item is likely to change. Valid values: always, hourly, daily, weekly, monthly, yearly, never.
- * @param $priority float|string The priority of the item relative to other URLs on your site. Valid values range from 0.0 to 1.0.
- */
- public function __construct($url, $lastmod, $changefreq = null, $priority = null) {
- $this->url = $url;
- $this->lastmod = $lastmod;
- $this->changefreq = $changefreq;
- $this->priority = $priority;
- }
-
- /**
- * Helper function for creating an item for a wikipage id.
- *
- * @param string $id A wikipage id.
- * @param string $changefreq How frequently the item is likely to change. Valid values: always, hourly, daily, weekly, monthly, yearly, never.
- * @param float|string $priority The priority of the item relative to other URLs on your site. Valid values range from 0.0 to 1.0.
- * @return SitemapItem The sitemap item.
- */
- public static function createFromID($id, $changefreq = null, $priority = null) {
- $id = trim($id);
- $date = @filemtime(wikiFN($id));
- if(!$date) return null;
- return new SitemapItem(wl($id, '', true), $date, $changefreq, $priority);
- }
-
- /**
- * Get the XML representation of the sitemap item.
- *
- * @return string The XML representation.
- */
- public function toXML() {
- $result = ' '.NL
- .' '.hsc($this->url).''.NL
- .' '.date_iso8601($this->lastmod).''.NL;
- if ($this->changefreq !== null)
- $result .= ' '.hsc($this->changefreq).''.NL;
- if ($this->priority !== null)
- $result .= ' '.hsc($this->priority).''.NL;
- $result .= ' '.NL;
- return $result;
- }
-}
diff --git a/sources/inc/Tar.class.php b/sources/inc/Tar.class.php
deleted file mode 100644
index 57c280d..0000000
--- a/sources/inc/Tar.class.php
+++ /dev/null
@@ -1,648 +0,0 @@
-100 chars) are supported in POSIX ustar and GNU longlink formats.
- *
- * To list the contents of an existing TAR archive, open() it and use contents() on it:
- *
- * $tar = new Tar();
- * $tar->open('myfile.tgz');
- * $toc = $tar->contents();
- * print_r($toc);
- *
- * To extract the contents of an existing TAR archive, open() it and use extract() on it:
- *
- * $tar = new Tar();
- * $tar->open('myfile.tgz');
- * $tar->extract('/tmp');
- *
- * To create a new TAR archive directly on the filesystem (low memory requirements), create() it,
- * add*() files and close() it:
- *
- * $tar = new Tar();
- * $tar->create('myfile.tgz');
- * $tar->addFile(...);
- * $tar->addData(...);
- * ...
- * $tar->close();
- *
- * To create a TAR archive directly in memory, create() it, add*() files and then either save()
- * or getData() it:
- *
- * $tar = new Tar();
- * $tar->create();
- * $tar->addFile(...);
- * $tar->addData(...);
- * ...
- * $tar->save('myfile.tgz'); // compresses and saves it
- * echo $tar->getArchive(Tar::COMPRESS_GZIP); // compresses and returns it
- *
- * @author Andreas Gohr
- * @author Bouchon (Maxg)
- * @license GPL 2
- * @deprecated 2015-05-15 - use splitbrain\PHPArchive\Tar instead
- */
-class Tar {
-
- const COMPRESS_AUTO = 0;
- const COMPRESS_NONE = 1;
- const COMPRESS_GZIP = 2;
- const COMPRESS_BZIP = 3;
-
- protected $file = '';
- protected $comptype = Tar::COMPRESS_AUTO;
- /** @var resource|int */
- protected $fh;
- protected $memory = '';
- protected $closed = true;
- protected $writeaccess = false;
-
- /**
- * Open an existing TAR file for reading
- *
- * @param string $file
- * @param int $comptype
- * @throws TarIOException
- */
- public function open($file, $comptype = Tar::COMPRESS_AUTO) {
- // determine compression
- if($comptype == Tar::COMPRESS_AUTO) $comptype = $this->filetype($file);
- $this->compressioncheck($comptype);
-
- $this->comptype = $comptype;
- $this->file = $file;
-
- if($this->comptype === Tar::COMPRESS_GZIP) {
- $this->fh = @gzopen($this->file, 'rb');
- } elseif($this->comptype === Tar::COMPRESS_BZIP) {
- $this->fh = @bzopen($this->file, 'r');
- } else {
- $this->fh = @fopen($this->file, 'rb');
- }
-
- if(!$this->fh) throw new TarIOException('Could not open file for reading: '.$this->file);
- $this->closed = false;
- }
-
- /**
- * Read the contents of a TAR archive
- *
- * This function lists the files stored in the archive, and returns an indexed array of associative
- * arrays containing for each file the following information:
- *
- * checksum Tar Checksum of the file
- * filename The full name of the stored file (up to 100 c.)
- * mode UNIX permissions in DECIMAL, not octal
- * uid The Owner ID
- * gid The Group ID
- * size Uncompressed filesize
- * mtime Timestamp of last modification
- * typeflag Empty for files, set for folders
- * link Is it a symlink?
- * uname Owner name
- * gname Group name
- *
- * The archive is closed afer reading the contents, because rewinding is not possible in bzip2 streams.
- * Reopen the file with open() again if you want to do additional operations
- *
- * @return array
- * @throws TarIOException
- */
- public function contents() {
- if($this->closed || !$this->file) throw new TarIOException('Can not read from a closed archive');
-
- $result = array();
- while($read = $this->readbytes(512)) {
- $header = $this->parseHeader($read);
- if(!is_array($header)) continue;
-
- $this->skipbytes(ceil($header['size'] / 512) * 512);
- $result[] = $header;
- }
-
- $this->close();
- return $result;
- }
-
- /**
- * Extract an existing TAR archive
- *
- * The $strip parameter allows you to strip a certain number of path components from the filenames
- * found in the tar file, similar to the --strip-components feature of GNU tar. This is triggered when
- * an integer is passed as $strip.
- * Alternatively a fixed string prefix may be passed in $strip. If the filename matches this prefix,
- * the prefix will be stripped. It is recommended to give prefixes with a trailing slash.
- *
- * By default this will extract all files found in the archive. You can restrict the output using the $include
- * and $exclude parameter. Both expect a full regular expression (including delimiters and modifiers). If
- * $include is set only files that match this expression will be extracted. Files that match the $exclude
- * expression will never be extracted. Both parameters can be used in combination. Expressions are matched against
- * stripped filenames as described above.
- *
- * The archive is closed afer reading the contents, because rewinding is not possible in bzip2 streams.
- * Reopen the file with open() again if you want to do additional operations
- *
- * @param string $outdir the target directory for extracting
- * @param int|string $strip either the number of path components or a fixed prefix to strip
- * @param string $exclude a regular expression of files to exclude
- * @param string $include a regular expression of files to include
- * @throws TarIOException
- * @return array
- */
- function extract($outdir, $strip = '', $exclude = '', $include = '') {
- if($this->closed || !$this->file) throw new TarIOException('Can not read from a closed archive');
-
- $outdir = rtrim($outdir, '/');
- io_mkdir_p($outdir);
- $striplen = strlen($strip);
-
- $extracted = array();
-
- while($dat = $this->readbytes(512)) {
- // read the file header
- $header = $this->parseHeader($dat);
- if(!is_array($header)) continue;
- if(!$header['filename']) continue;
-
- // strip prefix
- $filename = $this->cleanPath($header['filename']);
- if(is_int($strip)) {
- // if $strip is an integer we strip this many path components
- $parts = explode('/', $filename);
- if(!$header['typeflag']) {
- $base = array_pop($parts); // keep filename itself
- } else {
- $base = '';
- }
- $filename = join('/', array_slice($parts, $strip));
- if($base) $filename .= "/$base";
- } else {
- // ifstrip is a string, we strip a prefix here
- if(substr($filename, 0, $striplen) == $strip) $filename = substr($filename, $striplen);
- }
-
- // check if this should be extracted
- $extract = true;
- if(!$filename) {
- $extract = false;
- } else {
- if($include) {
- if(preg_match($include, $filename)) {
- $extract = true;
- } else {
- $extract = false;
- }
- }
- if($exclude && preg_match($exclude, $filename)) {
- $extract = false;
- }
- }
-
- // Now do the extraction (or not)
- if($extract) {
- $extracted[] = $header;
-
- $output = "$outdir/$filename";
- $directory = ($header['typeflag']) ? $output : dirname($output);
- io_mkdir_p($directory);
-
- // is this a file?
- if(!$header['typeflag']) {
- $fp = fopen($output, "wb");
- if(!$fp) throw new TarIOException('Could not open file for writing: '.$output);
-
- $size = floor($header['size'] / 512);
- for($i = 0; $i < $size; $i++) {
- fwrite($fp, $this->readbytes(512), 512);
- }
- if(($header['size'] % 512) != 0) fwrite($fp, $this->readbytes(512), $header['size'] % 512);
-
- fclose($fp);
- touch($output, $header['mtime']);
- chmod($output, $header['perm']);
- } else {
- $this->skipbytes(ceil($header['size'] / 512) * 512); // the size is usually 0 for directories
- }
- } else {
- $this->skipbytes(ceil($header['size'] / 512) * 512);
- }
- }
-
- $this->close();
- return $extracted;
- }
-
- /**
- * Create a new TAR file
- *
- * If $file is empty, the tar file will be created in memory
- *
- * @param string $file
- * @param int $comptype
- * @param int $complevel
- * @throws TarIOException
- * @throws TarIllegalCompressionException
- */
- public function create($file = '', $comptype = Tar::COMPRESS_AUTO, $complevel = 9) {
- // determine compression
- if($comptype == Tar::COMPRESS_AUTO) $comptype = $this->filetype($file);
- $this->compressioncheck($comptype);
-
- $this->comptype = $comptype;
- $this->file = $file;
- $this->memory = '';
- $this->fh = 0;
-
- if($this->file) {
- if($this->comptype === Tar::COMPRESS_GZIP) {
- $this->fh = @gzopen($this->file, 'wb'.$complevel);
- } elseif($this->comptype === Tar::COMPRESS_BZIP) {
- $this->fh = @bzopen($this->file, 'w');
- } else {
- $this->fh = @fopen($this->file, 'wb');
- }
-
- if(!$this->fh) throw new TarIOException('Could not open file for writing: '.$this->file);
- }
- $this->writeaccess = true;
- $this->closed = false;
- }
-
- /**
- * Add a file to the current TAR archive using an existing file in the filesystem
- *
- * @todo handle directory adding
- *
- * @param string $file the original file
- * @param string $name the name to use for the file in the archive
- * @throws TarIOException
- */
- public function addFile($file, $name = '') {
- if($this->closed) throw new TarIOException('Archive has been closed, files can no longer be added');
-
- if(!$name) $name = $file;
- $name = $this->cleanPath($name);
-
- $fp = fopen($file, 'rb');
- if(!$fp) throw new TarIOException('Could not open file for reading: '.$file);
-
- // create file header and copy all stat info from the original file
- clearstatcache(false, $file);
- $stat = stat($file);
- $this->writeFileHeader(
- $name,
- $stat[4],
- $stat[5],
- fileperms($file),
- filesize($file),
- filemtime($file)
- );
-
- while(!feof($fp)) {
- $data = fread($fp, 512);
- if($data === false) break;
- if($data === '') break;
- $packed = pack("a512", $data);
- $this->writebytes($packed);
- }
- fclose($fp);
- }
-
- /**
- * Add a file to the current TAR archive using the given $data as content
- *
- * @param string $name
- * @param string $data
- * @param int $uid
- * @param int $gid
- * @param int $perm
- * @param int $mtime
- * @throws TarIOException
- */
- public function addData($name, $data, $uid = 0, $gid = 0, $perm = 0666, $mtime = 0) {
- if($this->closed) throw new TarIOException('Archive has been closed, files can no longer be added');
-
- $name = $this->cleanPath($name);
- $len = strlen($data);
-
- $this->writeFileHeader(
- $name,
- $uid,
- $gid,
- $perm,
- $len,
- ($mtime) ? $mtime : time()
- );
-
- for($s = 0; $s < $len; $s += 512) {
- $this->writebytes(pack("a512", substr($data, $s, 512)));
- }
- }
-
- /**
- * Add the closing footer to the archive if in write mode, close all file handles
- *
- * After a call to this function no more data can be added to the archive, for
- * read access no reading is allowed anymore
- *
- * "Physically, an archive consists of a series of file entries terminated by an end-of-archive entry, which
- * consists of two 512 blocks of zero bytes"
- *
- * @link http://www.gnu.org/software/tar/manual/html_chapter/tar_8.html#SEC134
- */
- public function close() {
- if($this->closed) return; // we did this already
-
- // write footer
- if($this->writeaccess) {
- $this->writebytes(pack("a512", ""));
- $this->writebytes(pack("a512", ""));
- }
-
- // close file handles
- if($this->file) {
- if($this->comptype === Tar::COMPRESS_GZIP) {
- gzclose($this->fh);
- } elseif($this->comptype === Tar::COMPRESS_BZIP) {
- bzclose($this->fh);
- } else {
- fclose($this->fh);
- }
-
- $this->file = '';
- $this->fh = 0;
- }
-
- $this->closed = true;
- }
-
- /**
- * Returns the created in-memory archive data
- *
- * This implicitly calls close() on the Archive
- *
- * @param int $comptype
- * @param int $complevel
- * @return mixed|string
- */
- public function getArchive($comptype = Tar::COMPRESS_AUTO, $complevel = 9) {
- $this->close();
-
- if($comptype === Tar::COMPRESS_AUTO) $comptype = $this->comptype;
- $this->compressioncheck($comptype);
-
- if($comptype === Tar::COMPRESS_GZIP) return gzcompress($this->memory, $complevel);
- if($comptype === Tar::COMPRESS_BZIP) return bzcompress($this->memory);
- return $this->memory;
- }
-
- /**
- * Save the created in-memory archive data
- *
- * Note: It more memory effective to specify the filename in the create() function and
- * let the library work on the new file directly.
- *
- * @param string $file
- * @param int $comptype
- * @param int $complevel
- * @throws TarIOException
- */
- public function save($file, $comptype = Tar::COMPRESS_AUTO, $complevel = 9) {
- if($comptype === Tar::COMPRESS_AUTO) $comptype = $this->filetype($file);
-
- if(!file_put_contents($file, $this->getArchive($comptype, $complevel))) {
- throw new TarIOException('Could not write to file: '.$file);
- }
- }
-
- /**
- * Read from the open file pointer
- *
- * @param int $length bytes to read
- * @return string
- */
- protected function readbytes($length) {
- if($this->comptype === Tar::COMPRESS_GZIP) {
- return @gzread($this->fh, $length);
- } elseif($this->comptype === Tar::COMPRESS_BZIP) {
- return @bzread($this->fh, $length);
- } else {
- return @fread($this->fh, $length);
- }
- }
-
- /**
- * Write to the open filepointer or memory
- *
- * @param string $data
- * @throws TarIOException
- * @return int number of bytes written
- */
- protected function writebytes($data) {
- if(!$this->file) {
- $this->memory .= $data;
- $written = strlen($data);
- } elseif($this->comptype === Tar::COMPRESS_GZIP) {
- $written = @gzwrite($this->fh, $data);
- } elseif($this->comptype === Tar::COMPRESS_BZIP) {
- $written = @bzwrite($this->fh, $data);
- } else {
- $written = @fwrite($this->fh, $data);
- }
- if($written === false) throw new TarIOException('Failed to write to archive stream');
- return $written;
- }
-
- /**
- * Skip forward in the open file pointer
- *
- * This is basically a wrapper around seek() (and a workaround for bzip2)
- *
- * @param int $bytes seek to this position
- */
- function skipbytes($bytes) {
- if($this->comptype === Tar::COMPRESS_GZIP) {
- @gzseek($this->fh, $bytes, SEEK_CUR);
- } elseif($this->comptype === Tar::COMPRESS_BZIP) {
- // there is no seek in bzip2, we simply read on
- @bzread($this->fh, $bytes);
- } else {
- @fseek($this->fh, $bytes, SEEK_CUR);
- }
- }
-
- /**
- * Write a file header
- *
- * @param string $name
- * @param int $uid
- * @param int $gid
- * @param int $perm
- * @param int $size
- * @param int $mtime
- * @param string $typeflag Set to '5' for directories
- */
- protected function writeFileHeader($name, $uid, $gid, $perm, $size, $mtime, $typeflag = '') {
- // handle filename length restrictions
- $prefix = '';
- $namelen = strlen($name);
- if($namelen > 100) {
- $file = basename($name);
- $dir = dirname($name);
- if(strlen($file) > 100 || strlen($dir) > 155) {
- // we're still too large, let's use GNU longlink
- $this->writeFileHeader('././@LongLink', 0, 0, 0, $namelen, 0, 'L');
- for($s = 0; $s < $namelen; $s += 512) {
- $this->writebytes(pack("a512", substr($name, $s, 512)));
- }
- $name = substr($name, 0, 100); // cut off name
- } else {
- // we're fine when splitting, use POSIX ustar
- $prefix = $dir;
- $name = $file;
- }
- }
-
- // values are needed in octal
- $uid = sprintf("%6s ", decoct($uid));
- $gid = sprintf("%6s ", decoct($gid));
- $perm = sprintf("%6s ", decoct($perm));
- $size = sprintf("%11s ", decoct($size));
- $mtime = sprintf("%11s", decoct($mtime));
-
- $data_first = pack("a100a8a8a8a12A12", $name, $perm, $uid, $gid, $size, $mtime);
- $data_last = pack("a1a100a6a2a32a32a8a8a155a12", $typeflag, '', 'ustar', '', '', '', '', '', $prefix, "");
-
- for($i = 0, $chks = 0; $i < 148; $i++)
- $chks += ord($data_first[$i]);
-
- for($i = 156, $chks += 256, $j = 0; $i < 512; $i++, $j++)
- $chks += ord($data_last[$j]);
-
- $this->writebytes($data_first);
-
- $chks = pack("a8", sprintf("%6s ", decoct($chks)));
- $this->writebytes($chks.$data_last);
- }
-
- /**
- * Decode the given tar file header
- *
- * @param string $block a 512 byte block containign the header data
- * @return false|array
- */
- protected function parseHeader($block) {
- if(!$block || strlen($block) != 512) return false;
-
- for($i = 0, $chks = 0; $i < 148; $i++)
- $chks += ord($block[$i]);
-
- for($i = 156, $chks += 256; $i < 512; $i++)
- $chks += ord($block[$i]);
-
- $header = @unpack("a100filename/a8perm/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix", $block);
- if(!$header) return false;
-
- $return = array();
- $return['checksum'] = OctDec(trim($header['checksum']));
- if($return['checksum'] != $chks) return false;
-
- $return['filename'] = trim($header['filename']);
- $return['perm'] = OctDec(trim($header['perm']));
- $return['uid'] = OctDec(trim($header['uid']));
- $return['gid'] = OctDec(trim($header['gid']));
- $return['size'] = OctDec(trim($header['size']));
- $return['mtime'] = OctDec(trim($header['mtime']));
- $return['typeflag'] = $header['typeflag'];
- $return['link'] = trim($header['link']);
- $return['uname'] = trim($header['uname']);
- $return['gname'] = trim($header['gname']);
-
- // Handle ustar Posix compliant path prefixes
- if(trim($header['prefix'])) $return['filename'] = trim($header['prefix']).'/'.$return['filename'];
-
- // Handle Long-Link entries from GNU Tar
- if($return['typeflag'] == 'L') {
- // following data block(s) is the filename
- $filename = trim($this->readbytes(ceil($header['size'] / 512) * 512));
- // next block is the real header
- $block = $this->readbytes(512);
- $return = $this->parseHeader($block);
- // overwrite the filename
- $return['filename'] = $filename;
- }
-
- return $return;
- }
-
- /**
- * Cleans up a path and removes relative parts, also strips leading slashes
- *
- * @param string $path
- * @return string
- */
- public function cleanPath($path) {
- $path=explode('/', $path);
- $newpath=array();
- foreach($path as $p) {
- if ($p === '' || $p === '.') continue;
- if ($p==='..') {
- array_pop($newpath);
- continue;
- }
- array_push($newpath, $p);
- }
- return trim(implode('/', $newpath), '/');
- }
-
- /**
- * Checks if the given compression type is available and throws an exception if not
- *
- * @param int $comptype
- * @throws TarIllegalCompressionException
- */
- protected function compressioncheck($comptype) {
- if($comptype === Tar::COMPRESS_GZIP && !function_exists('gzopen')) {
- throw new TarIllegalCompressionException('No gzip support available');
- }
-
- if($comptype === Tar::COMPRESS_BZIP && !function_exists('bzopen')) {
- throw new TarIllegalCompressionException('No bzip2 support available');
- }
- }
-
- /**
- * Guesses the wanted compression from the given filename extension
- *
- * You don't need to call this yourself. It's used when you pass Tar::COMPRESS_AUTO somewhere
- *
- * @param string $file
- * @return int
- */
- public function filetype($file) {
- $file = strtolower($file);
- if(substr($file, -3) == '.gz' || substr($file, -4) == '.tgz') {
- $comptype = Tar::COMPRESS_GZIP;
- } elseif(substr($file, -4) == '.bz2' || substr($file, -4) == '.tbz') {
- $comptype = Tar::COMPRESS_BZIP;
- } else {
- $comptype = Tar::COMPRESS_NONE;
- }
- return $comptype;
- }
-}
-
-/**
- * Class TarIOException
- */
-class TarIOException extends Exception {
-}
-
-/**
- * Class TarIllegalCompressionException
- */
-class TarIllegalCompressionException extends Exception {
-}
diff --git a/sources/inc/ZipLib.class.php b/sources/inc/ZipLib.class.php
deleted file mode 100644
index 1358ca4..0000000
--- a/sources/inc/ZipLib.class.php
+++ /dev/null
@@ -1,576 +0,0 @@
-
- */
-class ZipLib {
-
- var $datasec;
- var $ctrl_dir = array();
- var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
- var $old_offset = 0;
- var $dirs = Array(".");
-
- /**
- * @param string $zip_name filename path to file
- * @return array|int
- */
- function get_List($zip_name) {
- $zip = @fopen($zip_name, 'rb');
- if(!$zip) return(0);
- $centd = $this->ReadCentralDir($zip,$zip_name);
-
- @rewind($zip);
- @fseek($zip, $centd['offset']);
-
- $ret = array();
- for ($i=0; $i<$centd['entries']; $i++) {
- $header = $this->ReadCentralFileHeaders($zip);
- $header['index'] = $i;
-
- $info = array();
- $info['filename'] = $header['filename'];
- $info['stored_filename'] = $header['stored_filename'];
- $info['size'] = $header['size'];
- $info['compressed_size'] = $header['compressed_size'];
- $info['crc'] = strtoupper(dechex( $header['crc'] ));
- $info['mtime'] = $header['mtime'];
- $info['comment'] = $header['comment'];
- $info['folder'] = ($header['external']==0x41FF0010||$header['external']==16)?1:0;
- $info['index'] = $header['index'];
- $info['status'] = $header['status'];
- $ret[]=$info;
-
- unset($header);
- }
- return $ret;
- }
-
- /**
- * @param array $files array filled with array(string filename, string data)
- * @param bool $compact
- * @return array
- */
- function Add($files,$compact) {
- if(!is_array($files[0])) $files=Array($files);
-
- $ret = array();
- for($i=0;$files[$i];$i++){
- $fn = $files[$i];
- if(!in_Array(dirname($fn[0]),$this->dirs))
- $this->add_Dir(dirname($fn[0]));
- if(utf8_basename($fn[0]))
- $ret[utf8_basename($fn[0])]=$this->add_File($fn[1],$fn[0],$compact);
- }
- return $ret;
- }
-
- /**
- * Zips recursively the $folder directory, from the $basedir directory
- *
- * @param string $folder filename path to file
- * @param string|null $basedir
- * @param string|null $parent
- */
- function Compress($folder, $basedir=null, $parent=null) {
- $full_path = $basedir."/".$parent.$folder;
- $zip_path = $parent.$folder;
- if ($zip_path) {
- $zip_path .= "/";
- $this->add_dir($zip_path);
- }
- $dir = new DirectoryIterator($full_path);
- foreach($dir as $file) {
- /** @var DirectoryIterator $file */
- if(!$file->isDot()) {
- $filename = $file->getFilename();
- if($file->isDir()) {
- $this->Compress($filename, $basedir, $zip_path);
- } else {
- $content = join('', file($full_path.'/'.$filename));
- $this->add_File($content, $zip_path.$filename);
- }
- }
- }
- }
-
- /**
- * Returns the Zip file
- *
- * @return string
- */
- function get_file() {
- $data = implode('', $this -> datasec);
- $ctrldir = implode('', $this -> ctrl_dir);
-
- return $data . $ctrldir . $this -> eof_ctrl_dir .
- pack('v', count($this->ctrl_dir)).pack('v', count($this->ctrl_dir)).
- pack('V', strlen($ctrldir)) . pack('V', strlen($data)) . "\x00\x00";
- }
-
- /**
- * @param string $name the name of the directory
- */
- function add_dir($name) {
- $name = str_replace("\\", "/", $name);
- $fr = "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00";
-
- $fr .= pack("V",0).pack("V",0).pack("V",0).pack("v", strlen($name) );
- $fr .= pack("v", 0 ).$name.pack("V", 0).pack("V", 0).pack("V", 0);
- $this -> datasec[] = $fr;
-
- $new_offset = strlen(implode("", $this->datasec));
-
- $cdrec = "\x50\x4b\x01\x02\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00";
- $cdrec .= pack("V",0).pack("V",0).pack("V",0).pack("v", strlen($name) );
- $cdrec .= pack("v", 0 ).pack("v", 0 ).pack("v", 0 ).pack("v", 0 );
- $ext = "\xff\xff\xff\xff";
- $cdrec .= pack("V", 16 ).pack("V", $this -> old_offset ).$name;
-
- $this -> ctrl_dir[] = $cdrec;
- $this -> old_offset = $new_offset;
- $this -> dirs[] = $name;
- }
-
- /**
- * Add a file named $name from a string $data
- *
- * @param string $data
- * @param string $name filename
- * @param bool $compact
- * @return bool
- */
- function add_File($data, $name, $compact = true) {
- $name = str_replace('\\', '/', $name);
- $dtime = dechex($this->DosTime());
-
- $hexdtime = pack('H*',$dtime[6].$dtime[7].
- $dtime[4].$dtime[5].
- $dtime[2].$dtime[3].
- $dtime[0].$dtime[1]);
-
- if($compact){
- $fr = "\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00".$hexdtime;
- }else{
- $fr = "\x50\x4b\x03\x04\x0a\x00\x00\x00\x00\x00".$hexdtime;
- }
- $unc_len = strlen($data);
- $crc = crc32($data);
-
- if($compact){
- $zdata = gzcompress($data);
- $c_len = strlen($zdata);
- $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);
- }else{
- $zdata = $data;
- }
- $c_len=strlen($zdata);
- $fr .= pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);
- $fr .= pack('v', strlen($name)).pack('v', 0).$name.$zdata;
-
- $fr .= pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);
-
- $this -> datasec[] = $fr;
- $new_offset = strlen(implode('', $this->datasec));
- if($compact) {
- $cdrec = "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00";
- } else {
- $cdrec = "\x50\x4b\x01\x02\x14\x00\x0a\x00\x00\x00\x00\x00";
- }
- $cdrec .= $hexdtime.pack('V', $crc).pack('V', $c_len).pack('V', $unc_len);
- $cdrec .= pack('v', strlen($name) ).pack('v', 0 ).pack('v', 0 );
- $cdrec .= pack('v', 0 ).pack('v', 0 ).pack('V', 32 );
- $cdrec .= pack('V', $this -> old_offset );
-
- $this -> old_offset = $new_offset;
- $cdrec .= $name;
- $this -> ctrl_dir[] = $cdrec;
- return true;
- }
-
- /**
- * @return int
- */
- function DosTime() {
- $timearray = getdate();
- if ($timearray['year'] < 1980) {
- $timearray['year'] = 1980;
- $timearray['mon'] = 1;
- $timearray['mday'] = 1;
- $timearray['hours'] = 0;
- $timearray['minutes'] = 0;
- $timearray['seconds'] = 0;
- }
- return (($timearray['year'] - 1980) << 25) |
- ($timearray['mon'] << 21) |
- ($timearray['mday'] << 16) |
- ($timearray['hours'] << 11) |
- ($timearray['minutes'] << 5) |
- ($timearray['seconds'] >> 1);
- }
-
- /**
- * Extract a zip file $zn to the $to directory
- *
- * @param string $zn filename
- * @param string $to filename path to file
- * @param array $index
- * @return array|int
- */
- function Extract ( $zn, $to, $index = Array(-1) ) {
- if(!@is_dir($to)) $this->_mkdir($to);
- $zip = @fopen($zn,'rb');
- if(!$zip) return(-1);
- $cdir = $this->ReadCentralDir($zip,$zn);
- $pos_entry = $cdir['offset'];
-
- if(!is_array($index)){
- $index = array($index);
- }
- for($i=0; isset($index[$i]);$i++){
- if(intval($index[$i])!=$index[$i]||$index[$i]>$cdir['entries'])
- return(-1);
- }
-
- $stat = array();
- for ($i=0; $i<$cdir['entries']; $i++) {
- @fseek($zip, $pos_entry);
- $header = $this->ReadCentralFileHeaders($zip);
- $header['index'] = $i;
- $pos_entry = ftell($zip);
- @rewind($zip);
- fseek($zip, $header['offset']);
- if(in_array("-1",$index)||in_array($i,$index)){
- $stat[$header['filename']]=$this->ExtractFile($header, $to, $zip);
- }
- }
- fclose($zip);
- return $stat;
- }
-
- /**
- * @param resource $zip
- * @param array $header
- * @return array
- */
- function ReadFileHeader($zip, $header) {
- $binary_data = fread($zip, 30);
- $data = unpack('vchk/vid/vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $binary_data);
-
- $header['filename'] = fread($zip, $data['filename_len']);
- if ($data['extra_len'] != 0) {
- $header['extra'] = fread($zip, $data['extra_len']);
- } else {
- $header['extra'] = '';
- }
-
- $header['compression'] = $data['compression'];
- foreach (array('size','compressed_size','crc') as $hd) { // On ODT files, these headers are 0. Keep the previous value.
- if ($data[$hd] != 0) $header[$hd] = $data[$hd];
- }
- $header['flag'] = $data['flag'];
- $header['mdate'] = $data['mdate'];
- $header['mtime'] = $data['mtime'];
-
- if ($header['mdate'] && $header['mtime']){
- $hour = ($header['mtime']&0xF800)>>11;
- $minute = ($header['mtime']&0x07E0)>>5;
- $seconde = ($header['mtime']&0x001F)*2;
- $year = (($header['mdate']&0xFE00)>>9)+1980;
- $month = ($header['mdate']&0x01E0)>>5;
- $day = $header['mdate']&0x001F;
- $header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
- } else {
- $header['mtime'] = time();
- }
-
- $header['stored_filename'] = $header['filename'];
- $header['status'] = "ok";
- return $header;
- }
-
- /**
- * @param resource $zip
- * @return array
- */
- function ReadCentralFileHeaders($zip){
- $binary_data = fread($zip, 46);
- $header = unpack('vchkid/vid/vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $binary_data);
-
- if ($header['filename_len'] != 0){
- $header['filename'] = fread($zip,$header['filename_len']);
- }else{
- $header['filename'] = '';
- }
-
- if ($header['extra_len'] != 0){
- $header['extra'] = fread($zip, $header['extra_len']);
- }else{
- $header['extra'] = '';
- }
-
- if ($header['comment_len'] != 0){
- $header['comment'] = fread($zip, $header['comment_len']);
- }else{
- $header['comment'] = '';
- }
-
- if ($header['mdate'] && $header['mtime']) {
- $hour = ($header['mtime'] & 0xF800) >> 11;
- $minute = ($header['mtime'] & 0x07E0) >> 5;
- $seconde = ($header['mtime'] & 0x001F)*2;
- $year = (($header['mdate'] & 0xFE00) >> 9) + 1980;
- $month = ($header['mdate'] & 0x01E0) >> 5;
- $day = $header['mdate'] & 0x001F;
- $header['mtime'] = mktime($hour, $minute, $seconde, $month, $day, $year);
- } else {
- $header['mtime'] = time();
- }
-
- $header['stored_filename'] = $header['filename'];
- $header['status'] = 'ok';
- if (substr($header['filename'], -1) == '/') $header['external'] = 0x41FF0010;
-
- return $header;
- }
-
- /**
- * @param resource $zip
- * @param string $zip_name filename path to file
- * @return array
- */
- function ReadCentralDir($zip,$zip_name) {
- $size = filesize($zip_name);
- if ($size < 277){
- $maximum_size = $size;
- } else {
- $maximum_size=277;
- }
-
- @fseek($zip, $size-$maximum_size);
- $pos = ftell($zip);
- $bytes = 0x00000000;
-
- while ($pos < $size) {
- $byte = @fread($zip, 1);
- $bytes=(($bytes << 8) & 0xFFFFFFFF) | Ord($byte);
- if ($bytes == 0x504b0506){
- $pos++;
- break;
- }
- $pos++;
- }
-
- $data=unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size',
- fread($zip, 18));
-
- $centd = array();
- if ($data['comment_size'] != 0){
- $centd['comment'] = fread($zip, $data['comment_size']);
- } else {
- $centd['comment'] = '';
- }
- $centd['entries'] = $data['entries'];
- $centd['disk_entries'] = $data['disk_entries'];
- $centd['offset'] = $data['offset'];
- $centd['disk_start'] = $data['disk_start'];
- $centd['size'] = $data['size'];
- $centd['disk'] = $data['disk'];
- return $centd;
- }
-
- /**
- * @param array $header
- * @param string $to filename path to file
- * @param resource $zip
- * @return bool|int
- */
- function ExtractFile($header,$to,$zip) {
- $header = $this->readfileheader($zip, $header);
-
- if(substr($to,-1)!="/") $to.="/";
- if(substr($header['filename'],-1)=="/") {
- $this->_mkdir($to.$header['filename']);
- return +2;
- }
-
- if (!$this->_mkdir($to.dirname($header['filename']))) return (-1);
-
- if (!array_key_exists("external", $header) || (!($header['external']==0x41FF0010)&&!($header['external']==16))) {
- if ($header['compression']==0) {
- $fp = @fopen($to.$header['filename'], 'wb');
- if(!$fp) return(-1);
- $size = $header['compressed_size'];
-
- while ($size != 0) {
- $read_size = ($size < 2048 ? $size : 2048);
- $buffer = fread($zip, $read_size);
- $binary_data = pack('a'.$read_size, $buffer);
- @fwrite($fp, $binary_data, $read_size);
- $size -= $read_size;
- }
- fclose($fp);
- touch($to.$header['filename'], $header['mtime']);
-
- }else{
- if (!is_dir(dirname($to.$header['filename']))) $this->_mkdir(dirname($to.$header['filename']));
- $fp = fopen($to.$header['filename'].'.gz','wb');
- if(!$fp) return(-1);
- $binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($header['compression']),
- Chr(0x00), time(), Chr(0x00), Chr(3));
-
- fwrite($fp, $binary_data, 10);
- $size = $header['compressed_size'];
-
- while ($size != 0) {
- $read_size = ($size < 1024 ? $size : 1024);
- $buffer = fread($zip, $read_size);
- $binary_data = pack('a'.$read_size, $buffer);
- @fwrite($fp, $binary_data, $read_size);
- $size -= $read_size;
- }
-
- $binary_data = pack('VV', $header['crc'], $header['size']);
- fwrite($fp, $binary_data,8);
- fclose($fp);
-
- $gzp = @gzopen($to.$header['filename'].'.gz','rb');
- if(!$gzp){
- @gzclose($gzp);
- @unlink($to.$header['filename']);
- die("Archive is compressed whereas ZLIB is not enabled.");
- }
- $fp = @fopen($to.$header['filename'],'wb');
- if(!$fp) return(-1);
- $size = $header['size'];
-
- while ($size != 0) {
- $read_size = ($size < 2048 ? $size : 2048);
- $buffer = gzread($gzp, $read_size);
- $binary_data = pack('a'.$read_size, $buffer);
- @fwrite($fp, $binary_data, $read_size);
- $size -= $read_size;
- }
- fclose($fp);
- gzclose($gzp);
-
- touch($to.$header['filename'], $header['mtime']);
- @unlink($to.$header['filename'].'.gz');
- }
- }
- return true;
- }
-
- /**
- * centralize mkdir calls and use dokuwiki io functions
- *
- * @author Christopher Smith
- *
- * @param string $d filename path to file
- * @return bool|int|string
- */
- function _mkdir($d) {
- return io_mkdir_p($d);
- }
-
- /**
- * @param string $zn
- * @param string $name
- * @return null|string
- */
- function ExtractStr($zn, $name) {
- $zip = @fopen($zn,'rb');
- if(!$zip) return(null);
- $cdir = $this->ReadCentralDir($zip,$zn);
- $pos_entry = $cdir['offset'];
-
- for ($i=0; $i<$cdir['entries']; $i++) {
- @fseek($zip, $pos_entry);
- $header = $this->ReadCentralFileHeaders($zip);
- $header['index'] = $i;
- $pos_entry = ftell($zip);
- @rewind($zip);
- fseek($zip, $header['offset']);
- if ($name == $header['stored_filename'] || $name == $header['filename']) {
- $str = $this->ExtractStrFile($header, $zip);
- fclose($zip);
- return $str;
- }
-
- }
- fclose($zip);
- return null;
- }
-
- /**
- * @param array $header
- * @param resource $zip
- * @return null|string
- */
- function ExtractStrFile($header,$zip) {
- $hdr = $this->readfileheader($zip, $header);
- $binary_data = '';
- if (!($header['external']==0x41FF0010) && !($header['external']==16)) {
- if ($header['compression']==0) {
- while ($size != 0) {
- $read_size = ($size < 2048 ? $size : 2048);
- $buffer = fread($zip, $read_size);
- $binary_data .= pack('a'.$read_size, $buffer);
- $size -= $read_size;
- }
- return $binary_data;
- } else {
- $size = $header['compressed_size'];
- if ($size == 0) {
- return '';
- }
- //Just in case
- if ($size > ($this->_ret_bytes(ini_get('memory_limit'))/2)) {
- die("Compressed file is to huge to be uncompress in memory.");
- }
- while ($size != 0)
- {
- $read_size = ($size < 2048 ? $size : 2048);
- $buffer = fread($zip, $read_size);
- $binary_data .= pack('a'.$read_size, $buffer);
- $size -= $read_size;
- }
- $str = gzinflate($binary_data, $header['size']);
- if ($header['crc'] == crc32($str)) {
- return $str;
- } else {
- die("Crc Error");
- }
- }
- }
- return null;
- }
-
- /**
- * @param string $val
- * @return int|string
- */
- function _ret_bytes($val) {
- $val = trim($val);
- $last = $val{strlen($val)-1};
- switch($last) {
- case 'k':
- case 'K':
- return (int) $val * 1024;
- break;
- case 'm':
- case 'M':
- return (int) $val * 1048576;
- break;
- default:
- return $val;
- }
- }
-}
-
diff --git a/sources/inc/actions.php b/sources/inc/actions.php
deleted file mode 100644
index adba2aa..0000000
--- a/sources/inc/actions.php
+++ /dev/null
@@ -1,861 +0,0 @@
-
- */
-
-if(!defined('DOKU_INC')) die('meh.');
-
-/**
- * Call the needed action handlers
- *
- * @author Andreas Gohr
- * @triggers ACTION_ACT_PREPROCESS
- * @triggers ACTION_HEADERS_SEND
- */
-function act_dispatch(){
- global $ACT;
- global $ID;
- global $INFO;
- global $QUERY;
- /* @var Input $INPUT */
- global $INPUT;
- global $lang;
- global $conf;
-
- $preact = $ACT;
-
- // give plugins an opportunity to process the action
- $evt = new Doku_Event('ACTION_ACT_PREPROCESS',$ACT);
-
- $headers = array();
- if ($evt->advise_before()) {
-
- //sanitize $ACT
- $ACT = act_validate($ACT);
-
- //check if searchword was given - else just show
- $s = cleanID($QUERY);
- if($ACT == 'search' && empty($s)){
- $ACT = 'show';
- }
-
- //login stuff
- if(in_array($ACT,array('login','logout'))){
- $ACT = act_auth($ACT);
- }
-
- //check if user is asking to (un)subscribe a page
- if($ACT == 'subscribe') {
- try {
- $ACT = act_subscription($ACT);
- } catch (Exception $e) {
- msg($e->getMessage(), -1);
- }
- }
-
- //display some info
- if($ACT == 'check'){
- check();
- $ACT = 'show';
- }
-
- //check permissions
- $ACT = act_permcheck($ACT);
-
- //sitemap
- if ($ACT == 'sitemap'){
- act_sitemap($ACT);
- }
-
- //recent changes
- if ($ACT == 'recent'){
- $show_changes = $INPUT->str('show_changes');
- if (!empty($show_changes)) {
- set_doku_pref('show_changes', $show_changes);
- }
- }
-
- //diff
- if ($ACT == 'diff'){
- $difftype = $INPUT->str('difftype');
- if (!empty($difftype)) {
- set_doku_pref('difftype', $difftype);
- }
- }
-
- //register
- if($ACT == 'register' && $INPUT->post->bool('save') && register()){
- $ACT = 'login';
- }
-
- if ($ACT == 'resendpwd' && act_resendpwd()) {
- $ACT = 'login';
- }
-
- // user profile changes
- if (in_array($ACT, array('profile','profile_delete'))) {
- if(!$INPUT->server->str('REMOTE_USER')) {
- $ACT = 'login';
- } else {
- switch ($ACT) {
- case 'profile' :
- if(updateprofile()) {
- msg($lang['profchanged'],1);
- $ACT = 'show';
- }
- break;
- case 'profile_delete' :
- if(auth_deleteprofile()){
- msg($lang['profdeleted'],1);
- $ACT = 'show';
- } else {
- $ACT = 'profile';
- }
- break;
- }
- }
- }
-
- //revert
- if($ACT == 'revert'){
- if(checkSecurityToken()){
- $ACT = act_revert($ACT);
- }else{
- $ACT = 'show';
- }
- }
-
- //save
- if($ACT == 'save'){
- if(checkSecurityToken()){
- $ACT = act_save($ACT);
- }else{
- $ACT = 'preview';
- }
- }
-
- //cancel conflicting edit
- if($ACT == 'cancel')
- $ACT = 'show';
-
- //draft deletion
- if($ACT == 'draftdel')
- $ACT = act_draftdel($ACT);
-
- //draft saving on preview
- if($ACT == 'preview') {
- $headers[] = "X-XSS-Protection: 0";
- $ACT = act_draftsave($ACT);
- }
-
- //edit
- if(in_array($ACT, array('edit', 'preview', 'recover'))) {
- $ACT = act_edit($ACT);
- }else{
- unlock($ID); //try to unlock
- }
-
- //handle export
- if(substr($ACT,0,7) == 'export_')
- $ACT = act_export($ACT);
-
- //handle admin tasks
- if($ACT == 'admin'){
- // retrieve admin plugin name from $_REQUEST['page']
- if (($page = $INPUT->str('page', '', true)) != '') {
- /** @var $plugin DokuWiki_Admin_Plugin */
- if ($plugin = plugin_getRequestAdminPlugin()){
- $plugin->handle();
- }
- }
- }
-
- // check permissions again - the action may have changed
- $ACT = act_permcheck($ACT);
- } // end event ACTION_ACT_PREPROCESS default action
- $evt->advise_after();
- // Make sure plugs can handle 'denied'
- if($conf['send404'] && $ACT == 'denied') {
- http_status(403);
- }
- unset($evt);
-
- // when action 'show', the intial not 'show' and POST, do a redirect
- if($ACT == 'show' && $preact != 'show' && strtolower($INPUT->server->str('REQUEST_METHOD')) == 'post'){
- act_redirect($ID,$preact);
- }
-
- global $INFO;
- global $conf;
- global $license;
-
- //call template FIXME: all needed vars available?
- $headers[] = 'Content-Type: text/html; charset=utf-8';
- trigger_event('ACTION_HEADERS_SEND',$headers,'act_sendheaders');
-
- include(template('main.php'));
- // output for the commands is now handled in inc/templates.php
- // in function tpl_content()
-}
-
-/**
- * Send the given headers using header()
- *
- * @param array $headers The headers that shall be sent
- */
-function act_sendheaders($headers) {
- foreach ($headers as $hdr) header($hdr);
-}
-
-/**
- * Sanitize the action command
- *
- * @author Andreas Gohr
- *
- * @param array|string $act
- * @return string
- */
-function act_clean($act){
- // check if the action was given as array key
- if(is_array($act)){
- list($act) = array_keys($act);
- }
-
- //remove all bad chars
- $act = strtolower($act);
- $act = preg_replace('/[^1-9a-z_]+/','',$act);
-
- if($act == 'export_html') $act = 'export_xhtml';
- if($act == 'export_htmlbody') $act = 'export_xhtmlbody';
-
- if($act === '') $act = 'show';
- return $act;
-}
-
-/**
- * Sanitize and validate action commands.
- *
- * Add all allowed commands here.
- *
- * @author Andreas Gohr
- *
- * @param array|string $act
- * @return string
- */
-function act_validate($act) {
- global $conf;
- global $INFO;
-
- $act = act_clean($act);
-
- // check if action is disabled
- if(!actionOK($act)){
- msg('Command disabled: '.htmlspecialchars($act),-1);
- return 'show';
- }
-
- //disable all acl related commands if ACL is disabled
- if(!$conf['useacl'] && in_array($act,array('login','logout','register','admin',
- 'subscribe','unsubscribe','profile','revert',
- 'resendpwd','profile_delete'))){
- msg('Command unavailable: '.htmlspecialchars($act),-1);
- return 'show';
- }
-
- //is there really a draft?
- if($act == 'draft' && !file_exists($INFO['draft'])) return 'edit';
-
- if(!in_array($act,array('login','logout','register','save','cancel','edit','draft',
- 'preview','search','show','check','index','revisions',
- 'diff','recent','backlink','admin','subscribe','revert',
- 'unsubscribe','profile','profile_delete','resendpwd','recover',
- 'draftdel','sitemap','media')) && substr($act,0,7) != 'export_' ) {
- msg('Command unknown: '.htmlspecialchars($act),-1);
- return 'show';
- }
- return $act;
-}
-
-/**
- * Run permissionchecks
- *
- * @author Andreas Gohr
- *
- * @param string $act action command
- * @return string action command
- */
-function act_permcheck($act){
- global $INFO;
-
- if(in_array($act,array('save','preview','edit','recover'))){
- if($INFO['exists']){
- if($act == 'edit'){
- //the edit function will check again and do a source show
- //when no AUTH_EDIT available
- $permneed = AUTH_READ;
- }else{
- $permneed = AUTH_EDIT;
- }
- }else{
- $permneed = AUTH_CREATE;
- }
- }elseif(in_array($act,array('login','search','recent','profile','profile_delete','index', 'sitemap'))){
- $permneed = AUTH_NONE;
- }elseif($act == 'revert'){
- $permneed = AUTH_ADMIN;
- if($INFO['ismanager']) $permneed = AUTH_EDIT;
- }elseif($act == 'register'){
- $permneed = AUTH_NONE;
- }elseif($act == 'resendpwd'){
- $permneed = AUTH_NONE;
- }elseif($act == 'admin'){
- if($INFO['ismanager']){
- // if the manager has the needed permissions for a certain admin
- // action is checked later
- $permneed = AUTH_READ;
- }else{
- $permneed = AUTH_ADMIN;
- }
- }else{
- $permneed = AUTH_READ;
- }
- if($INFO['perm'] >= $permneed) return $act;
-
- return 'denied';
-}
-
-/**
- * Handle 'draftdel'
- *
- * Deletes the draft for the current page and user
- *
- * @param string $act action command
- * @return string action command
- */
-function act_draftdel($act){
- global $INFO;
- @unlink($INFO['draft']);
- $INFO['draft'] = null;
- return 'show';
-}
-
-/**
- * Saves a draft on preview
- *
- * @todo this currently duplicates code from ajax.php :-/
- *
- * @param string $act action command
- * @return string action command
- */
-function act_draftsave($act){
- global $INFO;
- global $ID;
- global $INPUT;
- global $conf;
- if($conf['usedraft'] && $INPUT->post->has('wikitext')) {
- $draft = array('id' => $ID,
- 'prefix' => substr($INPUT->post->str('prefix'), 0, -1),
- 'text' => $INPUT->post->str('wikitext'),
- 'suffix' => $INPUT->post->str('suffix'),
- 'date' => $INPUT->post->int('date'),
- 'client' => $INFO['client'],
- );
- $cname = getCacheName($draft['client'].$ID,'.draft');
- if(io_saveFile($cname,serialize($draft))){
- $INFO['draft'] = $cname;
- }
- }
- return $act;
-}
-
-/**
- * Handle 'save'
- *
- * Checks for spam and conflicts and saves the page.
- * Does a redirect to show the page afterwards or
- * returns a new action.
- *
- * @author Andreas Gohr
- *
- * @param string $act action command
- * @return string action command
- */
-function act_save($act){
- global $ID;
- global $DATE;
- global $PRE;
- global $TEXT;
- global $SUF;
- global $SUM;
- global $lang;
- global $INFO;
- global $INPUT;
-
- //spam check
- if(checkwordblock()) {
- msg($lang['wordblock'], -1);
- return 'edit';
- }
- //conflict check
- if($DATE != 0 && $INFO['meta']['date']['modified'] > $DATE )
- return 'conflict';
-
- //save it
- saveWikiText($ID,con($PRE,$TEXT,$SUF,true),$SUM,$INPUT->bool('minor')); //use pretty mode for con
- //unlock it
- unlock($ID);
-
- //delete draft
- act_draftdel($act);
- session_write_close();
-
- // when done, show page
- return 'show';
-}
-
-/**
- * Revert to a certain revision
- *
- * @author Andreas Gohr
- *
- * @param string $act action command
- * @return string action command
- */
-function act_revert($act){
- global $ID;
- global $REV;
- global $lang;
- /* @var Input $INPUT */
- global $INPUT;
- // FIXME $INFO['writable'] currently refers to the attic version
- // global $INFO;
- // if (!$INFO['writable']) {
- // return 'show';
- // }
-
- // when no revision is given, delete current one
- // FIXME this feature is not exposed in the GUI currently
- $text = '';
- $sum = $lang['deleted'];
- if($REV){
- $text = rawWiki($ID,$REV);
- if(!$text) return 'show'; //something went wrong
- $sum = sprintf($lang['restored'], dformat($REV));
- }
-
- // spam check
-
- if (checkwordblock($text)) {
- msg($lang['wordblock'], -1);
- return 'edit';
- }
-
- saveWikiText($ID,$text,$sum,false);
- msg($sum,1);
-
- //delete any draft
- act_draftdel($act);
- session_write_close();
-
- // when done, show current page
- $INPUT->server->set('REQUEST_METHOD','post'); //should force a redirect
- $REV = '';
- return 'show';
-}
-
-/**
- * Do a redirect after receiving post data
- *
- * Tries to add the section id as hash mark after section editing
- *
- * @param string $id page id
- * @param string $preact action command before redirect
- */
-function act_redirect($id,$preact){
- global $PRE;
- global $TEXT;
-
- $opts = array(
- 'id' => $id,
- 'preact' => $preact
- );
- //get section name when coming from section edit
- if($PRE && preg_match('/^\s*==+([^=\n]+)/',$TEXT,$match)){
- $check = false; //Byref
- $opts['fragment'] = sectionID($match[0], $check);
- }
-
- trigger_event('ACTION_SHOW_REDIRECT',$opts,'act_redirect_execute');
-}
-
-/**
- * Execute the redirect
- *
- * @param array $opts id and fragment for the redirect and the preact
- */
-function act_redirect_execute($opts){
- $go = wl($opts['id'],'',true);
- if(isset($opts['fragment'])) $go .= '#'.$opts['fragment'];
-
- //show it
- send_redirect($go);
-}
-
-/**
- * Handle 'login', 'logout'
- *
- * @author Andreas Gohr
- *
- * @param string $act action command
- * @return string action command
- */
-function act_auth($act){
- global $ID;
- global $INFO;
- /* @var Input $INPUT */
- global $INPUT;
-
- //already logged in?
- if($INPUT->server->has('REMOTE_USER') && $act=='login'){
- return 'show';
- }
-
- //handle logout
- if($act=='logout'){
- $lockedby = checklock($ID); //page still locked?
- if($lockedby == $INPUT->server->str('REMOTE_USER')){
- unlock($ID); //try to unlock
- }
-
- // do the logout stuff
- auth_logoff();
-
- // rebuild info array
- $INFO = pageinfo();
-
- act_redirect($ID,'login');
- }
-
- return $act;
-}
-
-/**
- * Handle 'edit', 'preview', 'recover'
- *
- * @author Andreas Gohr
- *
- * @param string $act action command
- * @return string action command
- */
-function act_edit($act){
- global $ID;
- global $INFO;
-
- global $TEXT;
- global $RANGE;
- global $PRE;
- global $SUF;
- global $REV;
- global $SUM;
- global $lang;
- global $DATE;
-
- if (!isset($TEXT)) {
- if ($INFO['exists']) {
- if ($RANGE) {
- list($PRE,$TEXT,$SUF) = rawWikiSlices($RANGE,$ID,$REV);
- } else {
- $TEXT = rawWiki($ID,$REV);
- }
- } else {
- $TEXT = pageTemplate($ID);
- }
- }
-
- //set summary default
- if(!$SUM){
- if($REV){
- $SUM = sprintf($lang['restored'], dformat($REV));
- }elseif(!$INFO['exists']){
- $SUM = $lang['created'];
- }
- }
-
- // Use the date of the newest revision, not of the revision we edit
- // This is used for conflict detection
- if(!$DATE) $DATE = @filemtime(wikiFN($ID));
-
- //check if locked by anyone - if not lock for my self
- //do not lock when the user can't edit anyway
- if ($INFO['writable']) {
- $lockedby = checklock($ID);
- if($lockedby) return 'locked';
-
- lock($ID);
- }
-
- return $act;
-}
-
-/**
- * Export a wiki page for various formats
- *
- * Triggers ACTION_EXPORT_POSTPROCESS
- *
- * Event data:
- * data['id'] -- page id
- * data['mode'] -- requested export mode
- * data['headers'] -- export headers
- * data['output'] -- export output
- *
- * @author Andreas Gohr
- * @author Michael Klier
- *
- * @param string $act action command
- * @return string action command
- */
-function act_export($act){
- global $ID;
- global $REV;
- global $conf;
- global $lang;
-
- $pre = '';
- $post = '';
- $headers = array();
-
- // search engines: never cache exported docs! (Google only currently)
- $headers['X-Robots-Tag'] = 'noindex';
-
- $mode = substr($act,7);
- switch($mode) {
- case 'raw':
- $headers['Content-Type'] = 'text/plain; charset=utf-8';
- $headers['Content-Disposition'] = 'attachment; filename='.noNS($ID).'.txt';
- $output = rawWiki($ID,$REV);
- break;
- case 'xhtml':
- $pre .= '' . DOKU_LF;
- $pre .= '' . DOKU_LF;
- $pre .= '' . DOKU_LF;
- $pre .= ' ' . DOKU_LF;
- $pre .= ' '.$ID.'' . DOKU_LF;
-
- // get metaheaders
- ob_start();
- tpl_metaheaders();
- $pre .= ob_get_clean();
-
- $pre .= '' . DOKU_LF;
- $pre .= '' . DOKU_LF;
- $pre .= '' . DOKU_LF;
-
- // get toc
- $pre .= tpl_toc(true);
-
- $headers['Content-Type'] = 'text/html; charset=utf-8';
- $output = p_wiki_xhtml($ID,$REV,false);
-
- $post .= '
' . DOKU_LF;
- $post .= '' . DOKU_LF;
- $post .= '' . DOKU_LF;
- break;
- case 'xhtmlbody':
- $headers['Content-Type'] = 'text/html; charset=utf-8';
- $output = p_wiki_xhtml($ID,$REV,false);
- break;
- default:
- $output = p_cached_output(wikiFN($ID,$REV), $mode, $ID);
- $headers = p_get_metadata($ID,"format $mode");
- break;
- }
-
- // prepare event data
- $data = array();
- $data['id'] = $ID;
- $data['mode'] = $mode;
- $data['headers'] = $headers;
- $data['output'] =& $output;
-
- trigger_event('ACTION_EXPORT_POSTPROCESS', $data);
-
- if(!empty($data['output'])){
- if(is_array($data['headers'])) foreach($data['headers'] as $key => $val){
- header("$key: $val");
- }
- print $pre.$data['output'].$post;
- exit;
- }
- return 'show';
-}
-
-/**
- * Handle sitemap delivery
- *
- * @author Michael Hamann
- *
- * @param string $act action command
- */
-function act_sitemap($act) {
- global $conf;
-
- if ($conf['sitemap'] < 1 || !is_numeric($conf['sitemap'])) {
- http_status(404);
- print "Sitemap generation is disabled.";
- exit;
- }
-
- $sitemap = Sitemapper::getFilePath();
- if (Sitemapper::sitemapIsCompressed()) {
- $mime = 'application/x-gzip';
- }else{
- $mime = 'application/xml; charset=utf-8';
- }
-
- // Check if sitemap file exists, otherwise create it
- if (!is_readable($sitemap)) {
- Sitemapper::generate();
- }
-
- if (is_readable($sitemap)) {
- // Send headers
- header('Content-Type: '.$mime);
- header('Content-Disposition: attachment; filename='.utf8_basename($sitemap));
-
- http_conditionalRequest(filemtime($sitemap));
-
- // Send file
- //use x-sendfile header to pass the delivery to compatible webservers
- http_sendfile($sitemap);
-
- readfile($sitemap);
- exit;
- }
-
- http_status(500);
- print "Could not read the sitemap file - bad permissions?";
- exit;
-}
-
-/**
- * Handle page 'subscribe'
- *
- * Throws exception on error.
- *
- * @author Adrian Lang
- *
- * @param string $act action command
- * @return string action command
- * @throws Exception if (un)subscribing fails
- */
-function act_subscription($act){
- global $lang;
- global $INFO;
- global $ID;
- /* @var Input $INPUT */
- global $INPUT;
-
- // subcriptions work for logged in users only
- if(!$INPUT->server->str('REMOTE_USER')) return 'show';
-
- // get and preprocess data.
- $params = array();
- foreach(array('target', 'style', 'action') as $param) {
- if ($INPUT->has("sub_$param")) {
- $params[$param] = $INPUT->str("sub_$param");
- }
- }
-
- // any action given? if not just return and show the subscription page
- if(empty($params['action']) || !checkSecurityToken()) return $act;
-
- // Handle POST data, may throw exception.
- trigger_event('ACTION_HANDLE_SUBSCRIBE', $params, 'subscription_handle_post');
-
- $target = $params['target'];
- $style = $params['style'];
- $action = $params['action'];
-
- // Perform action.
- $sub = new Subscription();
- if($action == 'unsubscribe'){
- $ok = $sub->remove($target, $INPUT->server->str('REMOTE_USER'), $style);
- }else{
- $ok = $sub->add($target, $INPUT->server->str('REMOTE_USER'), $style);
- }
-
- if($ok) {
- msg(sprintf($lang["subscr_{$action}_success"], hsc($INFO['userinfo']['name']),
- prettyprint_id($target)), 1);
- act_redirect($ID, $act);
- } else {
- throw new Exception(sprintf($lang["subscr_{$action}_error"],
- hsc($INFO['userinfo']['name']),
- prettyprint_id($target)));
- }
-
- // Assure that we have valid data if act_redirect somehow fails.
- $INFO['subscribed'] = $sub->user_subscription();
- return 'show';
-}
-
-/**
- * Validate POST data
- *
- * Validates POST data for a subscribe or unsubscribe request. This is the
- * default action for the event ACTION_HANDLE_SUBSCRIBE.
- *
- * @author Adrian Lang
- *
- * @param array &$params the parameters: target, style and action
- * @throws Exception
- */
-function subscription_handle_post(&$params) {
- global $INFO;
- global $lang;
- /* @var Input $INPUT */
- global $INPUT;
-
- // Get and validate parameters.
- if (!isset($params['target'])) {
- throw new Exception('no subscription target given');
- }
- $target = $params['target'];
- $valid_styles = array('every', 'digest');
- if (substr($target, -1, 1) === ':') {
- // Allow “list” subscribe style since the target is a namespace.
- $valid_styles[] = 'list';
- }
- $style = valid_input_set('style', $valid_styles, $params,
- 'invalid subscription style given');
- $action = valid_input_set('action', array('subscribe', 'unsubscribe'),
- $params, 'invalid subscription action given');
-
- // Check other conditions.
- if ($action === 'subscribe') {
- if ($INFO['userinfo']['mail'] === '') {
- throw new Exception($lang['subscr_subscribe_noaddress']);
- }
- } elseif ($action === 'unsubscribe') {
- $is = false;
- foreach($INFO['subscribed'] as $subscr) {
- if ($subscr['target'] === $target) {
- $is = true;
- }
- }
- if ($is === false) {
- throw new Exception(sprintf($lang['subscr_not_subscribed'],
- $INPUT->server->str('REMOTE_USER'),
- prettyprint_id($target)));
- }
- // subscription_set deletes a subscription if style = null.
- $style = null;
- }
-
- $params = compact('target', 'style', 'action');
-}
-
-//Setup VIM: ex: et ts=2 :
diff --git a/sources/inc/auth.php b/sources/inc/auth.php
deleted file mode 100644
index b7bee21..0000000
--- a/sources/inc/auth.php
+++ /dev/null
@@ -1,1332 +0,0 @@
-
- */
-
-if(!defined('DOKU_INC')) die('meh.');
-
-// some ACL level defines
-define('AUTH_NONE', 0);
-define('AUTH_READ', 1);
-define('AUTH_EDIT', 2);
-define('AUTH_CREATE', 4);
-define('AUTH_UPLOAD', 8);
-define('AUTH_DELETE', 16);
-define('AUTH_ADMIN', 255);
-
-/**
- * Initialize the auth system.
- *
- * This function is automatically called at the end of init.php
- *
- * This used to be the main() of the auth.php
- *
- * @todo backend loading maybe should be handled by the class autoloader
- * @todo maybe split into multiple functions at the XXX marked positions
- * @triggers AUTH_LOGIN_CHECK
- * @return bool
- */
-function auth_setup() {
- global $conf;
- /* @var DokuWiki_Auth_Plugin $auth */
- global $auth;
- /* @var Input $INPUT */
- global $INPUT;
- global $AUTH_ACL;
- global $lang;
- /* @var Doku_Plugin_Controller $plugin_controller */
- global $plugin_controller;
- $AUTH_ACL = array();
-
- if(!$conf['useacl']) return false;
-
- // try to load auth backend from plugins
- foreach ($plugin_controller->getList('auth') as $plugin) {
- if ($conf['authtype'] === $plugin) {
- $auth = $plugin_controller->load('auth', $plugin);
- break;
- }
- }
-
- if(!isset($auth) || !$auth){
- msg($lang['authtempfail'], -1);
- return false;
- }
-
- if ($auth->success == false) {
- // degrade to unauthenticated user
- unset($auth);
- auth_logoff();
- msg($lang['authtempfail'], -1);
- return false;
- }
-
- // do the login either by cookie or provided credentials XXX
- $INPUT->set('http_credentials', false);
- if(!$conf['rememberme']) $INPUT->set('r', false);
-
- // handle renamed HTTP_AUTHORIZATION variable (can happen when a fix like
- // the one presented at
- // http://www.besthostratings.com/articles/http-auth-php-cgi.html is used
- // for enabling HTTP authentication with CGI/SuExec)
- if(isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']))
- $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
- // streamline HTTP auth credentials (IIS/rewrite -> mod_php)
- if(isset($_SERVER['HTTP_AUTHORIZATION'])) {
- list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
- explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
- }
-
- // if no credentials were given try to use HTTP auth (for SSO)
- if(!$INPUT->str('u') && empty($_COOKIE[DOKU_COOKIE]) && !empty($_SERVER['PHP_AUTH_USER'])) {
- $INPUT->set('u', $_SERVER['PHP_AUTH_USER']);
- $INPUT->set('p', $_SERVER['PHP_AUTH_PW']);
- $INPUT->set('http_credentials', true);
- }
-
- // apply cleaning (auth specific user names, remove control chars)
- if (true === $auth->success) {
- $INPUT->set('u', $auth->cleanUser(stripctl($INPUT->str('u'))));
- $INPUT->set('p', stripctl($INPUT->str('p')));
- }
-
- if(!is_null($auth) && $auth->canDo('external')) {
- // external trust mechanism in place
- $auth->trustExternal($INPUT->str('u'), $INPUT->str('p'), $INPUT->bool('r'));
- } else {
- $evdata = array(
- 'user' => $INPUT->str('u'),
- 'password' => $INPUT->str('p'),
- 'sticky' => $INPUT->bool('r'),
- 'silent' => $INPUT->bool('http_credentials')
- );
- trigger_event('AUTH_LOGIN_CHECK', $evdata, 'auth_login_wrapper');
- }
-
- //load ACL into a global array XXX
- $AUTH_ACL = auth_loadACL();
-
- return true;
-}
-
-/**
- * Loads the ACL setup and handle user wildcards
- *
- * @author Andreas Gohr
- *
- * @return array
- */
-function auth_loadACL() {
- global $config_cascade;
- global $USERINFO;
- /* @var Input $INPUT */
- global $INPUT;
-
- if(!is_readable($config_cascade['acl']['default'])) return array();
-
- $acl = file($config_cascade['acl']['default']);
-
- $out = array();
- foreach($acl as $line) {
- $line = trim($line);
- if(empty($line) || ($line{0} == '#')) continue; // skip blank lines & comments
- list($id,$rest) = preg_split('/[ \t]+/',$line,2);
-
- // substitute user wildcard first (its 1:1)
- if(strstr($line, '%USER%')){
- // if user is not logged in, this ACL line is meaningless - skip it
- if (!$INPUT->server->has('REMOTE_USER')) continue;
-
- $id = str_replace('%USER%',cleanID($INPUT->server->str('REMOTE_USER')),$id);
- $rest = str_replace('%USER%',auth_nameencode($INPUT->server->str('REMOTE_USER')),$rest);
- }
-
- // substitute group wildcard (its 1:m)
- if(strstr($line, '%GROUP%')){
- // if user is not logged in, grps is empty, no output will be added (i.e. skipped)
- foreach((array) $USERINFO['grps'] as $grp){
- $nid = str_replace('%GROUP%',cleanID($grp),$id);
- $nrest = str_replace('%GROUP%','@'.auth_nameencode($grp),$rest);
- $out[] = "$nid\t$nrest";
- }
- } else {
- $out[] = "$id\t$rest";
- }
- }
-
- return $out;
-}
-
-/**
- * Event hook callback for AUTH_LOGIN_CHECK
- *
- * @param array $evdata
- * @return bool
- */
-function auth_login_wrapper($evdata) {
- return auth_login(
- $evdata['user'],
- $evdata['password'],
- $evdata['sticky'],
- $evdata['silent']
- );
-}
-
-/**
- * This tries to login the user based on the sent auth credentials
- *
- * The authentication works like this: if a username was given
- * a new login is assumed and user/password are checked. If they
- * are correct the password is encrypted with blowfish and stored
- * together with the username in a cookie - the same info is stored
- * in the session, too. Additonally a browserID is stored in the
- * session.
- *
- * If no username was given the cookie is checked: if the username,
- * crypted password and browserID match between session and cookie
- * no further testing is done and the user is accepted
- *
- * If a cookie was found but no session info was availabe the
- * blowfish encrypted password from the cookie is decrypted and
- * together with username rechecked by calling this function again.
- *
- * On a successful login $_SERVER[REMOTE_USER] and $USERINFO
- * are set.
- *
- * @author Andreas Gohr
- *
- * @param string $user Username
- * @param string $pass Cleartext Password
- * @param bool $sticky Cookie should not expire
- * @param bool $silent Don't show error on bad auth
- * @return bool true on successful auth
- */
-function auth_login($user, $pass, $sticky = false, $silent = false) {
- global $USERINFO;
- global $conf;
- global $lang;
- /* @var DokuWiki_Auth_Plugin $auth */
- global $auth;
- /* @var Input $INPUT */
- global $INPUT;
-
- $sticky ? $sticky = true : $sticky = false; //sanity check
-
- if(!$auth) return false;
-
- if(!empty($user)) {
- //usual login
- if(!empty($pass) && $auth->checkPass($user, $pass)) {
- // make logininfo globally available
- $INPUT->server->set('REMOTE_USER', $user);
- $secret = auth_cookiesalt(!$sticky, true); //bind non-sticky to session
- auth_setCookie($user, auth_encrypt($pass, $secret), $sticky);
- return true;
- } else {
- //invalid credentials - log off
- if(!$silent) msg($lang['badlogin'], -1);
- auth_logoff();
- return false;
- }
- } else {
- // read cookie information
- list($user, $sticky, $pass) = auth_getCookie();
- if($user && $pass) {
- // we got a cookie - see if we can trust it
-
- // get session info
- $session = $_SESSION[DOKU_COOKIE]['auth'];
- if(isset($session) &&
- $auth->useSessionCache($user) &&
- ($session['time'] >= time() - $conf['auth_security_timeout']) &&
- ($session['user'] == $user) &&
- ($session['pass'] == sha1($pass)) && //still crypted
- ($session['buid'] == auth_browseruid())
- ) {
-
- // he has session, cookie and browser right - let him in
- $INPUT->server->set('REMOTE_USER', $user);
- $USERINFO = $session['info']; //FIXME move all references to session
- return true;
- }
- // no we don't trust it yet - recheck pass but silent
- $secret = auth_cookiesalt(!$sticky, true); //bind non-sticky to session
- $pass = auth_decrypt($pass, $secret);
- return auth_login($user, $pass, $sticky, true);
- }
- }
- //just to be sure
- auth_logoff(true);
- return false;
-}
-
-/**
- * Builds a pseudo UID from browser and IP data
- *
- * This is neither unique nor unfakable - still it adds some
- * security. Using the first part of the IP makes sure
- * proxy farms like AOLs are still okay.
- *
- * @author Andreas Gohr
- *
- * @return string a MD5 sum of various browser headers
- */
-function auth_browseruid() {
- /* @var Input $INPUT */
- global $INPUT;
-
- $ip = clientIP(true);
- $uid = '';
- $uid .= $INPUT->server->str('HTTP_USER_AGENT');
- $uid .= $INPUT->server->str('HTTP_ACCEPT_CHARSET');
- $uid .= substr($ip, 0, strpos($ip, '.'));
- $uid = strtolower($uid);
- return md5($uid);
-}
-
-/**
- * Creates a random key to encrypt the password in cookies
- *
- * This function tries to read the password for encrypting
- * cookies from $conf['metadir'].'/_htcookiesalt'
- * if no such file is found a random key is created and
- * and stored in this file.
- *
- * @author Andreas Gohr
- *
- * @param bool $addsession if true, the sessionid is added to the salt
- * @param bool $secure if security is more important than keeping the old value
- * @return string
- */
-function auth_cookiesalt($addsession = false, $secure = false) {
- global $conf;
- $file = $conf['metadir'].'/_htcookiesalt';
- if ($secure || !file_exists($file)) {
- $file = $conf['metadir'].'/_htcookiesalt2';
- }
- $salt = io_readFile($file);
- if(empty($salt)) {
- $salt = bin2hex(auth_randombytes(64));
- io_saveFile($file, $salt);
- }
- if($addsession) {
- $salt .= session_id();
- }
- return $salt;
-}
-
-/**
- * Return truly (pseudo) random bytes if available, otherwise fall back to mt_rand
- *
- * @author Mark Seecof
- * @author Michael Hamann
- * @link http://php.net/manual/de/function.mt-rand.php#83655
- *
- * @param int $length number of bytes to get
- * @return string binary random strings
- */
-function auth_randombytes($length) {
- $strong = false;
- $rbytes = false;
-
- if (function_exists('openssl_random_pseudo_bytes')
- && (version_compare(PHP_VERSION, '5.3.4') >= 0
- || strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')
- ) {
- $rbytes = openssl_random_pseudo_bytes($length, $strong);
- }
-
- if (!$strong && function_exists('mcrypt_create_iv')
- && (version_compare(PHP_VERSION, '5.3.7') >= 0
- || strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')
- ) {
- $rbytes = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
- if ($rbytes !== false && strlen($rbytes) === $length) {
- $strong = true;
- }
- }
-
- // If no strong randoms available, try OS the specific ways
- if(!$strong) {
- // Unix/Linux platform
- $fp = @fopen('/dev/urandom', 'rb');
- if($fp !== false) {
- $rbytes = fread($fp, $length);
- fclose($fp);
- }
-
- // MS-Windows platform
- if(class_exists('COM')) {
- // http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx
- try {
- $CAPI_Util = new COM('CAPICOM.Utilities.1');
- $rbytes = $CAPI_Util->GetRandom($length, 0);
-
- // if we ask for binary data PHP munges it, so we
- // request base64 return value.
- if($rbytes) $rbytes = base64_decode($rbytes);
- } catch(Exception $ex) {
- // fail
- }
- }
- }
- if(strlen($rbytes) < $length) $rbytes = false;
-
- // still no random bytes available - fall back to mt_rand()
- if($rbytes === false) {
- $rbytes = '';
- for ($i = 0; $i < $length; ++$i) {
- $rbytes .= chr(mt_rand(0, 255));
- }
- }
-
- return $rbytes;
-}
-
-/**
- * Random number generator using the best available source
- *
- * @author Michael Samuel
- * @author Michael Hamann
- *
- * @param int $min
- * @param int $max
- * @return int
- */
-function auth_random($min, $max) {
- $abs_max = $max - $min;
-
- $nbits = 0;
- for ($n = $abs_max; $n > 0; $n >>= 1) {
- ++$nbits;
- }
-
- $mask = (1 << $nbits) - 1;
- do {
- $bytes = auth_randombytes(PHP_INT_SIZE);
- $integers = unpack('Inum', $bytes);
- $integer = $integers["num"] & $mask;
- } while ($integer > $abs_max);
-
- return $min + $integer;
-}
-
-/**
- * Encrypt data using the given secret using AES
- *
- * The mode is CBC with a random initialization vector, the key is derived
- * using pbkdf2.
- *
- * @param string $data The data that shall be encrypted
- * @param string $secret The secret/password that shall be used
- * @return string The ciphertext
- */
-function auth_encrypt($data, $secret) {
- $iv = auth_randombytes(16);
- $cipher = new Crypt_AES();
- $cipher->setPassword($secret);
-
- /*
- this uses the encrypted IV as IV as suggested in
- http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, Appendix C
- for unique but necessarily random IVs. The resulting ciphertext is
- compatible to ciphertext that was created using a "normal" IV.
- */
- return $cipher->encrypt($iv.$data);
-}
-
-/**
- * Decrypt the given AES ciphertext
- *
- * The mode is CBC, the key is derived using pbkdf2
- *
- * @param string $ciphertext The encrypted data
- * @param string $secret The secret/password that shall be used
- * @return string The decrypted data
- */
-function auth_decrypt($ciphertext, $secret) {
- $iv = substr($ciphertext, 0, 16);
- $cipher = new Crypt_AES();
- $cipher->setPassword($secret);
- $cipher->setIV($iv);
-
- return $cipher->decrypt(substr($ciphertext, 16));
-}
-
-/**
- * Log out the current user
- *
- * This clears all authentication data and thus log the user
- * off. It also clears session data.
- *
- * @author Andreas Gohr
- *
- * @param bool $keepbc - when true, the breadcrumb data is not cleared
- */
-function auth_logoff($keepbc = false) {
- global $conf;
- global $USERINFO;
- /* @var DokuWiki_Auth_Plugin $auth */
- global $auth;
- /* @var Input $INPUT */
- global $INPUT;
-
- // make sure the session is writable (it usually is)
- @session_start();
-
- if(isset($_SESSION[DOKU_COOKIE]['auth']['user']))
- unset($_SESSION[DOKU_COOKIE]['auth']['user']);
- if(isset($_SESSION[DOKU_COOKIE]['auth']['pass']))
- unset($_SESSION[DOKU_COOKIE]['auth']['pass']);
- if(isset($_SESSION[DOKU_COOKIE]['auth']['info']))
- unset($_SESSION[DOKU_COOKIE]['auth']['info']);
- if(!$keepbc && isset($_SESSION[DOKU_COOKIE]['bc']))
- unset($_SESSION[DOKU_COOKIE]['bc']);
- $INPUT->server->remove('REMOTE_USER');
- $USERINFO = null; //FIXME
-
- $cookieDir = empty($conf['cookiedir']) ? DOKU_REL : $conf['cookiedir'];
- setcookie(DOKU_COOKIE, '', time() - 600000, $cookieDir, '', ($conf['securecookie'] && is_ssl()), true);
-
- if($auth) $auth->logOff();
-}
-
-/**
- * Check if a user is a manager
- *
- * Should usually be called without any parameters to check the current
- * user.
- *
- * The info is available through $INFO['ismanager'], too
- *
- * @author Andreas Gohr
- * @see auth_isadmin
- *
- * @param string $user Username
- * @param array $groups List of groups the user is in
- * @param bool $adminonly when true checks if user is admin
- * @return bool
- */
-function auth_ismanager($user = null, $groups = null, $adminonly = false) {
- global $conf;
- global $USERINFO;
- /* @var DokuWiki_Auth_Plugin $auth */
- global $auth;
- /* @var Input $INPUT */
- global $INPUT;
-
-
- if(!$auth) return false;
- if(is_null($user)) {
- if(!$INPUT->server->has('REMOTE_USER')) {
- return false;
- } else {
- $user = $INPUT->server->str('REMOTE_USER');
- }
- }
- if(is_null($groups)) {
- $groups = (array) $USERINFO['grps'];
- }
-
- // check superuser match
- if(auth_isMember($conf['superuser'], $user, $groups)) return true;
- if($adminonly) return false;
- // check managers
- if(auth_isMember($conf['manager'], $user, $groups)) return true;
-
- return false;
-}
-
-/**
- * Check if a user is admin
- *
- * Alias to auth_ismanager with adminonly=true
- *
- * The info is available through $INFO['isadmin'], too
- *
- * @author Andreas Gohr