From 207543754c4e7a6b1266952d846dc5c254b9a3d3 Mon Sep 17 00:00:00 2001
From: czaks
Date: Sun, 30 Mar 2014 16:40:14 +0200
Subject: SECURITY: remove XSS vulnerability
---
inc/lib/gettext/examples/index.php | 27 -------
.../examples/locale/de_CH/LC_MESSAGES/messages.mo | Bin 585 -> 0 bytes
.../examples/locale/de_CH/LC_MESSAGES/messages.po | 30 -------
.../examples/locale/sr_CS/LC_MESSAGES/messages.mo | Bin 829 -> 0 bytes
.../examples/locale/sr_CS/LC_MESSAGES/messages.po | 30 -------
inc/lib/gettext/examples/pigs_dropin.php | 89 ---------------------
inc/lib/gettext/examples/pigs_fallback.php | 88 --------------------
inc/lib/gettext/examples/update | 14 ----
inc/lib/gettext/tests/LocalesTest.php | 75 -----------------
inc/lib/gettext/tests/ParsingTest.php | 60 --------------
10 files changed, 413 deletions(-)
delete mode 100644 inc/lib/gettext/examples/index.php
delete mode 100644 inc/lib/gettext/examples/locale/de_CH/LC_MESSAGES/messages.mo
delete mode 100644 inc/lib/gettext/examples/locale/de_CH/LC_MESSAGES/messages.po
delete mode 100644 inc/lib/gettext/examples/locale/sr_CS/LC_MESSAGES/messages.mo
delete mode 100644 inc/lib/gettext/examples/locale/sr_CS/LC_MESSAGES/messages.po
delete mode 100644 inc/lib/gettext/examples/pigs_dropin.php
delete mode 100644 inc/lib/gettext/examples/pigs_fallback.php
delete mode 100755 inc/lib/gettext/examples/update
delete mode 100644 inc/lib/gettext/tests/LocalesTest.php
delete mode 100644 inc/lib/gettext/tests/ParsingTest.php
(limited to 'inc/lib')
diff --git a/inc/lib/gettext/examples/index.php b/inc/lib/gettext/examples/index.php
deleted file mode 100644
index 263cd3d3..00000000
--- a/inc/lib/gettext/examples/index.php
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-PHP-gettext examples
-
-
-PHP-gettext
-
-Introduction
-PHP-gettext provides a simple gettext replacement that works independently from the system's gettext abilities.
-It can read MO files and use them for translating strings.
-This version has the ability to cache all strings and translations to speed up the string lookup.
-While the cache is enabled by default, it can be switched off with the second parameter in the constructor (e.g. when using very large MO files
-that you don't want to keep in memory)
-
-
-Examples
-
-
-
-Copyright (c) 2003-2006 Danilo Segan
-Copyright (c) 2005-2006 Steven Armstrong
-
-
-
diff --git a/inc/lib/gettext/examples/locale/de_CH/LC_MESSAGES/messages.mo b/inc/lib/gettext/examples/locale/de_CH/LC_MESSAGES/messages.mo
deleted file mode 100644
index 91930376..00000000
Binary files a/inc/lib/gettext/examples/locale/de_CH/LC_MESSAGES/messages.mo and /dev/null differ
diff --git a/inc/lib/gettext/examples/locale/de_CH/LC_MESSAGES/messages.po b/inc/lib/gettext/examples/locale/de_CH/LC_MESSAGES/messages.po
deleted file mode 100644
index 6e4886b5..00000000
--- a/inc/lib/gettext/examples/locale/de_CH/LC_MESSAGES/messages.po
+++ /dev/null
@@ -1,30 +0,0 @@
-# Sample translation for PHP-gettext 1.0
-# Copyright (c) 2003 Danilo Segan
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: pigs\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2003-10-23 04:50+0200\n"
-"PO-Revision-Date: 2003-11-01 23:40+0100\n"
-"Last-Translator: Danilo Segan \n"
-"Language-Team: Serbian (sr) \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-#"Plural-Forms: nplurals=2; plural=n != 1;\n"
-
-#: pigs.php:19
-msgid ""
-"This is how the story goes.\n"
-"\n"
-msgstr ""
-"Und so geht die Geschichte.\n"
-"\n"
-
-#: pigs.php:21
-#, php-format
-msgid "%d pig went to the market\n"
-msgid_plural "%d pigs went to the market\n"
-msgstr[0] "%d Schwein ging zum Markt\n"
-msgstr[1] "%d Schweine gingen zum Markt\n"
diff --git a/inc/lib/gettext/examples/locale/sr_CS/LC_MESSAGES/messages.mo b/inc/lib/gettext/examples/locale/sr_CS/LC_MESSAGES/messages.mo
deleted file mode 100644
index 497c8830..00000000
Binary files a/inc/lib/gettext/examples/locale/sr_CS/LC_MESSAGES/messages.mo and /dev/null differ
diff --git a/inc/lib/gettext/examples/locale/sr_CS/LC_MESSAGES/messages.po b/inc/lib/gettext/examples/locale/sr_CS/LC_MESSAGES/messages.po
deleted file mode 100644
index e5da0e94..00000000
--- a/inc/lib/gettext/examples/locale/sr_CS/LC_MESSAGES/messages.po
+++ /dev/null
@@ -1,30 +0,0 @@
-# Sample translation for PHP-gettext 1.0
-# Copyright (c) 2003,2006 Danilo Segan
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: pigs\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2003-10-23 04:50+0200\n"
-"PO-Revision-Date: 2006-02-02 21:06+0100\n"
-"Last-Translator: Danilo Segan \n"
-"Language-Team: Serbian (sr) \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
-"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-
-#: pigs.php:19
-msgid ""
-"This is how the story goes.\n"
-"\n"
-msgstr "Овако иде прича.\n\n"
-
-#: pigs.php:21
-#, php-format
-msgid "%d pig went to the market\n"
-msgid_plural "%d pigs went to the market\n"
-msgstr[0] "%d мало прасе је отишло на пијац\n"
-msgstr[1] "%d мала прасета су отишла на пијац\n"
-msgstr[2] "%d малих прасића је отишло на пијац\n"
diff --git a/inc/lib/gettext/examples/pigs_dropin.php b/inc/lib/gettext/examples/pigs_dropin.php
deleted file mode 100644
index 94fd8507..00000000
--- a/inc/lib/gettext/examples/pigs_dropin.php
+++ /dev/null
@@ -1,89 +0,0 @@
-.
- Copyright (c) 2005,2006 Steven Armstrong
-
- This file is part of PHP-gettext.
-
- PHP-gettext is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- PHP-gettext is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with PHP-gettext; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-error_reporting(E_ALL | E_STRICT);
-
-// define constants
-define('PROJECT_DIR', realpath('./'));
-define('LOCALE_DIR', PROJECT_DIR .'/locale');
-define('DEFAULT_LOCALE', 'en_US');
-
-require_once('../gettext.inc');
-
-$supported_locales = array('en_US', 'sr_CS', 'de_CH');
-$encoding = 'UTF-8';
-
-$locale = (isset($_GET['lang']))? $_GET['lang'] : DEFAULT_LOCALE;
-
-// gettext setup
-T_setlocale(LC_MESSAGES, $locale);
-// Set the text domain as 'messages'
-$domain = 'messages';
-bindtextdomain($domain, LOCALE_DIR);
-// bind_textdomain_codeset is supported only in PHP 4.2.0+
-if (function_exists('bind_textdomain_codeset'))
- bind_textdomain_codeset($domain, $encoding);
-textdomain($domain);
-
-header("Content-type: text/html; charset=$encoding");
-?>
-
-
-PHP-gettext dropin example
-
-
-PHP-gettext as a dropin replacement
-Example showing how to use PHP-gettext as a dropin replacement for the native gettext library.
-";
-foreach($supported_locales as $l) {
- print "[$l ] ";
-}
-print "
\n";
-
-if (!locale_emulation()) {
- print "locale '$locale' is supported by your system, using native gettext implementation.
\n";
-}
-else {
- print "locale '$locale' is _not_ supported on your system, using the default locale '". DEFAULT_LOCALE ."'.
\n";
-}
-?>
-
-
-
-";
-print _("This is how the story goes.\n\n");
-for ($number=6; $number>=0; $number--) {
- print sprintf(T_ngettext("%d pig went to the market\n",
- "%d pigs went to the market\n", $number),
- $number );
-}
-print "\n";
-?>
-
-
-« back
-
-
diff --git a/inc/lib/gettext/examples/pigs_fallback.php b/inc/lib/gettext/examples/pigs_fallback.php
deleted file mode 100644
index 353190da..00000000
--- a/inc/lib/gettext/examples/pigs_fallback.php
+++ /dev/null
@@ -1,88 +0,0 @@
-.
- Copyright (c) 2005,2006 Steven Armstrong
-
- This file is part of PHP-gettext.
-
- PHP-gettext is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- PHP-gettext is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with PHP-gettext; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-
-error_reporting(E_ALL | E_STRICT);
-
-// define constants
-define('PROJECT_DIR', realpath('./'));
-define('LOCALE_DIR', PROJECT_DIR .'/locale');
-define('DEFAULT_LOCALE', 'en_US');
-
-require_once('../gettext.inc');
-
-$supported_locales = array('en_US', 'sr_CS', 'de_CH');
-$encoding = 'UTF-8';
-
-$locale = (isset($_GET['lang']))? $_GET['lang'] : DEFAULT_LOCALE;
-
-// gettext setup
-T_setlocale(LC_MESSAGES, $locale);
-// Set the text domain as 'messages'
-$domain = 'messages';
-T_bindtextdomain($domain, LOCALE_DIR);
-T_bind_textdomain_codeset($domain, $encoding);
-T_textdomain($domain);
-
-header("Content-type: text/html; charset=$encoding");
-?>
-
-
-PHP-gettext fallback example
-
-
-PHP-gettext as a fallback solution
-Example showing how to use PHP-gettext as a fallback solution if the native gettext library is not available or the system does not support the requested locale.
-
-";
-foreach($supported_locales as $l) {
- print "[$l ] ";
-}
-print "\n";
-
-if (!locale_emulation()) {
- print "locale '$locale' is supported by your system, using native gettext implementation.
\n";
-}
-else {
- print "locale '$locale' is not supported on your system, using custom gettext implementation.
\n";
-}
-?>
-
-
-
-";
-print T_("This is how the story goes.\n\n");
-for ($number=6; $number>=0; $number--) {
- print sprintf( T_ngettext("%d pig went to the market\n",
- "%d pigs went to the market\n", $number),
- $number );
-}
-print "\n";
-?>
-
-
-« back
-
-
diff --git a/inc/lib/gettext/examples/update b/inc/lib/gettext/examples/update
deleted file mode 100755
index 76b4308a..00000000
--- a/inc/lib/gettext/examples/update
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-TEMPLATE=pigs.pot
-xgettext -kT_ngettext:1,2 -kT_ -L PHP -o $TEMPLATE pigs_dropin.php
-if [ "x$1" = "x-p" ]; then
- msgfmt --statistics $TEMPLATE
-else
- if [ -f $1.po ]; then
- msgmerge -o .tmp$1.po $1.po $TEMPLATE
- mv .tmp$1.po $1.po
- msgfmt --statistics $1.po
- else
- echo "Usage: $0 [-p|]"
- fi
-fi
diff --git a/inc/lib/gettext/tests/LocalesTest.php b/inc/lib/gettext/tests/LocalesTest.php
deleted file mode 100644
index fab21f86..00000000
--- a/inc/lib/gettext/tests/LocalesTest.php
+++ /dev/null
@@ -1,75 +0,0 @@
-assertEquals('sr_RS', _setlocale(LC_MESSAGES, 0));
- }
-
- public function test_setlocale_system()
- {
- putenv("LC_ALL=");
- // For an existing locale, it never needs emulation.
- putenv("LANG=C");
- _setlocale(LC_MESSAGES, "");
- $this->assertEquals(0, locale_emulation());
- }
-
- public function test_setlocale_emulation()
- {
- putenv("LC_ALL=");
- // If we set it to a non-existent locale, it still works, but uses
- // emulation.
- _setlocale(LC_MESSAGES, "xxx_XXX");
- $this->assertEquals('xxx_XXX', _setlocale(LC_MESSAGES, 0));
- $this->assertEquals(1, locale_emulation());
- }
-
- public function test_get_list_of_locales()
- {
- // For a locale containing country code, we prefer
- // full locale name, but if that's not found, fall back
- // to the language only locale name.
- $this->assertEquals(array("sr_RS", "sr"),
- get_list_of_locales("sr_RS"));
-
- // If language code is used, it's the only thing returned.
- $this->assertEquals(array("sr"),
- get_list_of_locales("sr"));
-
- // There is support for language and charset only.
- $this->assertEquals(array("sr.UTF-8", "sr"),
- get_list_of_locales("sr.UTF-8"));
-
- // It can also split out character set from the full locale name.
- $this->assertEquals(array("sr_RS.UTF-8", "sr_RS", "sr"),
- get_list_of_locales("sr_RS.UTF-8"));
-
- // There is support for @modifier in locale names as well.
- $this->assertEquals(array("sr_RS.UTF-8@latin", "sr_RS@latin", "sr@latin",
- "sr_RS.UTF-8", "sr_RS", "sr"),
- get_list_of_locales("sr_RS.UTF-8@latin"));
-
- // We can pass in only language and modifier.
- $this->assertEquals(array("sr@latin", "sr"),
- get_list_of_locales("sr@latin"));
-
-
- // If locale name is not following the regular POSIX pattern,
- // it's used verbatim.
- $this->assertEquals(array("something"),
- get_list_of_locales("something"));
-
- // Passing in an empty string returns an empty array.
- $this->assertEquals(array(),
- get_list_of_locales(""));
- }
-}
-
-?>
diff --git a/inc/lib/gettext/tests/ParsingTest.php b/inc/lib/gettext/tests/ParsingTest.php
deleted file mode 100644
index ff561989..00000000
--- a/inc/lib/gettext/tests/ParsingTest.php
+++ /dev/null
@@ -1,60 +0,0 @@
-assertEquals(
- 'nplurals=2; plural=n == 1 ? 0 : 1;',
- $parser->extract_plural_forms_header_from_po_header(""));
-
- // Extracting it from the middle of the header works.
- $this->assertEquals(
- 'nplurals=1; plural=0;',
- $parser->extract_plural_forms_header_from_po_header(
- "Content-type: text/html; charset=UTF-8\n"
- ."Plural-Forms: nplurals=1; plural=0;\n"
- ."Last-Translator: nobody\n"
- ));
-
- // It's also case-insensitive.
- $this->assertEquals(
- 'nplurals=1; plural=0;',
- $parser->extract_plural_forms_header_from_po_header(
- "PLURAL-forms: nplurals=1; plural=0;\n"
- ));
-
- // It falls back to default if it's not on a separate line.
- $this->assertEquals(
- 'nplurals=2; plural=n == 1 ? 0 : 1;',
- $parser->extract_plural_forms_header_from_po_header(
- "Content-type: text/html; charset=UTF-8" // note the missing \n here
- ."Plural-Forms: nplurals=1; plural=0;\n"
- ."Last-Translator: nobody\n"
- ));
- }
-
- /**
- * @dataProvider data_provider_test_npgettext
- */
- public function test_npgettext($number, $expected) {
- $parser = new gettext_reader(NULL);
- $result = $parser->npgettext("context",
- "%d pig went to the market\n",
- "%d pigs went to the market\n",
- $number);
- $this->assertSame($expected, $result);
- }
- public static function data_provider_test_npgettext() {
- return array(
- array(1, "%d pig went to the market\n"),
- array(2, "%d pigs went to the market\n"),
- );
- }
-
-}
-?>
--
cgit v1.3
From 781fde7789e27bf35033bfbea740d56426b4d251 Mon Sep 17 00:00:00 2001
From: czaks
Date: Sun, 6 Apr 2014 21:21:17 +0200
Subject: move php files to a more sane directory
---
containerchan/README.md | 51 ----
containerchan/matroska.php | 524 ------------------------------------------
containerchan/player.php | 25 --
containerchan/posthandler.php | 49 ----
containerchan/videodata.php | 173 --------------
inc/lib/webm/README.md | 51 ++++
inc/lib/webm/matroska.php | 524 ++++++++++++++++++++++++++++++++++++++++++
inc/lib/webm/player.php | 25 ++
inc/lib/webm/posthandler.php | 49 ++++
inc/lib/webm/videodata.php | 173 ++++++++++++++
10 files changed, 822 insertions(+), 822 deletions(-)
delete mode 100644 containerchan/README.md
delete mode 100644 containerchan/matroska.php
delete mode 100644 containerchan/player.php
delete mode 100644 containerchan/posthandler.php
delete mode 100644 containerchan/videodata.php
create mode 100644 inc/lib/webm/README.md
create mode 100644 inc/lib/webm/matroska.php
create mode 100644 inc/lib/webm/player.php
create mode 100644 inc/lib/webm/posthandler.php
create mode 100644 inc/lib/webm/videodata.php
(limited to 'inc/lib')
diff --git a/containerchan/README.md b/containerchan/README.md
deleted file mode 100644
index 71036c07..00000000
--- a/containerchan/README.md
+++ /dev/null
@@ -1,51 +0,0 @@
-This project is an effort to enable imageboards to host small video clips. With modern video compression, it's possible to share much higher-quality videos in a few megabytes than what you can do with animated GIF files.
-
-The software here extends [Tinyboard](http://tinyboard.org/) to display metadata and create pseudo-thumbnails for WebM video files. It is intended to work on very basic web hosting services, including any hosting service that can run Tinyboard. In particular, it does not depend on any external video conversion software such as FFmpeg or Libav. Rather, it parses the video container to extract a single frame from the video to use in place of a thumbnail. If you can run FFmpeg or Libav on your server, it's a good idea to modify this code to use those tools to create true thumbnails; in the future, an option will be added to enable this.
-
-A board using this code can be found at:
-http://containerchan.org/tb/demo/
-
-Be aware that this is beta software. Please report any bugs you find.
-
-Much of the code is not specific to Tinyboard, and you are welcome to use it in your own projects. See the [core](https://github.com/ccd0/containerchan/tree/core) branch for a version without material from Tinyboard.
-
-Installation
-------------
-
-Create a directory named cc at the root of your Tinyboard installation. Upload these files into that directory.
-
-Replace the files templates/post_thread.html and templates/post_reply.html with the files given here.
-
-Move video.png to the static directory.
-
-Add these lines to inc/instance-config.php:
-
- $config['allowed_ext_files'][] = 'webm';
- $config['file_icons']['webm'] = 'video.png';
- $config['additional_javascript'][] = 'cc/settings.js';
- $config['additional_javascript'][] = 'cc/expandvideo.js';
- require_once 'cc/posthandler.php';
- event_handler('post', 'postHandler');
-
-And add this to stylesheets/style.css:
-
- video.post-image {
- display: block;
- float: left;
- margin: 10px 20px;
- border: none;
- }
- div.post video.post-image {
- padding: 0px;
- margin: 10px 25px 5px 5px;
- }
- span.settings {
- position: fixed;
- top: 1em;
- right: 1em;
- }
-
-License
--------
-
-See [LICENSE.md](https://github.com/ccd0/containerchan/blob/master/LICENSE.md).
diff --git a/containerchan/matroska.php b/containerchan/matroska.php
deleted file mode 100644
index 5f1c38ee..00000000
--- a/containerchan/matroska.php
+++ /dev/null
@@ -1,524 +0,0 @@
-datatype = $fields[1];
- $t->name = $fields[2];
- $t->validParents = array();
- for ($i = 0; $i + 3 < count($fields); $i++) {
- if ($fields[$i+3] == '*' || $fields[$i+3] == 'root') {
- $t->validParents[$i] = $fields[$i+3];
- } else {
- $t->validParents[$i] = hexdec($fields[$i+3]);
- }
- }
- $this->_els[$id] = $t;
- $this->_ids[strtoupper($t->name)] = $id;
- }
- }
-
- public function exists($id) {
- return isset($this->_els[$id]);
- }
-
- public function name($id) {
- if (!isset($this->_els[$id])) return NULL;
- return $this->_els[$id]->name;
- }
-
- public function id($name) {
- $name = strtoupper($name);
- if (!isset($this->_ids[$name])) return NULL;
- return $this->_ids[$name];
- }
-
- public function datatype($id) {
- if ($id == 'root') return 'container';
- if (!isset($this->_els[$id])) return 'binary';
- return $this->_els[$id]->datatype;
- }
-
- public function validChild($id1, $id2) {
- if (!isset($this->_els[$id2])) return TRUE;
- $parents = $this->_els[$id2]->validParents;
- return in_array('*', $parents) || in_array($id1, $parents);
- }
-}
-
-// Matroska element types
-global $EBML_ELEMENTS;
-$EBML_ELEMENTS = new EBMLElementTypeList(dirname(__FILE__) . '/matroska-elements.txt');
-
-// Decode big-endian integer
-function ebmlDecodeInt($data, $signed=FALSE, $carryIn=0) {
- $n = $carryIn;
- if (strlen($data) > 8) throw new Exception('not supported: integer too long');
- for ($i = 0; $i < strlen($data); $i++) {
- if ($n > (PHP_INT_MAX >> 8) || $n < ((-PHP_INT_MAX-1) >> 8)) {
- $n = floatval($n);
- }
- $n = $n * 0x100 + ord($data[$i]);
- if ($i == 0 && $signed && ($n & 0x80) != 0) {
- $n -= 0x100;
- }
- }
- return $n;
-}
-
-// Decode big-endian IEEE float
-function ebmlDecodeFloat($data) {
- switch (strlen($data)) {
- case 0:
- return 0;
- case 4:
- switch(pack('f', 1e9)) {
- case '(knN':
- $arr = unpack('f', strrev($data));
- return $arr[1];
- case 'Nnk(':
- $arr = unpack('f', $data);
- return $arr[1];
- default:
- error_log('cannot decode floats');
- return NULL;
- }
- case 8:
- switch(pack('d', 1e9)) {
- case "\x00\x00\x00\x00\x65\xcd\xcd\x41":
- $arr = unpack('d', strrev($data));
- return $arr[1];
- case "\x41\xcd\xcd\x65\x00\x00\x00\x00":
- $arr = unpack('d', $data);
- return $arr[1];
- default:
- error_log('cannot decode floats');
- return NULL;
- }
- default:
- error_log('unsupported float length');
- return NULL;
- }
-}
-
-// Decode big-endian signed offset from Jan 01, 2000 in nanoseconds
-// Convert to offset from Jan 01, 1970 in seconds
-function ebmlDecodeDate($data) {
- return ebmlDecodeInt($data, TRUE) * 1e-9 + 946684800;
-}
-
-// Decode data of specified datatype
-function ebmlDecode($data, $datatype) {
- switch ($datatype) {
- case 'int': return ebmlDecodeInt($data, TRUE);
- case 'uint': return ebmlDecodeInt($data, FALSE);
- case 'float': return ebmlDecodeFloat($data);
- case 'string': return chop($data, "\0");
- case 'date': return ebmlDecodeDate($data);
- case 'binary': return $data;
- default: throw new Exception('unknown datatype');
- }
-}
-
-// Methods for reading data from section of EBML file
-class EBMLReader {
- private $_fileHandle;
- private $_offset;
- private $_size;
- private $_position;
-
- public function __construct($fileHandle, $offset=0, $size=NULL) {
- $this->_fileHandle = $fileHandle;
- $this->_offset = $offset;
- $this->_size = $size;
- $this->_position = 0;
- }
-
- // Tell position within data section
- public function position() {
- return $this->_position;
- }
-
- // Set position within data section
- public function setPosition($position) {
- $this->_position = $position;
- }
-
- // Total size of data section (NULL if unknown)
- public function size() {
- return $this->_size;
- }
-
- // Set end of data section
- public function setSize($size) {
- if ($this->_size === NULL) {
- $this->_size = $size;
- } else {
- throw new Exception('size already set');
- }
- }
-
- // Determine whether we are at end of data
- public function endOfData() {
- if ($this->_size === NULL) {
- fseek($this->_fileHandle, $this->_offset + $this->_position);
- fread($this->_fileHandle, 1);
- if (feof($this->_fileHandle)) {
- $this->_size = $this->_position;
- return TRUE;
- } else {
- return FALSE;
- }
- } else {
- return $this->_position >= $this->_size;
- }
- }
-
- // Create EBMLReader containing $size bytes and advance
- public function nextSlice($size) {
- $slice = new EBMLReader($this->_fileHandle, $this->_offset + $this->_position, $size);
- if ($size !== NULL) {
- $this->_position += $size;
- if ($this->_size !== NULL && $this->_position > $this->_size) {
- throw new Exception('unexpected end of data');
- }
- }
- return $slice;
- }
-
- // Read entire region
- public function readAll() {
- if ($this->_size == 0) return '';
- if ($this->_size === NULL) throw new Exception('unknown length');
- fseek($this->_fileHandle, $this->_offset);
- $data = fread($this->_fileHandle, $this->_size);
- if ($data === FALSE || strlen($data) != $this->_size) {
- throw new Exception('error reading from file');
- }
- return $data;
- }
-
- // Read $size bytes
- public function read($size) {
- return $this->nextSlice($size)->readAll();
- }
-
- // Read variable-length integer
- public function readVarInt($signed=FALSE) {
- // Read size and remove flag
- $n = ord($this->read(1));
- $size = 0;
- if ($n == 0) {
- throw new Exception('not supported: variable-length integer too long');
- }
- $flag = 0x80;
- while (($n & $flag) == 0) {
- $flag = $flag >> 1;
- $size++;
- }
- $n -= $flag;
-
- // Read remaining data
- $rawInt = $this->read($size);
-
- // Check for all ones
- if ($n == $flag - 1 && $rawInt == str_repeat("\xFF", $size)) {
- return NULL;
- }
-
- // Range shift for signed integers
- if ($signed) {
- if ($flag == 0x01) {
- $n = ord($rawInt[0]) - 0x80;
- $rawInt = $rawInt.substr(1);
- } else {
- $n -= ($flag >> 1);
- }
- }
-
- // Convert to integer
- $n = ebmlDecodeInt($rawInt, FALSE, $n);
-
- // Range shift for signed integers
- if ($signed) {
- if ($n == PHP_INT_MAX) {
- $n = floatval($n);
- }
- $n++;
- }
-
- return $n;
- }
-}
-
-// EBML element
-class EBMLElement {
- private $_id;
- private $_name;
- private $_datatype;
- private $_content;
- private $_headSize;
-
- public function __construct($id, $content, $headSize) {
- global $EBML_ELEMENTS;
- $this->_id = $id;
- $this->_name = $EBML_ELEMENTS->name($this->_id);
- $this->_datatype = $EBML_ELEMENTS->datatype($this->_id);
- $this->_content = $content;
- $this->_headSize = $headSize;
- }
-
- public function id() {return $this->_id;}
- public function name() {return $this->_name;}
- public function datatype() {return $this->_datatype;}
- public function content() {return $this->_content;}
- public function headSize() {return $this->_headSize;}
-
- // Total size of element (including ID and datasize)
- public function size() {
- return $this->_headSize + $this->_content->size();
- }
-
- // Read and interpret content
- public function value() {
- if ($this->_datatype == 'binary') {
- return $this->_content;
- } else {
- return ebmlDecode($this->_content->readAll(), $this->_datatype);
- }
- }
-}
-
-// Iterate over EBML elements in data
-class EBMLElementList extends EBMLElement implements Iterator {
- private $_cache;
- private $_position;
- private static $MAX_ELEMENTS = 10000;
-
- public function __construct($id, $content, $headSize) {
- parent::__construct($id, $content, $headSize);
- $this->_cache = array();
- $this->_position = 0;
- }
-
- public function rewind() {
- $this->_position = 0;
- }
-
- public function current() {
- if ($this->valid()) {
- return $this->_cache[$this->_position];
- } else {
- return NULL;
- }
- }
-
- public function key() {
- return $this->_position;
- }
-
- public function next() {
- $this->_position += $this->current()->size();
- if ($this->content()->size() !== NULL && $this->_position > $this->content()->size()) {
- throw new Exception('unexpected end of data');
- }
- }
-
- public function valid() {
- global $EBML_ELEMENTS;
- if (isset($this->_cache[$this->_position])) return TRUE;
- $this->content()->setPosition($this->_position);
- if ($this->content()->endOfData()) return FALSE;
- $id = $this->content()->readVarInt();
- if ($id === NULL) throw new Exception('invalid ID');
- if ($this->content()->size() === NULL && !$EBML_ELEMENTS->validChild($this->id(), $id)) {
- $this->content()->setSize($this->_position);
- return FALSE;
- }
- $size = $this->content()->readVarInt();
- $headSize = $this->content()->position() - $this->_position;
- $content = $this->content()->nextSlice($size);
- if ($EBML_ELEMENTS->datatype($id) == 'container') {
- $element = new EBMLElementList($id, $content, $headSize);
- } else {
- if ($size === NULL) {
- throw new Exception('non-container element of unknown size');
- }
- $element = new EBMLElement($id, $content, $headSize);
- }
- $this->_cache[$this->_position] = $element;
- return TRUE;
- }
-
- // Total size of element (including ID and size)
- public function size() {
- if ($this->content()->size() === NULL) {
- $iElement = 0;
- foreach ($this as $element) { // iterate over elements to find end
- $iElement++;
- if ($iElement > self::$MAX_ELEMENTS) throw new Exception('not supported: too many elements');
- }
- }
- return $this->headSize() + $this->content()->size();
- }
-
- // Read and interpret content
- public function value() {
- return $this;
- }
-
- // Get element value by name
- public function get($name, $defaultValue=NULL) {
- $iElement = 0;
- foreach ($this as $element) {
- $iElement++;
- if ($iElement > self::$MAX_ELEMENTS) throw new Exception('not supported: too many elements');
- if (strtoupper($element->name()) == strtoupper($name)) {
- return $element->value();
- }
- }
- return $defaultValue;
- }
-}
-
-// Parse block
-class MatroskaBlock {
- const LACING_NONE = 0;
- const LACING_XIPH = 1;
- const LACING_EBML = 3;
- const LACING_FIXED = 2;
- public $trackNumber;
- public $timecode;
- public $keyframe;
- public $invisible;
- public $lacing;
- public $discardable;
- public $frames;
-
- public function __construct($reader) {
- # Header
- $this->trackNumber = $reader->readVarInt();
- $this->timecode = ebmlDecodeInt($reader->read(2), TRUE);
- $flags = ord($reader->read(1));
- if (($flags & 0x70) != 0) {
- throw new Exception('reserved flags set');
- }
- $this->keyframe = (($flags & 0x80) != 0);
- $this->invisible = (($flags & 0x08) != 0);
- $this->lacing = ($flags >> 1) & 0x03;
- $this->discardable = (($flags & 0x01) != 0);
-
- # Lacing sizes
- if ($this->lacing == self::LACING_NONE) {
- $nsizes = 0;
- } else {
- $nsizes = ord($reader->read(1));
- }
- $sizes = array();
- switch ($this->lacing) {
- case self::LACING_XIPH:
- for ($i = 0; $i < $nsizes; $i++) {
- $size = 0;
- $x = 255;
- while ($x == 255) {
- $x = ord($reader->read(1));
- $size += $x;
- if ($size > 65536) throw new Exception('not supported: laced frame too long');
- }
- $sizes[$i] = $size;
- }
- break;
- case self::LACING_EBML:
- $size = 0;
- for ($i = 0; $i < $nsizes; $i++) {
- $dsize = $reader->readVarInt($i != 0);
- if ($dsize === NULL || $size + $dsize < 0) {
- throw new Exception('invalid frame size');
- }
- $size += $dsize;
- $sizes[$i] = $size;
- }
- break;
- case self::LACING_FIXED:
- $lenRemaining = $reader->size() - $reader->position();
- if ($lenRemaining % ($nsizes + 1) != 0) {
- throw new Exception('data size not divisible by frame count');
- }
- $size = (int) ($lenRemaining / ($nsizes + 1));
- for ($i = 0; $i < $nsizes; $i++) {
- $sizes[$i] = $size;
- }
- break;
- }
-
- # Frames
- $this->frames = array();
- for ($i = 0; $i < $nsizes; $i++) {
- $this->frames[$i] = $reader->nextSlice($sizes[$i]);
- }
- $this->frames[$nsizes] = $reader->nextSlice($reader->size() - $reader->position());
- }
-}
-
-// Create element list from $fileHandle
-function readMatroska($fileHandle) {
- $reader = new EBMLReader($fileHandle);
- if ($reader->read(4) != "\x1a\x45\xdf\xa3") {
- throw new Exception('not an EBML file');
- }
- $root = new EBMLElementList('root', $reader, 0);
- $header = $root->get('EBML');
- $ebmlVersion = $header->get('EBMLReadVersion', 1);
- $docType = $header->get('DocType');
- $docTypeVersion = $header->get('DocTypeReadVersion', 1);
- if ($ebmlVersion != 1) {
- throw new Exception('unsupported EBML version');
- }
- if ($docType != 'matroska' && $docType != 'webm') {
- throw new Exception ('unsupported document type');
- }
- if ($docTypeVersion < 1 || $docTypeVersion > 4) {
- throw new Exception ('unsupported document type version');
- }
- return $root;
-}
-
-function ebmlEncodeVarInt($n) {
- $data = '';
- $flag = 0x80;
- while ($n >= $flag) {
- if ($flag == 0) {
- throw new Exception('not supported: number too large');
- }
- $data = chr($n & 0xFF) . $data;
- $n = $n >> 8;
- $flag = $flag >> 1;
- }
- $data = chr($n | $flag) . $data;
- return $data;
-}
-
-function ebmlEncodeElementName($name) {
- global $EBML_ELEMENTS;
- return ebmlEncodeVarInt($EBML_ELEMENTS->id($name));
-}
-
-function ebmlEncodeElement($name, $content) {
- return ebmlEncodeElementName($name) . ebmlEncodeVarInt(strlen($content)) . $content;
-}
diff --git a/containerchan/player.php b/containerchan/player.php
deleted file mode 100644
index bf4a259d..00000000
--- a/containerchan/player.php
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
src="">
- Your browser does not support HTML5 video. [Download]
-
-
-
-
diff --git a/containerchan/posthandler.php b/containerchan/posthandler.php
deleted file mode 100644
index 50adbe80..00000000
--- a/containerchan/posthandler.php
+++ /dev/null
@@ -1,49 +0,0 @@
-has_file && $post->extension == 'webm') {
- require_once dirname(__FILE__) . '/videodata.php';
- $videoDetails = videoData($post->file_path);
- if (!isset($videoDetails['container']) || $videoDetails['container'] != 'webm') return "not a WebM file";
-
- // Set thumbnail
- $thumbName = $board['dir'] . $config['dir']['thumb'] . $post->file_id . '.webm';
- if ($config['spoiler_images'] && isset($_POST['spoiler'])) {
- // Use spoiler thumbnail
- $post->thumb = 'spoiler';
- $size = @getimagesize($config['spoiler_image']);
- $post->thumbwidth = $size[0];
- $post->thumbheight = $size[1];
- } elseif (isset($videoDetails['frame']) && $thumbFile = fopen($thumbName, 'wb')) {
- // Use single frame from video as pseudo-thumbnail
- fwrite($thumbFile, $videoDetails['frame']);
- fclose($thumbFile);
- $post->thumb = $post->file_id . '.webm';
- } else {
- // Fall back to file thumbnail
- $post->thumb = 'file';
- }
- unset($videoDetails['frame']);
-
- // Set width and height
- if (isset($videoDetails['width']) && isset($videoDetails['height'])) {
- $post->width = $videoDetails['width'];
- $post->height = $videoDetails['height'];
- if ($post->thumb != 'file' && $post->thumb != 'spoiler') {
- $thumbMaxWidth = $post->op ? $config['thumb_op_width'] : $config['thumb_width'];
- $thumbMaxHeight = $post->op ? $config['thumb_op_height'] : $config['thumb_height'];
- if ($videoDetails['width'] > $thumbMaxWidth || $videoDetails['height'] > $thumbMaxHeight) {
- $post->thumbwidth = min($thumbMaxWidth, intval(round($videoDetails['width'] * $thumbMaxHeight / $videoDetails['height'])));
- $post->thumbheight = min($thumbMaxHeight, intval(round($videoDetails['height'] * $thumbMaxWidth / $videoDetails['width'])));
- } else {
- $post->thumbwidth = $videoDetails['width'];
- $post->thumbheight = $videoDetails['height'];
- }
- }
- }
- }
-}
diff --git a/containerchan/videodata.php b/containerchan/videodata.php
deleted file mode 100644
index d54d484b..00000000
--- a/containerchan/videodata.php
+++ /dev/null
@@ -1,173 +0,0 @@
-get('Video');
- if (isset($videoAttr)) {
- if ($videoAttr->get('StereoMode') !== NULL) $version = 3;
- if ($videoAttr->get('AlphaMode') !== NULL) $version = 3;
- }
- if ($videoTrack->get('CodecDelay') !== NULL) $version = 4;
- if ($videoTrack->get('SeekPreRoll') !== NULL) $version = 4;
- if ($frame->name() == 'BlockGroup' && $frame->get('DiscardPadding') !== NULL) $version = 4;
-
- // EBML header
- $ebml = ebmlEncodeElement('EBML',
- ebmlEncodeElement('DocType', "webm")
- . ebmlEncodeElement('DocTypeVersion', chr($version))
- . ebmlEncodeElement('DocTypeReadVersion', "\x02")
- );
-
- // Segment
- $info = ebmlEncodeElement('Info',
- ebmlEncodeElement('Duration', "\x41\x20\x00\x00")
- . ebmlEncodeElement('MuxingApp', 'ccframe')
- . ebmlEncodeElement('WritingApp', 'ccframe')
- );
- $tracks = ebmlEncodeElement('Tracks',
- ebmlEncodeElement('TrackEntry', $videoTrack->content()->readAll())
- );
- $cues = ebmlEncodeElement('Cues',
- ebmlEncodeElement('CuePoint',
- ebmlEncodeElement('CueTime', "\x00")
- . ebmlEncodeElement('CueTrackPositions',
- ebmlEncodeElement('CueTrack', pack('N', $videoTrack->get('TrackNumber')))
- . ebmlEncodeElement('CueClusterPosition', pack('N', $lenSeekHead + strlen($info) + strlen($tracks) + $lenCues))
- )
- )
- );
- if (strlen($cues) != $lenCues) throw new Exception('length of Cues element wrong');
- $cluster = ebmlEncodeElement('Cluster',
- ebmlEncodeElement('Timecode', "\x00")
- . ebmlEncodeElement($frame->name(), $frame->content()->readAll())
- . ebmlEncodeElement('Void', '')
- );
- $seekHead = ebmlEncodeElement('SeekHead',
- matroskaSeekElement('Info', $lenSeekHead)
- . matroskaSeekElement('Tracks', $lenSeekHead + strlen($info))
- . matroskaSeekElement('Cues', $lenSeekHead + strlen($info) + strlen($tracks))
- . matroskaSeekElement('Cluster', $lenSeekHead + strlen($info) + strlen($tracks) + $lenCues)
- );
- if (strlen($seekHead) != $lenSeekHead) throw new Exception('length of SeekHead element wrong');
- $segment = ebmlEncodeElement('Segment', $seekHead . $info . $tracks . $cues . $cluster);
-
- return $ebml . $segment;
-}
-
-// Locate first WebM keyframe of track $trackNumber after timecode $skip
-function firstWebMFrame($segment, $trackNumber, $skip=0) {
- foreach($segment as $x1) {
- if ($x1->name() == 'Cluster') {
- $cluserTimecode = $x1->Get('Timecode');
- foreach($x1 as $blockGroup) {
- $blockRaw = NULL;
- if ($blockGroup->name() == 'SimpleBlock') {
- $blockRaw = $blockGroup->value();
- } elseif ($blockGroup->name() == 'BlockGroup') {
- $blockRaw = $blockGroup->get('Block');
- }
- if (isset($blockRaw)) {
- $block = new MatroskaBlock($blockRaw);
- if ($block->trackNumber == $trackNumber && $block->keyframe) {
- if (!isset($cluserTimecode) || $cluserTimecode + $block->timecode >= $skip) {
- return $blockGroup;
- } elseif (!isset($frame1)) {
- $frame1 = $blockGroup;
- }
- }
- }
- }
- }
- }
- return isset($frame1) ? $frame1 : NULL;
-}
-
-function videoData($filename) {
- $data = array();
-
- // Open file
- $fileHandle = fopen($filename, 'rb');
- if (!$fileHandle) {
- error_log('could not open file');
- return $data;
- }
-
- try {
- $root = readMatroska($fileHandle);
- $data['container'] = $root->get('EBML')->get('DocType');
-
- // Locate segment information and tracks
- $segment = $root->get('Segment');
- if (!isset($segment)) throw new Exception('missing Segment element');
-
- // Get segment information
- $info = $segment->get('Info');
- if (isset($info)) {
- $timecodeScale = $info->get('TimecodeScale');
- $duration = $info->get('Duration');
- if (isset($timecodeScale) && isset($duration)) {
- $data['duration'] = 1e-9 * $timecodeScale * $duration;
- }
- }
-
- // Locate video track
- $tracks = $segment->get('Tracks');
- if (!isset($tracks)) throw new Exception('missing Tracks element');
- foreach($tracks as $trackEntry) {
- if ($trackEntry->name() == 'TrackEntry' && $trackEntry->get('TrackType') == 1) {
- $videoTrack = $trackEntry;
- break;
- }
- }
- if (!isset($videoTrack)) throw new Exception('no video track');
-
- // Get track information
- $videoAttr = $videoTrack->get('Video');
- if (!isset($videoAttr)) throw new Exception('missing video parameters');
- $pixelWidth = $videoAttr->get('PixelWidth');
- $pixelHeight = $videoAttr->get('PixelHeight');
- if (!isset($pixelWidth) || !isset($pixelHeight)) throw new Exception('no width or height');
- if ($pixelWidth == 0 || $pixelHeight == 0) throw new Exception('bad PixelWidth/PixelHeight');
- $displayWidth = $videoAttr->get('DisplayWidth', $pixelWidth);
- $displayHeight = $videoAttr->get('DisplayHeight', $pixelHeight);
- if ($displayWidth == 0 || $displayHeight == 0) throw new Exception('bad DisplayWidth/DisplayHeight');
- $data['width'] = $displayWidth;
- $data['height'] = $displayHeight;
-
- // Extract frame to use as thumbnail
- if ($videoAttr->get('AlphaMode') != NULL) {
- if (!($pixelWidth % 2 == 0 && $pixelHeight % 2 == 0 && $displayWidth % 2 == 0 && $displayHeight % 2 == 0)) {
- throw new Exception('preview frame blocked due to Chromium bug');
- }
- }
- $trackNumber = $videoTrack->get('TrackNumber');
- if (!isset($trackNumber)) throw new Exception('missing track number');
- if (isset($data['duration']) && $data['duration'] >= 5) {
- $skip = 1e9 / $timecodeScale;
- } else {
- $skip = 0;
- }
- $frame = firstWebMFrame($segment, $trackNumber, $skip);
- if (!isset($frame)) throw new Exception('no keyframes');
- $data['frame'] = muxWebMFrame($videoTrack, $frame);
- } catch (Exception $e) {
- error_log($e->getMessage());
- }
-
- fclose($fileHandle);
- return $data;
-}
diff --git a/inc/lib/webm/README.md b/inc/lib/webm/README.md
new file mode 100644
index 00000000..71036c07
--- /dev/null
+++ b/inc/lib/webm/README.md
@@ -0,0 +1,51 @@
+This project is an effort to enable imageboards to host small video clips. With modern video compression, it's possible to share much higher-quality videos in a few megabytes than what you can do with animated GIF files.
+
+The software here extends [Tinyboard](http://tinyboard.org/) to display metadata and create pseudo-thumbnails for WebM video files. It is intended to work on very basic web hosting services, including any hosting service that can run Tinyboard. In particular, it does not depend on any external video conversion software such as FFmpeg or Libav. Rather, it parses the video container to extract a single frame from the video to use in place of a thumbnail. If you can run FFmpeg or Libav on your server, it's a good idea to modify this code to use those tools to create true thumbnails; in the future, an option will be added to enable this.
+
+A board using this code can be found at:
+http://containerchan.org/tb/demo/
+
+Be aware that this is beta software. Please report any bugs you find.
+
+Much of the code is not specific to Tinyboard, and you are welcome to use it in your own projects. See the [core](https://github.com/ccd0/containerchan/tree/core) branch for a version without material from Tinyboard.
+
+Installation
+------------
+
+Create a directory named cc at the root of your Tinyboard installation. Upload these files into that directory.
+
+Replace the files templates/post_thread.html and templates/post_reply.html with the files given here.
+
+Move video.png to the static directory.
+
+Add these lines to inc/instance-config.php:
+
+ $config['allowed_ext_files'][] = 'webm';
+ $config['file_icons']['webm'] = 'video.png';
+ $config['additional_javascript'][] = 'cc/settings.js';
+ $config['additional_javascript'][] = 'cc/expandvideo.js';
+ require_once 'cc/posthandler.php';
+ event_handler('post', 'postHandler');
+
+And add this to stylesheets/style.css:
+
+ video.post-image {
+ display: block;
+ float: left;
+ margin: 10px 20px;
+ border: none;
+ }
+ div.post video.post-image {
+ padding: 0px;
+ margin: 10px 25px 5px 5px;
+ }
+ span.settings {
+ position: fixed;
+ top: 1em;
+ right: 1em;
+ }
+
+License
+-------
+
+See [LICENSE.md](https://github.com/ccd0/containerchan/blob/master/LICENSE.md).
diff --git a/inc/lib/webm/matroska.php b/inc/lib/webm/matroska.php
new file mode 100644
index 00000000..5f1c38ee
--- /dev/null
+++ b/inc/lib/webm/matroska.php
@@ -0,0 +1,524 @@
+datatype = $fields[1];
+ $t->name = $fields[2];
+ $t->validParents = array();
+ for ($i = 0; $i + 3 < count($fields); $i++) {
+ if ($fields[$i+3] == '*' || $fields[$i+3] == 'root') {
+ $t->validParents[$i] = $fields[$i+3];
+ } else {
+ $t->validParents[$i] = hexdec($fields[$i+3]);
+ }
+ }
+ $this->_els[$id] = $t;
+ $this->_ids[strtoupper($t->name)] = $id;
+ }
+ }
+
+ public function exists($id) {
+ return isset($this->_els[$id]);
+ }
+
+ public function name($id) {
+ if (!isset($this->_els[$id])) return NULL;
+ return $this->_els[$id]->name;
+ }
+
+ public function id($name) {
+ $name = strtoupper($name);
+ if (!isset($this->_ids[$name])) return NULL;
+ return $this->_ids[$name];
+ }
+
+ public function datatype($id) {
+ if ($id == 'root') return 'container';
+ if (!isset($this->_els[$id])) return 'binary';
+ return $this->_els[$id]->datatype;
+ }
+
+ public function validChild($id1, $id2) {
+ if (!isset($this->_els[$id2])) return TRUE;
+ $parents = $this->_els[$id2]->validParents;
+ return in_array('*', $parents) || in_array($id1, $parents);
+ }
+}
+
+// Matroska element types
+global $EBML_ELEMENTS;
+$EBML_ELEMENTS = new EBMLElementTypeList(dirname(__FILE__) . '/matroska-elements.txt');
+
+// Decode big-endian integer
+function ebmlDecodeInt($data, $signed=FALSE, $carryIn=0) {
+ $n = $carryIn;
+ if (strlen($data) > 8) throw new Exception('not supported: integer too long');
+ for ($i = 0; $i < strlen($data); $i++) {
+ if ($n > (PHP_INT_MAX >> 8) || $n < ((-PHP_INT_MAX-1) >> 8)) {
+ $n = floatval($n);
+ }
+ $n = $n * 0x100 + ord($data[$i]);
+ if ($i == 0 && $signed && ($n & 0x80) != 0) {
+ $n -= 0x100;
+ }
+ }
+ return $n;
+}
+
+// Decode big-endian IEEE float
+function ebmlDecodeFloat($data) {
+ switch (strlen($data)) {
+ case 0:
+ return 0;
+ case 4:
+ switch(pack('f', 1e9)) {
+ case '(knN':
+ $arr = unpack('f', strrev($data));
+ return $arr[1];
+ case 'Nnk(':
+ $arr = unpack('f', $data);
+ return $arr[1];
+ default:
+ error_log('cannot decode floats');
+ return NULL;
+ }
+ case 8:
+ switch(pack('d', 1e9)) {
+ case "\x00\x00\x00\x00\x65\xcd\xcd\x41":
+ $arr = unpack('d', strrev($data));
+ return $arr[1];
+ case "\x41\xcd\xcd\x65\x00\x00\x00\x00":
+ $arr = unpack('d', $data);
+ return $arr[1];
+ default:
+ error_log('cannot decode floats');
+ return NULL;
+ }
+ default:
+ error_log('unsupported float length');
+ return NULL;
+ }
+}
+
+// Decode big-endian signed offset from Jan 01, 2000 in nanoseconds
+// Convert to offset from Jan 01, 1970 in seconds
+function ebmlDecodeDate($data) {
+ return ebmlDecodeInt($data, TRUE) * 1e-9 + 946684800;
+}
+
+// Decode data of specified datatype
+function ebmlDecode($data, $datatype) {
+ switch ($datatype) {
+ case 'int': return ebmlDecodeInt($data, TRUE);
+ case 'uint': return ebmlDecodeInt($data, FALSE);
+ case 'float': return ebmlDecodeFloat($data);
+ case 'string': return chop($data, "\0");
+ case 'date': return ebmlDecodeDate($data);
+ case 'binary': return $data;
+ default: throw new Exception('unknown datatype');
+ }
+}
+
+// Methods for reading data from section of EBML file
+class EBMLReader {
+ private $_fileHandle;
+ private $_offset;
+ private $_size;
+ private $_position;
+
+ public function __construct($fileHandle, $offset=0, $size=NULL) {
+ $this->_fileHandle = $fileHandle;
+ $this->_offset = $offset;
+ $this->_size = $size;
+ $this->_position = 0;
+ }
+
+ // Tell position within data section
+ public function position() {
+ return $this->_position;
+ }
+
+ // Set position within data section
+ public function setPosition($position) {
+ $this->_position = $position;
+ }
+
+ // Total size of data section (NULL if unknown)
+ public function size() {
+ return $this->_size;
+ }
+
+ // Set end of data section
+ public function setSize($size) {
+ if ($this->_size === NULL) {
+ $this->_size = $size;
+ } else {
+ throw new Exception('size already set');
+ }
+ }
+
+ // Determine whether we are at end of data
+ public function endOfData() {
+ if ($this->_size === NULL) {
+ fseek($this->_fileHandle, $this->_offset + $this->_position);
+ fread($this->_fileHandle, 1);
+ if (feof($this->_fileHandle)) {
+ $this->_size = $this->_position;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ } else {
+ return $this->_position >= $this->_size;
+ }
+ }
+
+ // Create EBMLReader containing $size bytes and advance
+ public function nextSlice($size) {
+ $slice = new EBMLReader($this->_fileHandle, $this->_offset + $this->_position, $size);
+ if ($size !== NULL) {
+ $this->_position += $size;
+ if ($this->_size !== NULL && $this->_position > $this->_size) {
+ throw new Exception('unexpected end of data');
+ }
+ }
+ return $slice;
+ }
+
+ // Read entire region
+ public function readAll() {
+ if ($this->_size == 0) return '';
+ if ($this->_size === NULL) throw new Exception('unknown length');
+ fseek($this->_fileHandle, $this->_offset);
+ $data = fread($this->_fileHandle, $this->_size);
+ if ($data === FALSE || strlen($data) != $this->_size) {
+ throw new Exception('error reading from file');
+ }
+ return $data;
+ }
+
+ // Read $size bytes
+ public function read($size) {
+ return $this->nextSlice($size)->readAll();
+ }
+
+ // Read variable-length integer
+ public function readVarInt($signed=FALSE) {
+ // Read size and remove flag
+ $n = ord($this->read(1));
+ $size = 0;
+ if ($n == 0) {
+ throw new Exception('not supported: variable-length integer too long');
+ }
+ $flag = 0x80;
+ while (($n & $flag) == 0) {
+ $flag = $flag >> 1;
+ $size++;
+ }
+ $n -= $flag;
+
+ // Read remaining data
+ $rawInt = $this->read($size);
+
+ // Check for all ones
+ if ($n == $flag - 1 && $rawInt == str_repeat("\xFF", $size)) {
+ return NULL;
+ }
+
+ // Range shift for signed integers
+ if ($signed) {
+ if ($flag == 0x01) {
+ $n = ord($rawInt[0]) - 0x80;
+ $rawInt = $rawInt.substr(1);
+ } else {
+ $n -= ($flag >> 1);
+ }
+ }
+
+ // Convert to integer
+ $n = ebmlDecodeInt($rawInt, FALSE, $n);
+
+ // Range shift for signed integers
+ if ($signed) {
+ if ($n == PHP_INT_MAX) {
+ $n = floatval($n);
+ }
+ $n++;
+ }
+
+ return $n;
+ }
+}
+
+// EBML element
+class EBMLElement {
+ private $_id;
+ private $_name;
+ private $_datatype;
+ private $_content;
+ private $_headSize;
+
+ public function __construct($id, $content, $headSize) {
+ global $EBML_ELEMENTS;
+ $this->_id = $id;
+ $this->_name = $EBML_ELEMENTS->name($this->_id);
+ $this->_datatype = $EBML_ELEMENTS->datatype($this->_id);
+ $this->_content = $content;
+ $this->_headSize = $headSize;
+ }
+
+ public function id() {return $this->_id;}
+ public function name() {return $this->_name;}
+ public function datatype() {return $this->_datatype;}
+ public function content() {return $this->_content;}
+ public function headSize() {return $this->_headSize;}
+
+ // Total size of element (including ID and datasize)
+ public function size() {
+ return $this->_headSize + $this->_content->size();
+ }
+
+ // Read and interpret content
+ public function value() {
+ if ($this->_datatype == 'binary') {
+ return $this->_content;
+ } else {
+ return ebmlDecode($this->_content->readAll(), $this->_datatype);
+ }
+ }
+}
+
+// Iterate over EBML elements in data
+class EBMLElementList extends EBMLElement implements Iterator {
+ private $_cache;
+ private $_position;
+ private static $MAX_ELEMENTS = 10000;
+
+ public function __construct($id, $content, $headSize) {
+ parent::__construct($id, $content, $headSize);
+ $this->_cache = array();
+ $this->_position = 0;
+ }
+
+ public function rewind() {
+ $this->_position = 0;
+ }
+
+ public function current() {
+ if ($this->valid()) {
+ return $this->_cache[$this->_position];
+ } else {
+ return NULL;
+ }
+ }
+
+ public function key() {
+ return $this->_position;
+ }
+
+ public function next() {
+ $this->_position += $this->current()->size();
+ if ($this->content()->size() !== NULL && $this->_position > $this->content()->size()) {
+ throw new Exception('unexpected end of data');
+ }
+ }
+
+ public function valid() {
+ global $EBML_ELEMENTS;
+ if (isset($this->_cache[$this->_position])) return TRUE;
+ $this->content()->setPosition($this->_position);
+ if ($this->content()->endOfData()) return FALSE;
+ $id = $this->content()->readVarInt();
+ if ($id === NULL) throw new Exception('invalid ID');
+ if ($this->content()->size() === NULL && !$EBML_ELEMENTS->validChild($this->id(), $id)) {
+ $this->content()->setSize($this->_position);
+ return FALSE;
+ }
+ $size = $this->content()->readVarInt();
+ $headSize = $this->content()->position() - $this->_position;
+ $content = $this->content()->nextSlice($size);
+ if ($EBML_ELEMENTS->datatype($id) == 'container') {
+ $element = new EBMLElementList($id, $content, $headSize);
+ } else {
+ if ($size === NULL) {
+ throw new Exception('non-container element of unknown size');
+ }
+ $element = new EBMLElement($id, $content, $headSize);
+ }
+ $this->_cache[$this->_position] = $element;
+ return TRUE;
+ }
+
+ // Total size of element (including ID and size)
+ public function size() {
+ if ($this->content()->size() === NULL) {
+ $iElement = 0;
+ foreach ($this as $element) { // iterate over elements to find end
+ $iElement++;
+ if ($iElement > self::$MAX_ELEMENTS) throw new Exception('not supported: too many elements');
+ }
+ }
+ return $this->headSize() + $this->content()->size();
+ }
+
+ // Read and interpret content
+ public function value() {
+ return $this;
+ }
+
+ // Get element value by name
+ public function get($name, $defaultValue=NULL) {
+ $iElement = 0;
+ foreach ($this as $element) {
+ $iElement++;
+ if ($iElement > self::$MAX_ELEMENTS) throw new Exception('not supported: too many elements');
+ if (strtoupper($element->name()) == strtoupper($name)) {
+ return $element->value();
+ }
+ }
+ return $defaultValue;
+ }
+}
+
+// Parse block
+class MatroskaBlock {
+ const LACING_NONE = 0;
+ const LACING_XIPH = 1;
+ const LACING_EBML = 3;
+ const LACING_FIXED = 2;
+ public $trackNumber;
+ public $timecode;
+ public $keyframe;
+ public $invisible;
+ public $lacing;
+ public $discardable;
+ public $frames;
+
+ public function __construct($reader) {
+ # Header
+ $this->trackNumber = $reader->readVarInt();
+ $this->timecode = ebmlDecodeInt($reader->read(2), TRUE);
+ $flags = ord($reader->read(1));
+ if (($flags & 0x70) != 0) {
+ throw new Exception('reserved flags set');
+ }
+ $this->keyframe = (($flags & 0x80) != 0);
+ $this->invisible = (($flags & 0x08) != 0);
+ $this->lacing = ($flags >> 1) & 0x03;
+ $this->discardable = (($flags & 0x01) != 0);
+
+ # Lacing sizes
+ if ($this->lacing == self::LACING_NONE) {
+ $nsizes = 0;
+ } else {
+ $nsizes = ord($reader->read(1));
+ }
+ $sizes = array();
+ switch ($this->lacing) {
+ case self::LACING_XIPH:
+ for ($i = 0; $i < $nsizes; $i++) {
+ $size = 0;
+ $x = 255;
+ while ($x == 255) {
+ $x = ord($reader->read(1));
+ $size += $x;
+ if ($size > 65536) throw new Exception('not supported: laced frame too long');
+ }
+ $sizes[$i] = $size;
+ }
+ break;
+ case self::LACING_EBML:
+ $size = 0;
+ for ($i = 0; $i < $nsizes; $i++) {
+ $dsize = $reader->readVarInt($i != 0);
+ if ($dsize === NULL || $size + $dsize < 0) {
+ throw new Exception('invalid frame size');
+ }
+ $size += $dsize;
+ $sizes[$i] = $size;
+ }
+ break;
+ case self::LACING_FIXED:
+ $lenRemaining = $reader->size() - $reader->position();
+ if ($lenRemaining % ($nsizes + 1) != 0) {
+ throw new Exception('data size not divisible by frame count');
+ }
+ $size = (int) ($lenRemaining / ($nsizes + 1));
+ for ($i = 0; $i < $nsizes; $i++) {
+ $sizes[$i] = $size;
+ }
+ break;
+ }
+
+ # Frames
+ $this->frames = array();
+ for ($i = 0; $i < $nsizes; $i++) {
+ $this->frames[$i] = $reader->nextSlice($sizes[$i]);
+ }
+ $this->frames[$nsizes] = $reader->nextSlice($reader->size() - $reader->position());
+ }
+}
+
+// Create element list from $fileHandle
+function readMatroska($fileHandle) {
+ $reader = new EBMLReader($fileHandle);
+ if ($reader->read(4) != "\x1a\x45\xdf\xa3") {
+ throw new Exception('not an EBML file');
+ }
+ $root = new EBMLElementList('root', $reader, 0);
+ $header = $root->get('EBML');
+ $ebmlVersion = $header->get('EBMLReadVersion', 1);
+ $docType = $header->get('DocType');
+ $docTypeVersion = $header->get('DocTypeReadVersion', 1);
+ if ($ebmlVersion != 1) {
+ throw new Exception('unsupported EBML version');
+ }
+ if ($docType != 'matroska' && $docType != 'webm') {
+ throw new Exception ('unsupported document type');
+ }
+ if ($docTypeVersion < 1 || $docTypeVersion > 4) {
+ throw new Exception ('unsupported document type version');
+ }
+ return $root;
+}
+
+function ebmlEncodeVarInt($n) {
+ $data = '';
+ $flag = 0x80;
+ while ($n >= $flag) {
+ if ($flag == 0) {
+ throw new Exception('not supported: number too large');
+ }
+ $data = chr($n & 0xFF) . $data;
+ $n = $n >> 8;
+ $flag = $flag >> 1;
+ }
+ $data = chr($n | $flag) . $data;
+ return $data;
+}
+
+function ebmlEncodeElementName($name) {
+ global $EBML_ELEMENTS;
+ return ebmlEncodeVarInt($EBML_ELEMENTS->id($name));
+}
+
+function ebmlEncodeElement($name, $content) {
+ return ebmlEncodeElementName($name) . ebmlEncodeVarInt(strlen($content)) . $content;
+}
diff --git a/inc/lib/webm/player.php b/inc/lib/webm/player.php
new file mode 100644
index 00000000..bf4a259d
--- /dev/null
+++ b/inc/lib/webm/player.php
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
src="">
+ Your browser does not support HTML5 video. [Download]
+
+
+
+
diff --git a/inc/lib/webm/posthandler.php b/inc/lib/webm/posthandler.php
new file mode 100644
index 00000000..50adbe80
--- /dev/null
+++ b/inc/lib/webm/posthandler.php
@@ -0,0 +1,49 @@
+has_file && $post->extension == 'webm') {
+ require_once dirname(__FILE__) . '/videodata.php';
+ $videoDetails = videoData($post->file_path);
+ if (!isset($videoDetails['container']) || $videoDetails['container'] != 'webm') return "not a WebM file";
+
+ // Set thumbnail
+ $thumbName = $board['dir'] . $config['dir']['thumb'] . $post->file_id . '.webm';
+ if ($config['spoiler_images'] && isset($_POST['spoiler'])) {
+ // Use spoiler thumbnail
+ $post->thumb = 'spoiler';
+ $size = @getimagesize($config['spoiler_image']);
+ $post->thumbwidth = $size[0];
+ $post->thumbheight = $size[1];
+ } elseif (isset($videoDetails['frame']) && $thumbFile = fopen($thumbName, 'wb')) {
+ // Use single frame from video as pseudo-thumbnail
+ fwrite($thumbFile, $videoDetails['frame']);
+ fclose($thumbFile);
+ $post->thumb = $post->file_id . '.webm';
+ } else {
+ // Fall back to file thumbnail
+ $post->thumb = 'file';
+ }
+ unset($videoDetails['frame']);
+
+ // Set width and height
+ if (isset($videoDetails['width']) && isset($videoDetails['height'])) {
+ $post->width = $videoDetails['width'];
+ $post->height = $videoDetails['height'];
+ if ($post->thumb != 'file' && $post->thumb != 'spoiler') {
+ $thumbMaxWidth = $post->op ? $config['thumb_op_width'] : $config['thumb_width'];
+ $thumbMaxHeight = $post->op ? $config['thumb_op_height'] : $config['thumb_height'];
+ if ($videoDetails['width'] > $thumbMaxWidth || $videoDetails['height'] > $thumbMaxHeight) {
+ $post->thumbwidth = min($thumbMaxWidth, intval(round($videoDetails['width'] * $thumbMaxHeight / $videoDetails['height'])));
+ $post->thumbheight = min($thumbMaxHeight, intval(round($videoDetails['height'] * $thumbMaxWidth / $videoDetails['width'])));
+ } else {
+ $post->thumbwidth = $videoDetails['width'];
+ $post->thumbheight = $videoDetails['height'];
+ }
+ }
+ }
+ }
+}
diff --git a/inc/lib/webm/videodata.php b/inc/lib/webm/videodata.php
new file mode 100644
index 00000000..d54d484b
--- /dev/null
+++ b/inc/lib/webm/videodata.php
@@ -0,0 +1,173 @@
+get('Video');
+ if (isset($videoAttr)) {
+ if ($videoAttr->get('StereoMode') !== NULL) $version = 3;
+ if ($videoAttr->get('AlphaMode') !== NULL) $version = 3;
+ }
+ if ($videoTrack->get('CodecDelay') !== NULL) $version = 4;
+ if ($videoTrack->get('SeekPreRoll') !== NULL) $version = 4;
+ if ($frame->name() == 'BlockGroup' && $frame->get('DiscardPadding') !== NULL) $version = 4;
+
+ // EBML header
+ $ebml = ebmlEncodeElement('EBML',
+ ebmlEncodeElement('DocType', "webm")
+ . ebmlEncodeElement('DocTypeVersion', chr($version))
+ . ebmlEncodeElement('DocTypeReadVersion', "\x02")
+ );
+
+ // Segment
+ $info = ebmlEncodeElement('Info',
+ ebmlEncodeElement('Duration', "\x41\x20\x00\x00")
+ . ebmlEncodeElement('MuxingApp', 'ccframe')
+ . ebmlEncodeElement('WritingApp', 'ccframe')
+ );
+ $tracks = ebmlEncodeElement('Tracks',
+ ebmlEncodeElement('TrackEntry', $videoTrack->content()->readAll())
+ );
+ $cues = ebmlEncodeElement('Cues',
+ ebmlEncodeElement('CuePoint',
+ ebmlEncodeElement('CueTime', "\x00")
+ . ebmlEncodeElement('CueTrackPositions',
+ ebmlEncodeElement('CueTrack', pack('N', $videoTrack->get('TrackNumber')))
+ . ebmlEncodeElement('CueClusterPosition', pack('N', $lenSeekHead + strlen($info) + strlen($tracks) + $lenCues))
+ )
+ )
+ );
+ if (strlen($cues) != $lenCues) throw new Exception('length of Cues element wrong');
+ $cluster = ebmlEncodeElement('Cluster',
+ ebmlEncodeElement('Timecode', "\x00")
+ . ebmlEncodeElement($frame->name(), $frame->content()->readAll())
+ . ebmlEncodeElement('Void', '')
+ );
+ $seekHead = ebmlEncodeElement('SeekHead',
+ matroskaSeekElement('Info', $lenSeekHead)
+ . matroskaSeekElement('Tracks', $lenSeekHead + strlen($info))
+ . matroskaSeekElement('Cues', $lenSeekHead + strlen($info) + strlen($tracks))
+ . matroskaSeekElement('Cluster', $lenSeekHead + strlen($info) + strlen($tracks) + $lenCues)
+ );
+ if (strlen($seekHead) != $lenSeekHead) throw new Exception('length of SeekHead element wrong');
+ $segment = ebmlEncodeElement('Segment', $seekHead . $info . $tracks . $cues . $cluster);
+
+ return $ebml . $segment;
+}
+
+// Locate first WebM keyframe of track $trackNumber after timecode $skip
+function firstWebMFrame($segment, $trackNumber, $skip=0) {
+ foreach($segment as $x1) {
+ if ($x1->name() == 'Cluster') {
+ $cluserTimecode = $x1->Get('Timecode');
+ foreach($x1 as $blockGroup) {
+ $blockRaw = NULL;
+ if ($blockGroup->name() == 'SimpleBlock') {
+ $blockRaw = $blockGroup->value();
+ } elseif ($blockGroup->name() == 'BlockGroup') {
+ $blockRaw = $blockGroup->get('Block');
+ }
+ if (isset($blockRaw)) {
+ $block = new MatroskaBlock($blockRaw);
+ if ($block->trackNumber == $trackNumber && $block->keyframe) {
+ if (!isset($cluserTimecode) || $cluserTimecode + $block->timecode >= $skip) {
+ return $blockGroup;
+ } elseif (!isset($frame1)) {
+ $frame1 = $blockGroup;
+ }
+ }
+ }
+ }
+ }
+ }
+ return isset($frame1) ? $frame1 : NULL;
+}
+
+function videoData($filename) {
+ $data = array();
+
+ // Open file
+ $fileHandle = fopen($filename, 'rb');
+ if (!$fileHandle) {
+ error_log('could not open file');
+ return $data;
+ }
+
+ try {
+ $root = readMatroska($fileHandle);
+ $data['container'] = $root->get('EBML')->get('DocType');
+
+ // Locate segment information and tracks
+ $segment = $root->get('Segment');
+ if (!isset($segment)) throw new Exception('missing Segment element');
+
+ // Get segment information
+ $info = $segment->get('Info');
+ if (isset($info)) {
+ $timecodeScale = $info->get('TimecodeScale');
+ $duration = $info->get('Duration');
+ if (isset($timecodeScale) && isset($duration)) {
+ $data['duration'] = 1e-9 * $timecodeScale * $duration;
+ }
+ }
+
+ // Locate video track
+ $tracks = $segment->get('Tracks');
+ if (!isset($tracks)) throw new Exception('missing Tracks element');
+ foreach($tracks as $trackEntry) {
+ if ($trackEntry->name() == 'TrackEntry' && $trackEntry->get('TrackType') == 1) {
+ $videoTrack = $trackEntry;
+ break;
+ }
+ }
+ if (!isset($videoTrack)) throw new Exception('no video track');
+
+ // Get track information
+ $videoAttr = $videoTrack->get('Video');
+ if (!isset($videoAttr)) throw new Exception('missing video parameters');
+ $pixelWidth = $videoAttr->get('PixelWidth');
+ $pixelHeight = $videoAttr->get('PixelHeight');
+ if (!isset($pixelWidth) || !isset($pixelHeight)) throw new Exception('no width or height');
+ if ($pixelWidth == 0 || $pixelHeight == 0) throw new Exception('bad PixelWidth/PixelHeight');
+ $displayWidth = $videoAttr->get('DisplayWidth', $pixelWidth);
+ $displayHeight = $videoAttr->get('DisplayHeight', $pixelHeight);
+ if ($displayWidth == 0 || $displayHeight == 0) throw new Exception('bad DisplayWidth/DisplayHeight');
+ $data['width'] = $displayWidth;
+ $data['height'] = $displayHeight;
+
+ // Extract frame to use as thumbnail
+ if ($videoAttr->get('AlphaMode') != NULL) {
+ if (!($pixelWidth % 2 == 0 && $pixelHeight % 2 == 0 && $displayWidth % 2 == 0 && $displayHeight % 2 == 0)) {
+ throw new Exception('preview frame blocked due to Chromium bug');
+ }
+ }
+ $trackNumber = $videoTrack->get('TrackNumber');
+ if (!isset($trackNumber)) throw new Exception('missing track number');
+ if (isset($data['duration']) && $data['duration'] >= 5) {
+ $skip = 1e9 / $timecodeScale;
+ } else {
+ $skip = 0;
+ }
+ $frame = firstWebMFrame($segment, $trackNumber, $skip);
+ if (!isset($frame)) throw new Exception('no keyframes');
+ $data['frame'] = muxWebMFrame($videoTrack, $frame);
+ } catch (Exception $e) {
+ error_log($e->getMessage());
+ }
+
+ fclose($fileHandle);
+ return $data;
+}
--
cgit v1.3
From 09b64a289b30035024a202be06bf139346d4600e Mon Sep 17 00:00:00 2001
From: czaks
Date: Sun, 6 Apr 2014 21:29:09 +0200
Subject: matroska elements go there
---
containerchan/matroska-elements.txt | 224 ------------------------------------
inc/lib/webm/matroska-elements.txt | 224 ++++++++++++++++++++++++++++++++++++
2 files changed, 224 insertions(+), 224 deletions(-)
delete mode 100644 containerchan/matroska-elements.txt
create mode 100644 inc/lib/webm/matroska-elements.txt
(limited to 'inc/lib')
diff --git a/containerchan/matroska-elements.txt b/containerchan/matroska-elements.txt
deleted file mode 100644
index 07f8eecc..00000000
--- a/containerchan/matroska-elements.txt
+++ /dev/null
@@ -1,224 +0,0 @@
-a45dfa3 container EBML root
-286 uint EBMLVersion a45dfa3
-2f7 uint EBMLReadVersion a45dfa3
-2f2 uint EBMLMaxIDLength a45dfa3
-2f3 uint EBMLMaxSizeLength a45dfa3
-282 string DocType a45dfa3
-287 uint DocTypeVersion a45dfa3
-285 uint DocTypeReadVersion a45dfa3
-6c binary Void *
-3f binary CRC-32 *
-b538667 container SignatureSlot *
-3e8a uint SignatureAlgo b538667
-3e9a uint SignatureHash b538667
-3ea5 binary SignaturePublicKey b538667
-3eb5 binary Signature b538667
-3e5b container SignatureElements b538667
-3e7b container SignatureElementList 3e5b
-2532 binary SignedElement 3e7b
-8538067 container Segment root
-14d9b74 container SeekHead 8538067
-dbb container Seek 14d9b74
-13ab binary SeekID dbb
-13ac uint SeekPosition dbb
-549a966 container Info 8538067
-33a4 binary SegmentUID 549a966
-3384 string SegmentFilename 549a966
-1cb923 binary PrevUID 549a966
-1c83ab string PrevFilename 549a966
-1eb923 binary NextUID 549a966
-1e83bb string NextFilename 549a966
-444 binary SegmentFamily 549a966
-2924 container ChapterTranslate 549a966
-29fc uint ChapterTranslateEditionUID 2924
-29bf uint ChapterTranslateCodec 2924
-29a5 binary ChapterTranslateID 2924
-ad7b1 uint TimecodeScale 549a966
-489 float Duration 549a966
-461 date DateUTC 549a966
-3ba9 string Title 549a966
-d80 string MuxingApp 549a966
-1741 string WritingApp 549a966
-f43b675 container Cluster 8538067
-67 uint Timecode f43b675
-1854 container SilentTracks f43b675
-18d7 uint SilentTrackNumber 1854
-27 uint Position f43b675
-2b uint PrevSize f43b675
-23 binary SimpleBlock f43b675
-20 container BlockGroup f43b675
-21 binary Block 20
-22 binary BlockVirtual 20
-35a1 container BlockAdditions 20
-26 container BlockMore 35a1
-6e uint BlockAddID 26
-25 binary BlockAdditional 26
-1b uint BlockDuration 20
-7a uint ReferencePriority 20
-7b int ReferenceBlock 20
-7d int ReferenceVirtual 20
-24 binary CodecState 20
-35a2 int DiscardPadding 20
-e container Slices 20
-68 container TimeSlice e
-4c uint LaceNumber 68
-4d uint FrameNumber 68
-4b uint BlockAdditionID 68
-4e uint Delay 68
-4f uint SliceDuration 68
-48 container ReferenceFrame 20
-49 uint ReferenceOffset 48
-4a uint ReferenceTimeCode 48
-2f binary EncryptedBlock f43b675
-654ae6b container Tracks 8538067
-2e container TrackEntry 654ae6b
-57 uint TrackNumber 2e
-33c5 uint TrackUID 2e
-3 uint TrackType 2e
-39 uint FlagEnabled 2e
-8 uint FlagDefault 2e
-15aa uint FlagForced 2e
-1c uint FlagLacing 2e
-2de7 uint MinCache 2e
-2df8 uint MaxCache 2e
-3e383 uint DefaultDuration 2e
-34e7a uint DefaultDecodedFieldDuration 2e
-3314f float TrackTimecodeScale 2e
-137f int TrackOffset 2e
-15ee uint MaxBlockAdditionID 2e
-136e string Name 2e
-2b59c string Language 2e
-6 string CodecID 2e
-23a2 binary CodecPrivate 2e
-58688 string CodecName 2e
-3446 uint AttachmentLink 2e
-1a9697 string CodecSettings 2e
-1b4040 string CodecInfoURL 2e
-6b240 string CodecDownloadURL 2e
-2a uint CodecDecodeAll 2e
-2fab uint TrackOverlay 2e
-16aa uint CodecDelay 2e
-16bb uint SeekPreRoll 2e
-2624 container TrackTranslate 2e
-26fc uint TrackTranslateEditionUID 2624
-26bf uint TrackTranslateCodec 2624
-26a5 binary TrackTranslateTrackID 2624
-60 container Video 2e
-1a uint FlagInterlaced 60
-13b8 uint StereoMode 60
-13c0 uint AlphaMode 60
-13b9 uint OldStereoMode 60
-30 uint PixelWidth 60
-3a uint PixelHeight 60
-14aa uint PixelCropBottom 60
-14bb uint PixelCropTop 60
-14cc uint PixelCropLeft 60
-14dd uint PixelCropRight 60
-14b0 uint DisplayWidth 60
-14ba uint DisplayHeight 60
-14b2 uint DisplayUnit 60
-14b3 uint AspectRatioType 60
-eb524 binary ColourSpace 60
-fb523 float GammaValue 60
-383e3 float FrameRate 60
-61 container Audio 2e
-35 float SamplingFrequency 61
-38b5 float OutputSamplingFrequency 61
-1f uint Channels 61
-3d7b binary ChannelPositions 61
-2264 uint BitDepth 61
-62 container TrackOperation 2e
-63 container TrackCombinePlanes 62
-64 container TrackPlane 63
-65 uint TrackPlaneUID 64
-66 uint TrackPlaneType 64
-69 container TrackJoinBlocks 62
-6d uint TrackJoinUID 69
-40 uint TrickTrackUID 2e
-41 binary TrickTrackSegmentUID 2e
-46 uint TrickTrackFlag 2e
-47 uint TrickMasterTrackUID 2e
-44 binary TrickMasterTrackSegmentUID 2e
-2d80 container ContentEncodings 2e
-2240 container ContentEncoding 2d80
-1031 uint ContentEncodingOrder 2240
-1032 uint ContentEncodingScope 2240
-1033 uint ContentEncodingType 2240
-1034 container ContentCompression 2240
-254 uint ContentCompAlgo 1034
-255 binary ContentCompSettings 1034
-1035 container ContentEncryption 2240
-7e1 uint ContentEncAlgo 1035
-7e2 binary ContentEncKeyID 1035
-7e3 binary ContentSignature 1035
-7e4 binary ContentSigKeyID 1035
-7e5 uint ContentSigAlgo 1035
-7e6 uint ContentSigHashAlgo 1035
-c53bb6b container Cues 8538067
-3b container CuePoint c53bb6b
-33 uint CueTime 3b
-37 container CueTrackPositions 3b
-77 uint CueTrack 37
-71 uint CueClusterPosition 37
-70 uint CueRelativePosition 37
-32 uint CueDuration 37
-1378 uint CueBlockNumber 37
-6a uint CueCodecState 37
-5b container CueReference 37
-16 uint CueRefTime 5b
-17 uint CueRefCluster 5b
-135f uint CueRefNumber 5b
-6b uint CueRefCodecState 5b
-941a469 container Attachments 8538067
-21a7 container AttachedFile 941a469
-67e string FileDescription 21a7
-66e string FileName 21a7
-660 string FileMimeType 21a7
-65c binary FileData 21a7
-6ae uint FileUID 21a7
-675 binary FileReferral 21a7
-661 uint FileUsedStartTime 21a7
-662 uint FileUsedEndTime 21a7
-43a770 container Chapters 8538067
-5b9 container EditionEntry 43a770
-5bc uint EditionUID 5b9
-5bd uint EditionFlagHidden 5b9
-5db uint EditionFlagDefault 5b9
-5dd uint EditionFlagOrdered 5b9
-36 container ChapterAtom 5b9 36
-33c4 uint ChapterUID 36
-1654 string ChapterStringUID 36
-11 uint ChapterTimeStart 36
-12 uint ChapterTimeEnd 36
-18 uint ChapterFlagHidden 36
-598 uint ChapterFlagEnabled 36
-2e67 binary ChapterSegmentUID 36
-2ebc uint ChapterSegmentEditionUID 36
-23c3 uint ChapterPhysicalEquiv 36
-f container ChapterTrack 36
-9 uint ChapterTrackNumber f
-0 container ChapterDisplay 36
-5 string ChapString 0
-37c string ChapLanguage 0
-37e string ChapCountry 0
-2944 container ChapProcess 36
-2955 uint ChapProcessCodecID 2944
-50d binary ChapProcessPrivate 2944
-2911 container ChapProcessCommand 2944
-2922 uint ChapProcessTime 2911
-2933 binary ChapProcessData 2911
-254c367 container Tags 8538067
-3373 container Tag 254c367
-23c0 container Targets 3373
-28ca uint TargetTypeValue 23c0
-23ca string TargetType 23c0
-23c5 uint TagTrackUID 23c0
-23c9 uint TagEditionUID 23c0
-23c4 uint TagChapterUID 23c0
-23c6 uint TagAttachmentUID 23c0
-27c8 container SimpleTag 3373 27c8
-5a3 string TagName 27c8
-47a string TagLanguage 27c8
-484 uint TagDefault 27c8
-487 string TagString 27c8
-485 binary TagBinary 27c8
diff --git a/inc/lib/webm/matroska-elements.txt b/inc/lib/webm/matroska-elements.txt
new file mode 100644
index 00000000..07f8eecc
--- /dev/null
+++ b/inc/lib/webm/matroska-elements.txt
@@ -0,0 +1,224 @@
+a45dfa3 container EBML root
+286 uint EBMLVersion a45dfa3
+2f7 uint EBMLReadVersion a45dfa3
+2f2 uint EBMLMaxIDLength a45dfa3
+2f3 uint EBMLMaxSizeLength a45dfa3
+282 string DocType a45dfa3
+287 uint DocTypeVersion a45dfa3
+285 uint DocTypeReadVersion a45dfa3
+6c binary Void *
+3f binary CRC-32 *
+b538667 container SignatureSlot *
+3e8a uint SignatureAlgo b538667
+3e9a uint SignatureHash b538667
+3ea5 binary SignaturePublicKey b538667
+3eb5 binary Signature b538667
+3e5b container SignatureElements b538667
+3e7b container SignatureElementList 3e5b
+2532 binary SignedElement 3e7b
+8538067 container Segment root
+14d9b74 container SeekHead 8538067
+dbb container Seek 14d9b74
+13ab binary SeekID dbb
+13ac uint SeekPosition dbb
+549a966 container Info 8538067
+33a4 binary SegmentUID 549a966
+3384 string SegmentFilename 549a966
+1cb923 binary PrevUID 549a966
+1c83ab string PrevFilename 549a966
+1eb923 binary NextUID 549a966
+1e83bb string NextFilename 549a966
+444 binary SegmentFamily 549a966
+2924 container ChapterTranslate 549a966
+29fc uint ChapterTranslateEditionUID 2924
+29bf uint ChapterTranslateCodec 2924
+29a5 binary ChapterTranslateID 2924
+ad7b1 uint TimecodeScale 549a966
+489 float Duration 549a966
+461 date DateUTC 549a966
+3ba9 string Title 549a966
+d80 string MuxingApp 549a966
+1741 string WritingApp 549a966
+f43b675 container Cluster 8538067
+67 uint Timecode f43b675
+1854 container SilentTracks f43b675
+18d7 uint SilentTrackNumber 1854
+27 uint Position f43b675
+2b uint PrevSize f43b675
+23 binary SimpleBlock f43b675
+20 container BlockGroup f43b675
+21 binary Block 20
+22 binary BlockVirtual 20
+35a1 container BlockAdditions 20
+26 container BlockMore 35a1
+6e uint BlockAddID 26
+25 binary BlockAdditional 26
+1b uint BlockDuration 20
+7a uint ReferencePriority 20
+7b int ReferenceBlock 20
+7d int ReferenceVirtual 20
+24 binary CodecState 20
+35a2 int DiscardPadding 20
+e container Slices 20
+68 container TimeSlice e
+4c uint LaceNumber 68
+4d uint FrameNumber 68
+4b uint BlockAdditionID 68
+4e uint Delay 68
+4f uint SliceDuration 68
+48 container ReferenceFrame 20
+49 uint ReferenceOffset 48
+4a uint ReferenceTimeCode 48
+2f binary EncryptedBlock f43b675
+654ae6b container Tracks 8538067
+2e container TrackEntry 654ae6b
+57 uint TrackNumber 2e
+33c5 uint TrackUID 2e
+3 uint TrackType 2e
+39 uint FlagEnabled 2e
+8 uint FlagDefault 2e
+15aa uint FlagForced 2e
+1c uint FlagLacing 2e
+2de7 uint MinCache 2e
+2df8 uint MaxCache 2e
+3e383 uint DefaultDuration 2e
+34e7a uint DefaultDecodedFieldDuration 2e
+3314f float TrackTimecodeScale 2e
+137f int TrackOffset 2e
+15ee uint MaxBlockAdditionID 2e
+136e string Name 2e
+2b59c string Language 2e
+6 string CodecID 2e
+23a2 binary CodecPrivate 2e
+58688 string CodecName 2e
+3446 uint AttachmentLink 2e
+1a9697 string CodecSettings 2e
+1b4040 string CodecInfoURL 2e
+6b240 string CodecDownloadURL 2e
+2a uint CodecDecodeAll 2e
+2fab uint TrackOverlay 2e
+16aa uint CodecDelay 2e
+16bb uint SeekPreRoll 2e
+2624 container TrackTranslate 2e
+26fc uint TrackTranslateEditionUID 2624
+26bf uint TrackTranslateCodec 2624
+26a5 binary TrackTranslateTrackID 2624
+60 container Video 2e
+1a uint FlagInterlaced 60
+13b8 uint StereoMode 60
+13c0 uint AlphaMode 60
+13b9 uint OldStereoMode 60
+30 uint PixelWidth 60
+3a uint PixelHeight 60
+14aa uint PixelCropBottom 60
+14bb uint PixelCropTop 60
+14cc uint PixelCropLeft 60
+14dd uint PixelCropRight 60
+14b0 uint DisplayWidth 60
+14ba uint DisplayHeight 60
+14b2 uint DisplayUnit 60
+14b3 uint AspectRatioType 60
+eb524 binary ColourSpace 60
+fb523 float GammaValue 60
+383e3 float FrameRate 60
+61 container Audio 2e
+35 float SamplingFrequency 61
+38b5 float OutputSamplingFrequency 61
+1f uint Channels 61
+3d7b binary ChannelPositions 61
+2264 uint BitDepth 61
+62 container TrackOperation 2e
+63 container TrackCombinePlanes 62
+64 container TrackPlane 63
+65 uint TrackPlaneUID 64
+66 uint TrackPlaneType 64
+69 container TrackJoinBlocks 62
+6d uint TrackJoinUID 69
+40 uint TrickTrackUID 2e
+41 binary TrickTrackSegmentUID 2e
+46 uint TrickTrackFlag 2e
+47 uint TrickMasterTrackUID 2e
+44 binary TrickMasterTrackSegmentUID 2e
+2d80 container ContentEncodings 2e
+2240 container ContentEncoding 2d80
+1031 uint ContentEncodingOrder 2240
+1032 uint ContentEncodingScope 2240
+1033 uint ContentEncodingType 2240
+1034 container ContentCompression 2240
+254 uint ContentCompAlgo 1034
+255 binary ContentCompSettings 1034
+1035 container ContentEncryption 2240
+7e1 uint ContentEncAlgo 1035
+7e2 binary ContentEncKeyID 1035
+7e3 binary ContentSignature 1035
+7e4 binary ContentSigKeyID 1035
+7e5 uint ContentSigAlgo 1035
+7e6 uint ContentSigHashAlgo 1035
+c53bb6b container Cues 8538067
+3b container CuePoint c53bb6b
+33 uint CueTime 3b
+37 container CueTrackPositions 3b
+77 uint CueTrack 37
+71 uint CueClusterPosition 37
+70 uint CueRelativePosition 37
+32 uint CueDuration 37
+1378 uint CueBlockNumber 37
+6a uint CueCodecState 37
+5b container CueReference 37
+16 uint CueRefTime 5b
+17 uint CueRefCluster 5b
+135f uint CueRefNumber 5b
+6b uint CueRefCodecState 5b
+941a469 container Attachments 8538067
+21a7 container AttachedFile 941a469
+67e string FileDescription 21a7
+66e string FileName 21a7
+660 string FileMimeType 21a7
+65c binary FileData 21a7
+6ae uint FileUID 21a7
+675 binary FileReferral 21a7
+661 uint FileUsedStartTime 21a7
+662 uint FileUsedEndTime 21a7
+43a770 container Chapters 8538067
+5b9 container EditionEntry 43a770
+5bc uint EditionUID 5b9
+5bd uint EditionFlagHidden 5b9
+5db uint EditionFlagDefault 5b9
+5dd uint EditionFlagOrdered 5b9
+36 container ChapterAtom 5b9 36
+33c4 uint ChapterUID 36
+1654 string ChapterStringUID 36
+11 uint ChapterTimeStart 36
+12 uint ChapterTimeEnd 36
+18 uint ChapterFlagHidden 36
+598 uint ChapterFlagEnabled 36
+2e67 binary ChapterSegmentUID 36
+2ebc uint ChapterSegmentEditionUID 36
+23c3 uint ChapterPhysicalEquiv 36
+f container ChapterTrack 36
+9 uint ChapterTrackNumber f
+0 container ChapterDisplay 36
+5 string ChapString 0
+37c string ChapLanguage 0
+37e string ChapCountry 0
+2944 container ChapProcess 36
+2955 uint ChapProcessCodecID 2944
+50d binary ChapProcessPrivate 2944
+2911 container ChapProcessCommand 2944
+2922 uint ChapProcessTime 2911
+2933 binary ChapProcessData 2911
+254c367 container Tags 8538067
+3373 container Tag 254c367
+23c0 container Targets 3373
+28ca uint TargetTypeValue 23c0
+23ca string TargetType 23c0
+23c5 uint TagTrackUID 23c0
+23c9 uint TagEditionUID 23c0
+23c4 uint TagChapterUID 23c0
+23c6 uint TagAttachmentUID 23c0
+27c8 container SimpleTag 3373 27c8
+5a3 string TagName 27c8
+47a string TagLanguage 27c8
+484 uint TagDefault 27c8
+487 string TagString 27c8
+485 binary TagBinary 27c8
--
cgit v1.3
From e99c638e260a4e3f883a16c7e53b41cbfb542691 Mon Sep 17 00:00:00 2001
From: czaks
Date: Sun, 6 Apr 2014 21:32:23 +0200
Subject: work on player.php (webm)
---
inc/lib/webm/player.php | 25 -------------------------
player.php | 25 +++++++++++++++++++++++++
2 files changed, 25 insertions(+), 25 deletions(-)
delete mode 100644 inc/lib/webm/player.php
create mode 100644 player.php
(limited to 'inc/lib')
diff --git a/inc/lib/webm/player.php b/inc/lib/webm/player.php
deleted file mode 100644
index bf4a259d..00000000
--- a/inc/lib/webm/player.php
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
src="">
- Your browser does not support HTML5 video. [Download]
-
-
-
-
diff --git a/player.php b/player.php
new file mode 100644
index 00000000..33f02215
--- /dev/null
+++ b/player.php
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
src="">
+ Your browser does not support HTML5 video. [Download]
+
+
+
+
--
cgit v1.3
From e741ca9b01ca02a9942514a76619790d603651b8 Mon Sep 17 00:00:00 2001
From: czaks
Date: Sun, 6 Apr 2014 21:56:34 +0200
Subject: update containerchan readme
---
inc/lib/webm/README.md | 43 +++++++++----------------------------------
1 file changed, 9 insertions(+), 34 deletions(-)
(limited to 'inc/lib')
diff --git a/inc/lib/webm/README.md b/inc/lib/webm/README.md
index 71036c07..baa7a641 100644
--- a/inc/lib/webm/README.md
+++ b/inc/lib/webm/README.md
@@ -1,49 +1,24 @@
-This project is an effort to enable imageboards to host small video clips. With modern video compression, it's possible to share much higher-quality videos in a few megabytes than what you can do with animated GIF files.
+This directory contains files being the integration of containerchan with vichan-devel imageboards.
-The software here extends [Tinyboard](http://tinyboard.org/) to display metadata and create pseudo-thumbnails for WebM video files. It is intended to work on very basic web hosting services, including any hosting service that can run Tinyboard. In particular, it does not depend on any external video conversion software such as FFmpeg or Libav. Rather, it parses the video container to extract a single frame from the video to use in place of a thumbnail. If you can run FFmpeg or Libav on your server, it's a good idea to modify this code to use those tools to create true thumbnails; in the future, an option will be added to enable this.
+Containerchan allows posting of webm files, like they were the regular images.
-A board using this code can be found at:
+An original board using this code can be found at:
http://containerchan.org/tb/demo/
-Be aware that this is beta software. Please report any bugs you find.
+The original repo containing the containerchan (possibly with no Tinyboard integration) can be found here:
+https://github.com/ccd0/containerchan
+
-Much of the code is not specific to Tinyboard, and you are welcome to use it in your own projects. See the [core](https://github.com/ccd0/containerchan/tree/core) branch for a version without material from Tinyboard.
+Be aware that this is beta software. Please report any bugs you find.
Installation
------------
-Create a directory named cc at the root of your Tinyboard installation. Upload these files into that directory.
-
-Replace the files templates/post_thread.html and templates/post_reply.html with the files given here.
-
-Move video.png to the static directory.
-
Add these lines to inc/instance-config.php:
$config['allowed_ext_files'][] = 'webm';
- $config['file_icons']['webm'] = 'video.png';
- $config['additional_javascript'][] = 'cc/settings.js';
- $config['additional_javascript'][] = 'cc/expandvideo.js';
- require_once 'cc/posthandler.php';
- event_handler('post', 'postHandler');
-
-And add this to stylesheets/style.css:
-
- video.post-image {
- display: block;
- float: left;
- margin: 10px 20px;
- border: none;
- }
- div.post video.post-image {
- padding: 0px;
- margin: 10px 25px 5px 5px;
- }
- span.settings {
- position: fixed;
- top: 1em;
- right: 1em;
- }
+ $config['additional_javascript'][] = 'js/webm-settings.js';
+ $config['additional_javascript'][] = 'js/expand-video.js';
License
-------
--
cgit v1.3