1
0
mirror of https://github.com/vichan-devel/vichan.git synced 2024-11-29 01:34:31 +01:00

Merge vichan-devel!

This commit is contained in:
root 2014-04-16 15:05:32 +00:00
commit e34fe06db1
254 changed files with 19484 additions and 900 deletions

27
.gitignore vendored
View File

@ -1,5 +1,18 @@
# static html # static html and json
*.html /*/*.html
/*/*.json
/*/res
/*/src
/*/thumb
/*/config.php
/*.html
# include some files though
!/templates/*.html
!/inc/config.php
# minify
/inc/lib/minify
# instance-config # instance-config
/inc/instance-config.php /inc/instance-config.php
@ -15,6 +28,16 @@
# other stuff # other stuff
.DS_Store .DS_Store
.htaccess
thumbs.db thumbs.db
Icon? Icon?
Thumbs.db Thumbs.db
*.patch
*.diff
*.rej
*.orig
*~
#vichan custom
favicon.ico
/static/spoiler.png

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "js/wPaint"]
path = js/wPaint
url = https://github.com/vichan-devel/wPaint.git

View File

@ -1,5 +1,5 @@
# License # License
Copyright (c) 2010-2013 Tinyboard Development Group (tinyboard.org) Copyright (c) 2010-2014 Tinyboard Development Group (tinyboard.org)
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,15 @@
Tinyboard - A lightweight PHP imageboard. Tinyboard - A lightweight PHP imageboard.
========================================== ==========================================
Tinyboard + vichan-devel
------------
Tinyboard branch taking lightweightness somewhat more liberally. Running live at
https://pl.vichan.net/ (Polish) and http://vichan.net/ (International; may be outdated).
It contains many changes from original Tinyboard, mainly in frontend area.
Support and announcements: https://int.vichan.net/devel/
About About
------------ ------------
Tinyboard is a free light-weight, fast, highly configurable and user-friendly Tinyboard is a free light-weight, fast, highly configurable and user-friendly
@ -63,6 +72,11 @@ find support from a variety of sources:
[irc.datnode.net #tinyboard](irc://irc.datnode.net/tinyboard). [irc.datnode.net #tinyboard](irc://irc.datnode.net/tinyboard).
* You may find help at [tinyboard.org](http://tinyboard.org/#help). * You may find help at [tinyboard.org](http://tinyboard.org/#help).
Tinyboard-Tools:
-----------------
## Directories
* ```tools/``` -- Command-line management scripts for Tinyboard. These should not be publicly executable.
License License
-------- --------
See [LICENSE.md](http://github.com/savetheinternet/Tinyboard/blob/master/LICENSE.md). See [LICENSE.md](http://github.com/savetheinternet/Tinyboard/blob/master/LICENSE.md).

11
attentionbar.php Normal file
View File

@ -0,0 +1,11 @@
<?php
require_once 'inc/functions.php';
checkBan();
$text = isset($_POST['text']) ? $_POST['text'] : '';
if(strlen($text)>0 && !preg_match('/a href/', $text)) {
file_put_contents("attentionbar.txt",htmlspecialchars($text));
if(strlen($_SERVER['HTTP_REFERER'])>0) { header('Location: ' . $_SERVER['HTTP_REFERER']); }
else { header('Location: /'); }
} else print(file_get_contents("attentionbar.txt"));
return;
?>

1
attentionbar.txt Normal file
View File

@ -0,0 +1 @@
- * ( Pasek Atencji ) * -

7
banned.php Normal file
View File

@ -0,0 +1,7 @@
<?php
require_once 'inc/functions.php';
checkBan();
print "<!doctype html><html><head><meta charset='utf-8'><title>"._("Banned?")."</title></head><body>";
print "<h1>"._("You are not banned.")."</h1>";
print "</body></html>";
?>

View File

@ -34,8 +34,16 @@ class Api {
'filename' => 'filename', 'filename' => 'filename',
'omitted' => 'omitted_posts', 'omitted' => 'omitted_posts',
'omitted_images' => 'omitted_images', 'omitted_images' => 'omitted_images',
'replies' => 'replies',
'images' => 'images',
'sticky' => 'sticky', 'sticky' => 'sticky',
'locked' => 'locked', 'locked' => 'locked',
'bump' => 'last_modified',
);
$this->threadsPageFields = array(
'id' => 'no',
'bump' => 'last_modified'
); );
if (isset($config['api']['extra_fields']) && gettype($config['api']['extra_fields']) == 'array'){ if (isset($config['api']['extra_fields']) && gettype($config['api']['extra_fields']) == 'array'){
@ -56,11 +64,13 @@ class Api {
'omitted_images' => 1, 'omitted_images' => 1,
'sticky' => 1, 'sticky' => 1,
'locked' => 1, 'locked' => 1,
'last_modified' => 1
); );
private function translatePost($post) { private function translatePost($post, $threadsPage = false) {
$apiPost = array(); $apiPost = array();
foreach ($this->postFields as $local => $translated) { $fields = $threadsPage ? $this->threadsPageFields : $this->postFields;
foreach ($fields as $local => $translated) {
if (!isset($post->$local)) if (!isset($post->$local))
continue; continue;
@ -72,10 +82,14 @@ class Api {
} }
if ($threadsPage) return $apiPost;
if (isset($post->filename)) { if (isset($post->filename)) {
$dotPos = strrpos($post->filename, '.'); $dotPos = strrpos($post->filename, '.');
$apiPost['filename'] = substr($post->filename, 0, $dotPos); $apiPost['filename'] = substr($post->filename, 0, $dotPos);
$apiPost['ext'] = substr($post->filename, $dotPos); $apiPost['ext'] = substr($post->filename, $dotPos);
$dotPos = strrpos($post->file, '.');
$apiPost['tim'] = substr($post->file, 0, $dotPos);
} }
// Handle country field // Handle country field
@ -93,14 +107,14 @@ class Api {
return $apiPost; return $apiPost;
} }
function translateThread(Thread $thread) { function translateThread(Thread $thread, $threadsPage = false) {
$apiPosts = array(); $apiPosts = array();
$op = $this->translatePost($thread); $op = $this->translatePost($thread, $threadsPage);
$op['resto'] = 0; if (!$threadsPage) $op['resto'] = 0;
$apiPosts['posts'][] = $op; $apiPosts['posts'][] = $op;
foreach ($thread->posts as $p) { foreach ($thread->posts as $p) {
$apiPosts['posts'][] = $this->translatePost($p); $apiPosts['posts'][] = $this->translatePost($p, $threadsPage);
} }
return $apiPosts; return $apiPosts;
@ -114,19 +128,19 @@ class Api {
return $apiPage; return $apiPage;
} }
function translateCatalogPage(array $threads) { function translateCatalogPage(array $threads, $threadsPage = false) {
$apiPage = array(); $apiPage = array();
foreach ($threads as $thread) { foreach ($threads as $thread) {
$ts = $this->translateThread($thread); $ts = $this->translateThread($thread, $threadsPage);
$apiPage['threads'][] = current($ts['posts']); $apiPage['threads'][] = current($ts['posts']);
} }
return $apiPage; return $apiPage;
} }
function translateCatalog($catalog) { function translateCatalog($catalog, $threadsPage = false) {
$apiCatalog = array(); $apiCatalog = array();
foreach ($catalog as $page => $threads) { foreach ($catalog as $page => $threads) {
$apiPage = $this->translateCatalogPage($threads); $apiPage = $this->translateCatalogPage($threads, $threadsPage);
$apiPage['page'] = $page; $apiPage['page'] = $page;
$apiCatalog[] = $apiPage; $apiCatalog[] = $apiPage;
} }

View File

@ -23,6 +23,7 @@
* *
*/ */
defined('TINYBOARD') or exit;
/* /*
* ======================= * =======================
@ -476,8 +477,10 @@
$config['auto_unicode'] = true; $config['auto_unicode'] = true;
// Whether to turn URLs into functional links. // Whether to turn URLs into functional links.
$config['markup_urls'] = true; $config['markup_urls'] = true;
// Optional URL prefix for links (eg. "http://anonym.to/?"). // Optional URL prefix for links (eg. "http://anonym.to/?").
$config['link_prefix'] = ''; $config['link_prefix'] = '';
$config['url_ads'] = &$config['link_prefix']; // leave alias
// Allow "uploading" images via URL as well. Users can enter the URL of the image and then Tinyboard will // Allow "uploading" images via URL as well. Users can enter the URL of the image and then Tinyboard will
// download it. Not usually recommended. // download it. Not usually recommended.
@ -518,11 +521,16 @@
// When true, a blank password will be used for files (not usable for deletion). // When true, a blank password will be used for files (not usable for deletion).
$config['field_disable_password'] = false; $config['field_disable_password'] = false;
// Attach country flags to posts. Requires the PHP "geoip" extension to be installed: // When true, users are instead presented a selectbox for email. Contains, blank, noko and sage.
// http://www.php.net/manual/en/intro.geoip.php. In the future, maybe I will find and include a proper $config['field_email_selectbox'] = false;
// pure-PHP geolocation library.
// Attach country flags to posts.
$config['country_flags'] = false; $config['country_flags'] = false;
// Load all country flags from one file
$config['country_flags_condensed'] = true;
$config['country_flags_condensed_css'] = 'static/flags/flags.css';
/* /*
* ==================== * ====================
* Ban settings * Ban settings
@ -558,7 +566,7 @@
$config['markup'][] = array("/'''(.+?)'''/", "<strong>\$1</strong>"); $config['markup'][] = array("/'''(.+?)'''/", "<strong>\$1</strong>");
$config['markup'][] = array("/''(.+?)''/", "<em>\$1</em>"); $config['markup'][] = array("/''(.+?)''/", "<em>\$1</em>");
$config['markup'][] = array("/\*\*(.+?)\*\*/", "<span class=\"spoiler\">\$1</span>"); $config['markup'][] = array("/\*\*(.+?)\*\*/", "<span class=\"spoiler\">\$1</span>");
// $config['markup'][] = array("/^[ |\t]*==(.+?)==[ |\t]*$/m", "<span class=\"heading\">\$1</span>"); $config['markup'][] = array("/^[ |\t]*==(.+?)==[ |\t]*$/m", "<span class=\"heading\">\$1</span>");
// Highlight PHP code wrapped in <code> tags (PHP 5.3+) // Highlight PHP code wrapped in <code> tags (PHP 5.3+)
// $config['markup'][] = array( // $config['markup'][] = array(
@ -675,6 +683,7 @@
// Thumbnail to use for the non-image file uploads. // Thumbnail to use for the non-image file uploads.
$config['file_icons']['default'] = 'file.png'; $config['file_icons']['default'] = 'file.png';
$config['file_icons']['zip'] = 'zip.png'; $config['file_icons']['zip'] = 'zip.png';
$config['file_icons']['webm'] = 'video.png';
// Example: Custom thumbnail for certain file extension. // Example: Custom thumbnail for certain file extension.
// $config['file_icons']['extension'] = 'some_file.png'; // $config['file_icons']['extension'] = 'some_file.png';
@ -708,6 +717,11 @@
// Display image identification links using regex.info/exif, TinEye and Google Images. // Display image identification links using regex.info/exif, TinEye and Google Images.
$config['image_identification'] = false; $config['image_identification'] = false;
// Number of posts in a "View Last X Posts" page
$config['noko50_count'] = 50;
// Number of posts a thread needs before it gets a "View Last X Posts" page.
// Set to an arbitrarily large value to disable.
$config['noko50_min'] = 100;
/* /*
* ==================== * ====================
* Board settings * Board settings
@ -733,7 +747,12 @@
// Number of reports you can create at once. // Number of reports you can create at once.
$config['report_limit'] = 3; $config['report_limit'] = 3;
// Allow unfiltered HTML in board subtitles. This is useful for placing icons and links. // Attention Whoring Bar
// REMEMBER TO CHMOD attentionbar.txt PROPERLY
// Oh, and add jQuery in additional_javascript.
$config['attention_bar'] = false;
// Allow unfiltered HTML in board subtitle. This is useful for placing icons and links.
$config['allow_subtitle_html'] = false; $config['allow_subtitle_html'] = false;
/* /*
@ -818,7 +837,7 @@
// ); // );
// Whether or not to put brackets around the whole board list // Whether or not to put brackets around the whole board list
$config['boardlist_wrap_bracket'] = true; $config['boardlist_wrap_bracket'] = false;
// Show page navigation links at the top as well. // Show page navigation links at the top as well.
$config['page_nav_top'] = false; $config['page_nav_top'] = false;
@ -843,6 +862,15 @@
// Automatically remove unnecessary whitespace when compiling HTML files from templates. // Automatically remove unnecessary whitespace when compiling HTML files from templates.
$config['minify_html'] = true; $config['minify_html'] = true;
/*
* Advertisement HTML to appear at the top and bottom of board pages.
*/
// $config['ad'] = array(
// 'top' => '',
// 'bottom' => '',
// );
// Display flags (when available). This config option has no effect unless poster flags are enabled (see // Display flags (when available). This config option has no effect unless poster flags are enabled (see
// $config['country_flags']). Disable this if you want all previously-assigned flags to be hidden. // $config['country_flags']). Disable this if you want all previously-assigned flags to be hidden.
$config['display_flags'] = true; $config['display_flags'] = true;
@ -993,6 +1021,7 @@
$config['error']['modexists'] = _('That mod <a href="?/users/%d">already exists</a>!'); $config['error']['modexists'] = _('That mod <a href="?/users/%d">already exists</a>!');
$config['error']['invalidtheme'] = _('That theme doesn\'t exist!'); $config['error']['invalidtheme'] = _('That theme doesn\'t exist!');
$config['error']['csrf'] = _('Invalid security token! Please go back and try again.'); $config['error']['csrf'] = _('Invalid security token! Please go back and try again.');
$config['error']['badsyntax'] = _('Your code contained PHP syntax errors. Please go back and correct them. PHP says: ');
/* /*
* ========================= * =========================
@ -1024,6 +1053,7 @@
// Location of files. // Location of files.
$config['file_index'] = 'index.html'; $config['file_index'] = 'index.html';
$config['file_page'] = '%d.html'; $config['file_page'] = '%d.html';
$config['file_page50'] = '%d+50.html';
$config['file_mod'] = 'mod.php'; $config['file_mod'] = 'mod.php';
$config['file_post'] = 'post.php'; $config['file_post'] = 'post.php';
$config['file_script'] = 'main.js'; $config['file_script'] = 'main.js';
@ -1048,6 +1078,9 @@
// Home directory. Used by themes. // Home directory. Used by themes.
$config['dir']['home'] = ''; $config['dir']['home'] = '';
// Location of a blank 1x1 gif file. Only used when country_flags_condensed is enabled
// $config['image_blank'] = 'static/blank.gif';
// Static images. These can be URLs OR base64 (data URI scheme). These are only used if // Static images. These can be URLs OR base64 (data URI scheme). These are only used if
// $config['font_awesome'] is false (default). // $config['font_awesome'] is false (default).
// $config['image_sticky'] = 'static/sticky.gif'; // $config['image_sticky'] = 'static/sticky.gif';
@ -1123,6 +1156,9 @@
// 'color:red;font-weight:bold' // Change tripcode style; optional // 'color:red;font-weight:bold' // Change tripcode style; optional
//); //);
// Enable the moving of single replies
$config['move_replies'] = false;
// How often (minimum) to purge the ban list of expired bans (which have been seen). Only works when // How often (minimum) to purge the ban list of expired bans (which have been seen). Only works when
// $config['cache'] is enabled and working. // $config['cache'] is enabled and working.
$config['purge_bans'] = 60 * 60 * 12; // 12 hours $config['purge_bans'] = 60 * 60 * 12; // 12 hours
@ -1388,6 +1424,28 @@
// 'db', // 'db',
// ); // );
/*
* ====================
* Public post search
* ====================
*/
$config['search'] = array();
// Enable the search form
$config['search']['enable'] = false;
// Maximal number of queries per IP address per minutes
$config['search']['queries_per_minutes'] = Array(15, 2);
// Global maximal number of queries per minutes
$config['search']['queries_per_minutes_all'] = Array(50, 2);
// Limit of search results
$config['search']['search_limit'] = 100;
// Boards for searching
//$config['search']['boards'] = array('a', 'b', 'c', 'd', 'e');
/* /*
* ==================== * ====================
* Events (PHP 5.3.0+) * Events (PHP 5.3.0+)
@ -1415,7 +1473,7 @@
// Whether or not to enable the 4chan-compatible API, disabled by default. See // Whether or not to enable the 4chan-compatible API, disabled by default. See
// https://github.com/4chan/4chan-API for API specification. // https://github.com/4chan/4chan-API for API specification.
$config['api']['enabled'] = false; $config['api']['enabled'] = true;
// Extra fields in to be shown in the array that are not in the 4chan-API. You can get these by taking a // Extra fields in to be shown in the array that are not in the 4chan-API. You can get these by taking a
// look at the schema for posts_ tables. The array should be formatted as $db_column => $translated_name. // look at the schema for posts_ tables. The array should be formatted as $db_column => $translated_name.
@ -1472,3 +1530,8 @@
// is the absolute maximum, because MySQL cannot handle table names greater than 64 characters. // is the absolute maximum, because MySQL cannot handle table names greater than 64 characters.
$config['board_regex'] = '[0-9a-zA-Z$_\x{0080}-\x{FFFF}]{1,58}'; $config['board_regex'] = '[0-9a-zA-Z$_\x{0080}-\x{FFFF}]{1,58}';
// Youtube.js embed HTML code
$config['youtube_js_html'] = '<div class="video-container" data-video="$2">'.
'<a href="$0" target="_blank" class="file">'.
'<img style="width:360px;height:270px;" src="//img.youtube.com/vi/$2/0.jpg" class="post-image"/>'.
'</a></div>';

View File

@ -19,19 +19,23 @@ function format_bytes($size) {
return round($size, 2).$units[$i]; return round($size, 2).$units[$i];
} }
function doBoardListPart($list, $root) { function doBoardListPart($list, $root, &$boards) {
global $config; global $config;
$body = ''; $body = '';
foreach ($list as $board) { foreach ($list as $key => $board) {
if (is_array($board)) if (is_array($board))
$body .= ' [' . doBoardListPart($board, $root) . '] '; $body .= ' <span class="sub" data-description="' . $key . '">[' . doBoardListPart($board, $root, $boards) . ']</span> ';
// $body .= ' <span class="sub">[' . doBoardListPart($board, $root) . ']</span> ';
else { else {
if (($key = array_search($board, $list)) && gettype($key) == 'string') { if (gettype($key) == 'string') {
$body .= ' <a href="' . $board . '">' . $key . '</a> /'; $body .= ' <a href="' . $board . '">' . $key . '</a> /';
} else { } else {
$body .= ' <a href="' . $root . $board . '/' . $config['file_index'] . '">' . $board . '</a> /'; $title = '';
if (isset ($boards[$board])) {
$title = ' title="'.$boards[$board].'"';
}
$body .= ' <a href="' . $root . $board . '/' . $config['file_index'] . '"'.$title.'>' . $board . '</a> /';
} }
} }
} }
@ -45,14 +49,24 @@ function createBoardlist($mod=false) {
if (!isset($config['boards'])) return array('top'=>'','bottom'=>''); if (!isset($config['boards'])) return array('top'=>'','bottom'=>'');
$body = doBoardListPart($config['boards'], $mod?'?/':$config['root']); $xboards = listBoards();
$boards = array();
foreach ($xboards as $val) {
$boards[$val['uri']] = $val['title'];
}
$body = doBoardListPart($config['boards'], $mod?'?/':$config['root'], $boards);
if ($config['boardlist_wrap_bracket'] && !preg_match('/\] $/', $body)) if ($config['boardlist_wrap_bracket'] && !preg_match('/\] $/', $body))
$body = '[' . $body . ']'; $body = '[' . $body . ']';
$body = trim($body); $body = trim($body);
// Message compact-boardlist.js faster, so that page looks less ugly during loading
$top = "<script type='text/javascript'>if (typeof do_boardlist != 'undefined') do_boardlist();</script>";
return array( return array(
'top' => '<div class="boardlist">' . $body . '</div>', 'top' => '<div class="boardlist">' . $body . '</div>' . $top,
'bottom' => '<div class="boardlist bottom">' . $body . '</div>' 'bottom' => '<div class="boardlist bottom">' . $body . '</div>'
); );
} }
@ -74,6 +88,13 @@ function error($message, $priority = true, $debug_stuff = false) {
$debug_stuff = array_combine(array('SQLSTATE', 'Error code', 'Error message'), $db_error); $debug_stuff = array_combine(array('SQLSTATE', 'Error code', 'Error message'), $db_error);
} }
// Return the bad request header, necessary for AJAX posts
// czaks: is it really so? the ajax errors only work when this is commented out
// better yet use it when ajax is disabled
if (!isset ($_POST['json_response'])) {
header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
}
// Is there a reason to disable this? // Is there a reason to disable this?
if (isset($_POST['json_response'])) { if (isset($_POST['json_response'])) {
header('Content-Type: text/json; charset=utf-8'); header('Content-Type: text/json; charset=utf-8');
@ -375,13 +396,18 @@ class Post {
$built .= ' ' . secure_link_confirm($config['mod']['link_deletefile'], _('Delete file'), _('Are you sure you want to delete this file?'), $board['dir'] . 'deletefile/' . $this->id); $built .= ' ' . secure_link_confirm($config['mod']['link_deletefile'], _('Delete file'), _('Are you sure you want to delete this file?'), $board['dir'] . 'deletefile/' . $this->id);
// Spoiler file (keep post) // Spoiler file (keep post)
if (!empty($this->file) && $this->file != 'deleted' && $this->thumb != 'spoiler' && hasPermission($config['mod']['spoilerimage'], $board['uri'], $this->mod) && $config['spoiler_images']) if (!empty($this->file) && $this->file != "deleted" && $this->file != null && $this->thumb != 'spoiler' && hasPermission($config['mod']['spoilerimage'], $board['uri'], $this->mod) && $config['spoiler_images'])
$built .= ' ' . secure_link_confirm($config['mod']['link_spoilerimage'], 'Spoiler File', 'Are you sure you want to spoiler this file?', $board['uri'] . '/spoiler/' . $this->id); $built .= ' ' . secure_link_confirm($config['mod']['link_spoilerimage'], _('Spoiler File'), _('Are you sure you want to spoiler this file?'), $board['uri'] . '/spoiler/' . $this->id);
// Move post
if (hasPermission($config['mod']['move'], $board['uri'], $this->mod) && $config['move_replies'])
$built .= ' <a title="'._('Move reply to another board').'" href="?/' . $board['uri'] . '/move_reply/' . $this->id . '">' . $config['mod']['link_move'] . '</a>';
// Edit post // Edit post
if (hasPermission($config['mod']['editpost'], $board['uri'], $this->mod)) if (hasPermission($config['mod']['editpost'], $board['uri'], $this->mod))
$built .= ' <a title="'._('Edit post').'" href="?/' . $board['dir'] . 'edit' . ($config['mod']['raw_html_default'] ? '_raw' : '') . '/' . $this->id . '">' . $config['mod']['link_editpost'] . '</a>'; $built .= ' <a title="'._('Edit post').'" href="?/' . $board['dir'] . 'edit' . ($config['mod']['raw_html_default'] ? '_raw' : '') . '/' . $this->id . '">' . $config['mod']['link_editpost'] . '</a>';
if (!empty($built)) if (!empty($built))
$built = '<span class="controls">' . $built . '</span>'; $built = '<span class="controls">' . $built . '</span>';
} }
@ -446,6 +472,9 @@ class Thread {
public function add(Post $post) { public function add(Post $post) {
$this->posts[] = $post; $this->posts[] = $post;
} }
public function postCount() {
return count($this->posts) + $this->omitted;
}
public function postControls() { public function postControls() {
global $board, $config; global $board, $config;
@ -477,8 +506,8 @@ class Thread {
$built .= ' ' . secure_link_confirm($config['mod']['link_deletefile'], _('Delete file'), _('Are you sure you want to delete this file?'), $board['dir'] . 'deletefile/' . $this->id); $built .= ' ' . secure_link_confirm($config['mod']['link_deletefile'], _('Delete file'), _('Are you sure you want to delete this file?'), $board['dir'] . 'deletefile/' . $this->id);
// Spoiler file (keep post) // Spoiler file (keep post)
if (!empty($this->file) && $this->file != 'deleted' && $this->thumb != 'spoiler' && hasPermission($config['mod']['spoilerimage'], $board['uri'], $this->mod) && $config['spoiler_images']) if (!empty($this->file) && $this->file != "deleted" && $this->file != null && $this->thumb != 'spoiler' && hasPermission($config['mod']['spoilerimage'], $board['uri'], $this->mod) && $config['spoiler_images'])
$built .= ' ' . secure_link_confirm($config['mod']['link_spoilerimage'], 'Spoiler File', 'Are you sure you want to spoiler this file?', $board['uri'] . '/spoiler/' . $this->id); $built .= ' ' . secure_link_confirm($config['mod']['link_spoilerimage'], _('Spoiler File'), _('Are you sure you want to spoiler this file?'), $board['uri'] . '/spoiler/' . $this->id);
// Sticky // Sticky
if (hasPermission($config['mod']['sticky'], $board['uri'], $this->mod)) if (hasPermission($config['mod']['sticky'], $board['uri'], $this->mod))
@ -517,12 +546,14 @@ class Thread {
return fraction($this->filewidth, $this->fileheight, ':'); return fraction($this->filewidth, $this->fileheight, ':');
} }
public function build($index=false) { public function build($index=false, $isnoko50=false) {
global $board, $config, $debug; global $board, $config, $debug;
$hasnoko50 = $this->postCount() >= $config['noko50_min'];
event('show-thread', $this); event('show-thread', $this);
$built = Element('post_thread.html', array('config' => $config, 'board' => $board, 'post' => &$this, 'index' => $index)); $built = Element('post_thread.html', array('config' => $config, 'board' => $board, 'post' => &$this, 'index' => $index, 'hasnoko50' => $hasnoko50, 'isnoko50' => $isnoko50));
return $built; return $built;
} }

View File

@ -28,8 +28,25 @@ register_shutdown_function('fatal_error_handler');
mb_internal_encoding('UTF-8'); mb_internal_encoding('UTF-8');
loadConfig(); loadConfig();
function init_locale($locale, $error='error') {
if (_setlocale(LC_ALL, $locale) === false) {
$error('The specified locale (' . $locale . ') does not exist on your platform!');
}
if (extension_loaded('gettext')) {
bindtextdomain('tinyboard', './inc/locale');
bind_textdomain_codeset('tinyboard', 'UTF-8');
textdomain('tinyboard');
} else {
_bindtextdomain('tinyboard', './inc/locale');
_bind_textdomain_codeset('tinyboard', 'UTF-8');
_textdomain('tinyboard');
}
}
$current_locale = 'en';
function loadConfig() { function loadConfig() {
global $board, $config, $__ip, $debug, $__version, $microtime_start; global $board, $config, $__ip, $debug, $__version, $microtime_start, $current_locale;
$error = function_exists('error') ? 'error' : 'basic_error_function_because_the_other_isnt_loaded_yet'; $error = function_exists('error') ? 'error' : 'basic_error_function_because_the_other_isnt_loaded_yet';
@ -70,16 +87,43 @@ function loadConfig() {
$config[$key] = array(); $config[$key] = array();
} }
require 'inc/config.php';
if (!file_exists('inc/instance-config.php')) if (!file_exists('inc/instance-config.php'))
$error('Tinyboard is not configured! Create inc/instance-config.php.'); $error('Tinyboard is not configured! Create inc/instance-config.php.');
// Initialize locale as early as possible
$config['locale'] = 'en';
$configstr = file_get_contents('inc/instance-config.php');
if (isset($board['dir']) && file_exists($board['dir'] . '/config.php')) {
$configstr .= file_get_contents($board['dir'] . '/config.php');
}
$matches = array();
preg_match_all('/[^\/*#]\$config\s*\[\s*[\'"]locale[\'"]\s*\]\s*=\s*([\'"])(.*?)\1/', $configstr, $matches);
if ($matches && isset ($matches[2]) && $matches[2]) {
$matches = $matches[2];
$config['locale'] = $matches[count($matches)-1];
}
if ($config['locale'] != $current_locale) {
$current_locale = $config['locale'];
init_locale($config['locale'], $error);
}
require 'inc/config.php';
require 'inc/instance-config.php'; require 'inc/instance-config.php';
if (isset($board['dir']) && file_exists($board['dir'] . '/config.php')) { if (isset($board['dir']) && file_exists($board['dir'] . '/config.php')) {
require $board['dir'] . '/config.php'; require $board['dir'] . '/config.php';
} }
if ($config['locale'] != $current_locale) {
$current_locale = $config['locale'];
init_locale($config['locale'], $error);
}
if (!isset($__version)) if (!isset($__version))
$__version = file_exists('.installed') ? trim(file_get_contents('.installed')) : false; $__version = file_exists('.installed') ? trim(file_get_contents('.installed')) : false;
$config['version'] = $__version; $config['version'] = $__version;
@ -107,7 +151,10 @@ function loadConfig() {
'|' . '|' .
str_replace('%s', $config['board_regex'], preg_quote($config['board_path'], '/')) . str_replace('%s', $config['board_regex'], preg_quote($config['board_path'], '/')) .
preg_quote($config['dir']['res'], '/') . preg_quote($config['dir']['res'], '/') .
str_replace('%d', '\d+', preg_quote($config['file_page'], '/')) . '(' .
str_replace('%d', '\d+', preg_quote($config['file_page'], '/')) . '|' .
str_replace('%d', '\d+', preg_quote($config['file_page50'], '/')) .
')' .
'|' . '|' .
preg_quote($config['file_mod'], '/') . '\?\/.+' . preg_quote($config['file_mod'], '/') . '\?\/.+' .
')([#?](.+)?)?$/ui'; ')([#?](.+)?)?$/ui';
@ -121,6 +168,9 @@ function loadConfig() {
if (!isset($config['dir']['static'])) if (!isset($config['dir']['static']))
$config['dir']['static'] = $config['root'] . 'static/'; $config['dir']['static'] = $config['root'] . 'static/';
if (!isset($config['image_blank']))
$config['image_blank'] = $config['dir']['static'] . 'blank.gif';
if (!isset($config['image_sticky'])) if (!isset($config['image_sticky']))
$config['image_sticky'] = $config['dir']['static'] . 'sticky.gif'; $config['image_sticky'] = $config['dir']['static'] . 'sticky.gif';
if (!isset($config['image_locked'])) if (!isset($config['image_locked']))
@ -171,21 +221,6 @@ function loadConfig() {
if (preg_match('/^\:\:(ffff\:)?(\d+\.\d+\.\d+\.\d+)$/', $__ip, $m)) if (preg_match('/^\:\:(ffff\:)?(\d+\.\d+\.\d+\.\d+)$/', $__ip, $m))
$_SERVER['REMOTE_ADDR'] = $m[2]; $_SERVER['REMOTE_ADDR'] = $m[2];
if ($config['locale'] != 'en') {
if (_setlocale(LC_ALL, $config['locale']) === false) {
$error('The specified locale (' . $config['locale'] . ') does not exist on your platform!');
}
if (extension_loaded('gettext')) {
bindtextdomain('tinyboard', './inc/locale');
bind_textdomain_codeset('tinyboard', 'UTF-8');
textdomain('tinyboard');
} else {
_bindtextdomain('tinyboard', './inc/locale');
_bind_textdomain_codeset('tinyboard', 'UTF-8');
_textdomain('tinyboard');
}
}
if ($config['syslog']) if ($config['syslog'])
openlog('tinyboard', LOG_ODELAY, LOG_SYSLOG); // open a connection to sysem logger openlog('tinyboard', LOG_ODELAY, LOG_SYSLOG); // open a connection to sysem logger
@ -193,6 +228,12 @@ function loadConfig() {
require_once 'inc/lib/recaptcha/recaptchalib.php'; require_once 'inc/lib/recaptcha/recaptchalib.php';
if ($config['cache']['enabled']) if ($config['cache']['enabled'])
require_once 'inc/cache.php'; require_once 'inc/cache.php';
if (in_array('webm', $config['allowed_ext_files'])) {
require_once 'inc/lib/webm/posthandler.php';
event_handler('post', 'postHandler');
}
event('load-config'); event('load-config');
if ($config['debug']) { if ($config['debug']) {
@ -989,6 +1030,8 @@ function deletePost($id, $error_if_doesnt_exist=true, $rebuild_after=true) {
if (!$post['thread']) { if (!$post['thread']) {
// Delete thread HTML page // Delete thread HTML page
file_unlink($board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $post['id'])); file_unlink($board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $post['id']));
file_unlink($board['dir'] . $config['dir']['res'] . sprintf($config['file_page50'], $post['id']));
file_unlink($board['dir'] . $config['dir']['res'] . sprintf('%d.json', $post['id']));
$antispam_query = prepare('DELETE FROM ``antispam`` WHERE `board` = :board AND `thread` = :thread'); $antispam_query = prepare('DELETE FROM ``antispam`` WHERE `board` = :board AND `thread` = :thread');
$antispam_query->bindValue(':board', $board['uri']); $antispam_query->bindValue(':board', $board['uri']);
@ -1036,6 +1079,7 @@ function deletePost($id, $error_if_doesnt_exist=true, $rebuild_after=true) {
if (isset($rebuild) && $rebuild_after) { if (isset($rebuild) && $rebuild_after) {
buildThread($rebuild); buildThread($rebuild);
buildIndex();
} }
return true; return true;
@ -1051,7 +1095,7 @@ function clean() {
$query->execute() or error(db_error($query)); $query->execute() or error(db_error($query));
while ($post = $query->fetch(PDO::FETCH_ASSOC)) { while ($post = $query->fetch(PDO::FETCH_ASSOC)) {
deletePost($post['id']); deletePost($post['id'], false, false);
} }
} }
@ -1126,6 +1170,9 @@ function index($page, $mod=false) {
$thread->add(new Post($po, $mod ? '?/' : $config['root'], $mod)); $thread->add(new Post($po, $mod ? '?/' : $config['root'], $mod));
} }
$thread->images = $num_images;
$thread->replies = isset($omitted['post_count']) ? $omitted['post_count'] : count($replies);
if ($omitted) { if ($omitted) {
$thread->omitted = $omitted['post_count'] - ($th['sticky'] ? $config['threads_preview_sticky'] : $config['threads_preview']); $thread->omitted = $omitted['post_count'] - ($th['sticky'] ? $config['threads_preview_sticky'] : $config['threads_preview']);
$thread->omitted_images = $omitted['image_count'] - $num_images; $thread->omitted_images = $omitted['image_count'] - $num_images;
@ -1359,13 +1406,27 @@ function buildIndex() {
for ($page = 1; $page <= $config['max_pages']; $page++) { for ($page = 1; $page <= $config['max_pages']; $page++) {
$filename = $board['dir'] . ($page == 1 ? $config['file_index'] : sprintf($config['file_page'], $page)); $filename = $board['dir'] . ($page == 1 ? $config['file_index'] : sprintf($config['file_page'], $page));
if ($config['try_smarter'] && isset($build_pages) && !empty($build_pages) if (!$config['api']['enabled'] && $config['try_smarter'] && isset($build_pages) && !empty($build_pages)
&& !in_array($page, $build_pages) && is_file($filename)) && !in_array($page, $build_pages) && is_file($filename))
continue; continue;
$content = index($page); $content = index($page);
if (!$content) if (!$content)
break; break;
// json api
if ($config['api']['enabled']) {
$threads = $content['threads'];
$json = json_encode($api->translatePage($threads));
$jsonFilename = $board['dir'] . ($page - 1) . '.json'; // pages should start from 0
file_write($jsonFilename, $json);
$catalog[$page-1] = $threads;
}
if ($config['api']['enabled'] && $config['try_smarter'] && isset($build_pages) && !empty($build_pages)
&& !in_array($page, $build_pages) && is_file($filename))
continue;
if ($config['try_smarter']) { if ($config['try_smarter']) {
$antibot = create_antibot($board['uri'], 0 - $page); $antibot = create_antibot($board['uri'], 0 - $page);
$content['current_page'] = $page; $content['current_page'] = $page;
@ -1377,16 +1438,6 @@ function buildIndex() {
$content['antibot'] = $antibot; $content['antibot'] = $antibot;
file_write($filename, Element('index.html', $content)); file_write($filename, Element('index.html', $content));
// json api
if ($config['api']['enabled']) {
$threads = $content['threads'];
$json = json_encode($api->translatePage($threads));
$jsonFilename = $board['dir'] . ($page - 1) . '.json'; // pages should start from 0
file_write($jsonFilename, $json);
$catalog[$page-1] = $threads;
}
} }
if ($page < $config['max_pages']) { if ($page < $config['max_pages']) {
@ -1394,16 +1445,22 @@ function buildIndex() {
$filename = $board['dir'] . ($page==1 ? $config['file_index'] : sprintf($config['file_page'], $page)); $filename = $board['dir'] . ($page==1 ? $config['file_index'] : sprintf($config['file_page'], $page));
file_unlink($filename); file_unlink($filename);
if ($config['api']['enabled']) {
$jsonFilename = $board['dir'] . ($page - 1) . '.json'; $jsonFilename = $board['dir'] . ($page - 1) . '.json';
file_unlink($jsonFilename); file_unlink($jsonFilename);
} }
} }
}
// json api catalog // json api catalog
if ($config['api']['enabled']) { if ($config['api']['enabled']) {
$json = json_encode($api->translateCatalog($catalog)); $json = json_encode($api->translateCatalog($catalog));
$jsonFilename = $board['dir'] . 'catalog.json'; $jsonFilename = $board['dir'] . 'catalog.json';
file_write($jsonFilename, $json); file_write($jsonFilename, $json);
$json = json_encode($api->translateCatalog($catalog, true));
$jsonFilename = $board['dir'] . 'threads.json';
file_write($jsonFilename, $json);
} }
if ($config['try_smarter']) if ($config['try_smarter'])
@ -1531,7 +1588,7 @@ function markup_url($matches) {
$markup_urls[] = $url; $markup_urls[] = $url;
$link = (object) array( $link = (object) array(
'href' => $url, 'href' => $config['link_prefix'] . $url,
'text' => $url, 'text' => $url,
'rel' => 'nofollow', 'rel' => 'nofollow',
'target' => '_blank', 'target' => '_blank',
@ -1903,6 +1960,9 @@ function buildThread($id, $return = false, $mod = false) {
if (!isset($thread)) if (!isset($thread))
error($config['error']['nonexistant']); error($config['error']['nonexistant']);
$hasnoko50 = $thread->postCount() >= $config['noko50_min'];
$antibot = $mod || $return ? false : create_antibot($board['uri'], $id);
$body = Element('thread.html', array( $body = Element('thread.html', array(
'board' => $board, 'board' => $board,
'thread' => $thread, 'thread' => $thread,
@ -1910,7 +1970,9 @@ function buildThread($id, $return = false, $mod = false) {
'config' => $config, 'config' => $config,
'id' => $id, 'id' => $id,
'mod' => $mod, 'mod' => $mod,
'antibot' => $mod || $return ? false : create_antibot($board['uri'], $id), 'hasnoko50' => $hasnoko50,
'isnoko50' => false,
'antibot' => $antibot,
'boardlist' => createBoardlist($mod), 'boardlist' => createBoardlist($mod),
'return' => ($mod ? '?' . $board['url'] . $config['file_index'] : $config['root'] . $board['dir'] . $config['file_index']) 'return' => ($mod ? '?' . $board['url'] . $config['file_index'] : $config['root'] . $board['dir'] . $config['file_index'])
)); ));
@ -1918,11 +1980,6 @@ function buildThread($id, $return = false, $mod = false) {
if ($config['try_smarter'] && !$mod) if ($config['try_smarter'] && !$mod)
$build_pages[] = thread_find_page($id); $build_pages[] = thread_find_page($id);
if ($return)
return $body;
file_write($board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $id), $body);
// json api // json api
if ($config['api']['enabled']) { if ($config['api']['enabled']) {
$api = new Api(); $api = new Api();
@ -1930,6 +1987,96 @@ function buildThread($id, $return = false, $mod = false) {
$jsonFilename = $board['dir'] . $config['dir']['res'] . $id . '.json'; $jsonFilename = $board['dir'] . $config['dir']['res'] . $id . '.json';
file_write($jsonFilename, $json); file_write($jsonFilename, $json);
} }
if ($return) {
return $body;
} else {
$noko50fn = $board['dir'] . $config['dir']['res'] . sprintf($config['file_page50'], $id);
if ($hasnoko50 || file_exists($noko50fn)) {
buildThread50($id, $return, $mod, $thread, $antibot);
}
file_write($board['dir'] . $config['dir']['res'] . sprintf($config['file_page'], $id), $body);
}
}
function buildThread50($id, $return = false, $mod = false, $thread = null, $antibot = false) {
global $board, $config, $build_pages;
$id = round($id);
if ($antibot)
$antibot->reset();
if (!$thread) {
$query = prepare(sprintf("SELECT * FROM ``posts_%s`` WHERE (`thread` IS NULL AND `id` = :id) OR `thread` = :id ORDER BY `thread`,`id` DESC LIMIT :limit", $board['uri']));
$query->bindValue(':id', $id, PDO::PARAM_INT);
$query->bindValue(':limit', $config['noko50_count']+1, PDO::PARAM_INT);
$query->execute() or error(db_error($query));
$num_images = 0;
while ($post = $query->fetch(PDO::FETCH_ASSOC)) {
if (!isset($thread)) {
$thread = new Thread($post, $mod ? '?/' : $config['root'], $mod);
} else {
if ($post['file'])
$num_images++;
$thread->add(new Post($post, $mod ? '?/' : $config['root'], $mod));
}
}
// Check if any posts were found
if (!isset($thread))
error($config['error']['nonexistant']);
if ($query->rowCount() == $config['noko50_count']+1) {
$count = prepare(sprintf("SELECT COUNT(`id`) as `num` FROM ``posts_%s`` WHERE `thread` = :thread UNION ALL SELECT COUNT(`id`) FROM ``posts_%s`` WHERE `file` IS NOT NULL AND `thread` = :thread", $board['uri'], $board['uri']));
$count->bindValue(':thread', $id, PDO::PARAM_INT);
$count->execute() or error(db_error($count));
$c = $count->fetch();
$thread->omitted = $c['num'] - $config['noko50_count'];
$c = $count->fetch();
$thread->omitted_images = $c['num'] - $num_images;
}
$thread->posts = array_reverse($thread->posts);
} else {
$allPosts = $thread->posts;
$thread->posts = array_slice($allPosts, -$config['noko50_count']);
$thread->omitted += count($allPosts) - count($thread->posts);
foreach ($allPosts as $index => $post) {
if ($index == count($allPosts)-count($thread->posts))
break;
if ($post->file)
$thread->omitted_images++;
}
}
$hasnoko50 = $thread->postCount() >= $config['noko50_min'];
$body = Element('thread.html', array(
'board' => $board,
'thread' => $thread,
'body' => $thread->build(false, true),
'config' => $config,
'id' => $id,
'mod' => $mod,
'hasnoko50' => $hasnoko50,
'isnoko50' => true,
'antibot' => $mod ? false : ($antibot ? $antibot : create_antibot($board['uri'], $id)),
'boardlist' => createBoardlist($mod),
'return' => ($mod ? '?' . $board['url'] . $config['file_index'] : $config['root'] . $board['dir'] . $config['file_index'])
));
if ($return) {
return $body;
} else {
file_write($board['dir'] . $config['dir']['res'] . sprintf($config['file_page50'], $id), $body);
}
} }
function rrmdir($dir) { function rrmdir($dir) {

View File

@ -339,7 +339,7 @@ class ImageConvert extends ImageBase {
$this->height, $this->height,
escapeshellarg($this->temp)))) || !file_exists($this->temp)) { escapeshellarg($this->temp)))) || !file_exists($this->temp)) {
$this->destroy(); $this->destroy();
error('Failed to resize image!', null, $error); error(_('Failed to resize image!'), null, $error);
} }
if ($size = $this->get_size($this->temp)) { if ($size = $this->get_size($this->temp)) {
$this->width = $size[0]; $this->width = $size[0];
@ -365,6 +365,10 @@ class ImageConvert extends ImageBase {
$this->destroy(); $this->destroy();
error('Failed to resize image!', null, $error); error('Failed to resize image!', null, $error);
} }
if (!file_exists($this->temp)) {
$this->destroy();
error(_('Failed to resize image!'), null, $error);
}
} }
if ($size = $this->get_size($this->temp)) { if ($size = $this->get_size($this->temp)) {
$this->width = $size[0]; $this->width = $size[0];

BIN
inc/lib/geoip/GeoIPv6.dat Normal file

Binary file not shown.

722
inc/lib/geoip/geoip.inc Normal file
View File

@ -0,0 +1,722 @@
<?php
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
/* geoip.inc
*
* Copyright (C) 2007 MaxMind LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
namespace geoip;
@define("GEOIP_COUNTRY_BEGIN", 16776960);
@define("GEOIP_STATE_BEGIN_REV0", 16700000);
@define("GEOIP_STATE_BEGIN_REV1", 16000000);
@define("GEOIP_STANDARD", 0);
@define("GEOIP_MEMORY_CACHE", 1);
@define("GEOIP_SHARED_MEMORY", 2);
@define("STRUCTURE_INFO_MAX_SIZE", 20);
@define("DATABASE_INFO_MAX_SIZE", 100);
@define("GEOIP_COUNTRY_EDITION", 1);
@define("GEOIP_PROXY_EDITION", 8);
@define("GEOIP_ASNUM_EDITION", 9);
@define("GEOIP_NETSPEED_EDITION", 10);
@define("GEOIP_REGION_EDITION_REV0", 7);
@define("GEOIP_REGION_EDITION_REV1", 3);
@define("GEOIP_CITY_EDITION_REV0", 6);
@define("GEOIP_CITY_EDITION_REV1", 2);
@define("GEOIP_ORG_EDITION", 5);
@define("GEOIP_ISP_EDITION", 4);
@define("SEGMENT_RECORD_LENGTH", 3);
@define("STANDARD_RECORD_LENGTH", 3);
@define("ORG_RECORD_LENGTH", 4);
@define("MAX_RECORD_LENGTH", 4);
@define("MAX_ORG_RECORD_LENGTH", 300);
@define("GEOIP_SHM_KEY", 0x4f415401);
@define("US_OFFSET", 1);
@define("CANADA_OFFSET", 677);
@define("WORLD_OFFSET", 1353);
@define("FIPS_RANGE", 360);
@define("GEOIP_UNKNOWN_SPEED", 0);
@define("GEOIP_DIALUP_SPEED", 1);
@define("GEOIP_CABLEDSL_SPEED", 2);
@define("GEOIP_CORPORATE_SPEED", 3);
@define("GEOIP_DOMAIN_EDITION", 11);
@define("GEOIP_COUNTRY_EDITION_V6", 12);
@define("GEOIP_LOCATIONA_EDITION", 13);
@define("GEOIP_ACCURACYRADIUS_EDITION", 14);
@define("GEOIP_CITYCOMBINED_EDITION", 15);
@define("GEOIP_CITY_EDITION_REV1_V6", 30);
@define("GEOIP_CITY_EDITION_REV0_V6",31);
@define("GEOIP_NETSPEED_EDITION_REV1",32);
@define("GEOIP_NETSPEED_EDITION_REV1_V6",33);
@define("GEOIP_USERTYPE_EDITION",28);
@define("GEOIP_USERTYPE_EDITION_V6",29);
@define("GEOIP_ASNUM_EDITION_V6",21);
@define("GEOIP_ISP_EDITION_V6",22);
@define("GEOIP_ORG_EDITION_V6",23);
@define("GEOIP_DOMAIN_EDITION_V6",24);
@define("CITYCOMBINED_FIXED_RECORD", 7 );
class GeoIP {
var $flags;
var $filehandle;
var $memory_buffer;
var $databaseType;
var $databaseSegments;
var $record_length;
var $shmid;
var $GEOIP_COUNTRY_CODE_TO_NUMBER = array(
"" => 0, "AP" => 1, "EU" => 2, "AD" => 3, "AE" => 4, "AF" => 5,
"AG" => 6, "AI" => 7, "AL" => 8, "AM" => 9, "CW" => 10, "AO" => 11,
"AQ" => 12, "AR" => 13, "AS" => 14, "AT" => 15, "AU" => 16, "AW" => 17,
"AZ" => 18, "BA" => 19, "BB" => 20, "BD" => 21, "BE" => 22, "BF" => 23,
"BG" => 24, "BH" => 25, "BI" => 26, "BJ" => 27, "BM" => 28, "BN" => 29,
"BO" => 30, "BR" => 31, "BS" => 32, "BT" => 33, "BV" => 34, "BW" => 35,
"BY" => 36, "BZ" => 37, "CA" => 38, "CC" => 39, "CD" => 40, "CF" => 41,
"CG" => 42, "CH" => 43, "CI" => 44, "CK" => 45, "CL" => 46, "CM" => 47,
"CN" => 48, "CO" => 49, "CR" => 50, "CU" => 51, "CV" => 52, "CX" => 53,
"CY" => 54, "CZ" => 55, "DE" => 56, "DJ" => 57, "DK" => 58, "DM" => 59,
"DO" => 60, "DZ" => 61, "EC" => 62, "EE" => 63, "EG" => 64, "EH" => 65,
"ER" => 66, "ES" => 67, "ET" => 68, "FI" => 69, "FJ" => 70, "FK" => 71,
"FM" => 72, "FO" => 73, "FR" => 74, "SX" => 75, "GA" => 76, "GB" => 77,
"GD" => 78, "GE" => 79, "GF" => 80, "GH" => 81, "GI" => 82, "GL" => 83,
"GM" => 84, "GN" => 85, "GP" => 86, "GQ" => 87, "GR" => 88, "GS" => 89,
"GT" => 90, "GU" => 91, "GW" => 92, "GY" => 93, "HK" => 94, "HM" => 95,
"HN" => 96, "HR" => 97, "HT" => 98, "HU" => 99, "ID" => 100, "IE" => 101,
"IL" => 102, "IN" => 103, "IO" => 104, "IQ" => 105, "IR" => 106, "IS" => 107,
"IT" => 108, "JM" => 109, "JO" => 110, "JP" => 111, "KE" => 112, "KG" => 113,
"KH" => 114, "KI" => 115, "KM" => 116, "KN" => 117, "KP" => 118, "KR" => 119,
"KW" => 120, "KY" => 121, "KZ" => 122, "LA" => 123, "LB" => 124, "LC" => 125,
"LI" => 126, "LK" => 127, "LR" => 128, "LS" => 129, "LT" => 130, "LU" => 131,
"LV" => 132, "LY" => 133, "MA" => 134, "MC" => 135, "MD" => 136, "MG" => 137,
"MH" => 138, "MK" => 139, "ML" => 140, "MM" => 141, "MN" => 142, "MO" => 143,
"MP" => 144, "MQ" => 145, "MR" => 146, "MS" => 147, "MT" => 148, "MU" => 149,
"MV" => 150, "MW" => 151, "MX" => 152, "MY" => 153, "MZ" => 154, "NA" => 155,
"NC" => 156, "NE" => 157, "NF" => 158, "NG" => 159, "NI" => 160, "NL" => 161,
"NO" => 162, "NP" => 163, "NR" => 164, "NU" => 165, "NZ" => 166, "OM" => 167,
"PA" => 168, "PE" => 169, "PF" => 170, "PG" => 171, "PH" => 172, "PK" => 173,
"PL" => 174, "PM" => 175, "PN" => 176, "PR" => 177, "PS" => 178, "PT" => 179,
"PW" => 180, "PY" => 181, "QA" => 182, "RE" => 183, "RO" => 184, "RU" => 185,
"RW" => 186, "SA" => 187, "SB" => 188, "SC" => 189, "SD" => 190, "SE" => 191,
"SG" => 192, "SH" => 193, "SI" => 194, "SJ" => 195, "SK" => 196, "SL" => 197,
"SM" => 198, "SN" => 199, "SO" => 200, "SR" => 201, "ST" => 202, "SV" => 203,
"SY" => 204, "SZ" => 205, "TC" => 206, "TD" => 207, "TF" => 208, "TG" => 209,
"TH" => 210, "TJ" => 211, "TK" => 212, "TM" => 213, "TN" => 214, "TO" => 215,
"TL" => 216, "TR" => 217, "TT" => 218, "TV" => 219, "TW" => 220, "TZ" => 221,
"UA" => 222, "UG" => 223, "UM" => 224, "US" => 225, "UY" => 226, "UZ" => 227,
"VA" => 228, "VC" => 229, "VE" => 230, "VG" => 231, "VI" => 232, "VN" => 233,
"VU" => 234, "WF" => 235, "WS" => 236, "YE" => 237, "YT" => 238, "RS" => 239,
"ZA" => 240, "ZM" => 241, "ME" => 242, "ZW" => 243, "A1" => 244, "A2" => 245,
"O1" => 246, "AX" => 247, "GG" => 248, "IM" => 249, "JE" => 250, "BL" => 251,
"MF" => 252, "BQ" => 253, "SS" => 254
);
var $GEOIP_COUNTRY_CODES = array(
"","AP","EU","AD","AE","AF","AG","AI","AL","AM","CW",
"AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB",
"BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO",
"BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD",
"CF","CG","CH","CI","CK","CL","CM","CN","CO","CR",
"CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO",
"DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ",
"FK","FM","FO","FR","SX","GA","GB","GD","GE","GF",
"GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT",
"GU","GW","GY","HK","HM","HN","HR","HT","HU","ID",
"IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO",
"JP","KE","KG","KH","KI","KM","KN","KP","KR","KW",
"KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT",
"LU","LV","LY","MA","MC","MD","MG","MH","MK","ML",
"MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV",
"MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI",
"NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF",
"PG","PH","PK","PL","PM","PN","PR","PS","PT","PW",
"PY","QA","RE","RO","RU","RW","SA","SB","SC","SD",
"SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO",
"SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH",
"TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW",
"TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE",
"VG","VI","VN","VU","WF","WS","YE","YT","RS","ZA",
"ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE",
"BL","MF", "BQ", "SS", "O1" );
var $GEOIP_COUNTRY_CODES3 = array(
"","AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","CUW",
"AGO","ATA","ARG","ASM","AUT","AUS","ABW","AZE","BIH","BRB",
"BGD","BEL","BFA","BGR","BHR","BDI","BEN","BMU","BRN","BOL",
"BRA","BHS","BTN","BVT","BWA","BLR","BLZ","CAN","CCK","COD",
"CAF","COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI",
"CUB","CPV","CXR","CYP","CZE","DEU","DJI","DNK","DMA","DOM",
"DZA","ECU","EST","EGY","ESH","ERI","ESP","ETH","FIN","FJI",
"FLK","FSM","FRO","FRA","SXM","GAB","GBR","GRD","GEO","GUF",
"GHA","GIB","GRL","GMB","GIN","GLP","GNQ","GRC","SGS","GTM",
"GUM","GNB","GUY","HKG","HMD","HND","HRV","HTI","HUN","IDN",
"IRL","ISR","IND","IOT","IRQ","IRN","ISL","ITA","JAM","JOR",
"JPN","KEN","KGZ","KHM","KIR","COM","KNA","PRK","KOR","KWT",
"CYM","KAZ","LAO","LBN","LCA","LIE","LKA","LBR","LSO","LTU",
"LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD","MLI",
"MMR","MNG","MAC","MNP","MTQ","MRT","MSR","MLT","MUS","MDV",
"MWI","MEX","MYS","MOZ","NAM","NCL","NER","NFK","NGA","NIC",
"NLD","NOR","NPL","NRU","NIU","NZL","OMN","PAN","PER","PYF",
"PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW",
"PRY","QAT","REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN",
"SWE","SGP","SHN","SVN","SJM","SVK","SLE","SMR","SEN","SOM",
"SUR","STP","SLV","SYR","SWZ","TCA","TCD","ATF","TGO","THA",
"TJK","TKL","TKM","TUN","TON","TLS","TUR","TTO","TUV","TWN",
"TZA","UKR","UGA","UMI","USA","URY","UZB","VAT","VCT","VEN",
"VGB","VIR","VNM","VUT","WLF","WSM","YEM","MYT","SRB","ZAF",
"ZMB","MNE","ZWE","A1","A2","O1","ALA","GGY","IMN","JEY",
"BLM","MAF", "BES", "SSD", "O1"
);
var $GEOIP_COUNTRY_NAMES = array(
"","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Curacao",
"Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
"Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
"Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
"Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica",
"Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic",
"Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji",
"Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","Sint Maarten (Dutch part)","Gabon","United Kingdom","Grenada","Georgia","French Guiana",
"Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala",
"Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia",
"Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan",
"Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
"Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
"Luxembourg","Latvia","Libya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali",
"Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives",
"Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
"Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia",
"Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau",
"Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan",
"Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname",
"Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand",
"Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan",
"Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela",
"Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
"Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
"Saint Barthelemy","Saint Martin", "Bonaire, Saint Eustatius and Saba",
"South Sudan", "Other"
);
var $GEOIP_CONTINENT_CODES = array(
"--", "AS","EU","EU","AS","AS","NA","NA","EU","AS","NA",
"AF","AN","SA","OC","EU","OC","NA","AS","EU","NA",
"AS","EU","AF","EU","AS","AF","AF","NA","AS","SA",
"SA","NA","AS","AN","AF","EU","NA","NA","AS","AF",
"AF","AF","EU","AF","OC","SA","AF","AS","SA","NA",
"NA","AF","AS","AS","EU","EU","AF","EU","NA","NA",
"AF","SA","EU","AF","AF","AF","EU","AF","EU","OC",
"SA","OC","EU","EU","NA","AF","EU","NA","AS","SA",
"AF","EU","NA","AF","AF","NA","AF","EU","AN","NA",
"OC","AF","SA","AS","AN","NA","EU","NA","EU","AS",
"EU","AS","AS","AS","AS","AS","EU","EU","NA","AS",
"AS","AF","AS","AS","OC","AF","NA","AS","AS","AS",
"NA","AS","AS","AS","NA","EU","AS","AF","AF","EU",
"EU","EU","AF","AF","EU","EU","AF","OC","EU","AF",
"AS","AS","AS","OC","NA","AF","NA","EU","AF","AS",
"AF","NA","AS","AF","AF","OC","AF","OC","AF","NA",
"EU","EU","AS","OC","OC","OC","AS","NA","SA","OC",
"OC","AS","AS","EU","NA","OC","NA","AS","EU","OC",
"SA","AS","AF","EU","EU","AF","AS","OC","AF","AF",
"EU","AS","AF","EU","EU","EU","AF","EU","AF","AF",
"SA","AF","NA","AS","AF","NA","AF","AN","AF","AS",
"AS","OC","AS","AF","OC","AS","EU","NA","OC","AS",
"AF","EU","AF","OC","NA","SA","AS","EU","NA","SA",
"NA","NA","AS","OC","OC","OC","AS","AF","EU","AF",
"AF","EU","AF","--","--","--","EU","EU","EU","EU",
"NA","NA","NA", "AF", "--"
);
}
function geoip_load_shared_mem ($file) {
$fp = fopen($file, "rb");
if (!$fp) {
print "error opening $file: $php_errormsg\n";
exit;
}
$s_array = fstat($fp);
$size = $s_array['size'];
if ($shmid = @shmop_open (GEOIP_SHM_KEY, "w", 0, 0)) {
shmop_delete ($shmid);
shmop_close ($shmid);
}
$shmid = shmop_open (GEOIP_SHM_KEY, "c", 0644, $size);
shmop_write ($shmid, fread($fp, $size), 0);
shmop_close ($shmid);
}
function _setup_segments($gi){
$gi->databaseType = GEOIP_COUNTRY_EDITION;
$gi->record_length = STANDARD_RECORD_LENGTH;
if ($gi->flags & GEOIP_SHARED_MEMORY) {
$offset = @shmop_size ($gi->shmid) - 3;
for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
$delim = @shmop_read ($gi->shmid, $offset, 3);
$offset += 3;
if ($delim == (chr(255).chr(255).chr(255))) {
$gi->databaseType = ord(@shmop_read ($gi->shmid, $offset, 1));
if ( $gi->databaseType >= 106 ){
$gi->databaseType -= 105;
}
$offset++;
if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){
$gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
} else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1){
$gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
} else if (($gi->databaseType == GEOIP_CITY_EDITION_REV0)||
($gi->databaseType == GEOIP_CITY_EDITION_REV1)
|| ($gi->databaseType == GEOIP_ORG_EDITION)
|| ($gi->databaseType == GEOIP_ORG_EDITION_V6)
|| ($gi->databaseType == GEOIP_DOMAIN_EDITION)
|| ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
|| ($gi->databaseType == GEOIP_ISP_EDITION)
|| ($gi->databaseType == GEOIP_ISP_EDITION_V6)
|| ($gi->databaseType == GEOIP_USERTYPE_EDITION)
|| ($gi->databaseType == GEOIP_USERTYPE_EDITION_V6)
|| ($gi->databaseType == GEOIP_LOCATIONA_EDITION)
|| ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION)
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
|| ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1)
|| ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6)
|| ($gi->databaseType == GEOIP_ASNUM_EDITION)
|| ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)){
$gi->databaseSegments = 0;
$buf = @shmop_read ($gi->shmid, $offset, SEGMENT_RECORD_LENGTH);
for ($j = 0;$j < SEGMENT_RECORD_LENGTH;$j++){
$gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
}
if (($gi->databaseType == GEOIP_ORG_EDITION)
|| ($gi->databaseType == GEOIP_ORG_EDITION_V6)
|| ($gi->databaseType == GEOIP_DOMAIN_EDITION)
|| ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
|| ($gi->databaseType == GEOIP_ISP_EDITION)
|| ($gi->databaseType == GEOIP_ISP_EDITION_V6)) {
$gi->record_length = ORG_RECORD_LENGTH;
}
}
break;
} else {
$offset -= 4;
}
}
if (($gi->databaseType == GEOIP_COUNTRY_EDITION)||
($gi->databaseType == GEOIP_COUNTRY_EDITION_V6)||
($gi->databaseType == GEOIP_PROXY_EDITION)||
($gi->databaseType == GEOIP_NETSPEED_EDITION)){
$gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
}
} else {
$filepos = ftell($gi->filehandle);
fseek($gi->filehandle, -3, SEEK_END);
for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
$delim = fread($gi->filehandle,3);
if ($delim == (chr(255).chr(255).chr(255))){
$gi->databaseType = ord(fread($gi->filehandle,1));
if ( $gi->databaseType >= 106 ){
$gi->databaseType -= 105;
}
if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){
$gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
}
else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1){
$gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
} else if (($gi->databaseType == GEOIP_CITY_EDITION_REV0)
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV1)
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
|| ($gi->databaseType == GEOIP_ORG_EDITION)
|| ($gi->databaseType == GEOIP_DOMAIN_EDITION)
|| ($gi->databaseType == GEOIP_ISP_EDITION)
|| ($gi->databaseType == GEOIP_ORG_EDITION_V6)
|| ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
|| ($gi->databaseType == GEOIP_ISP_EDITION_V6)
|| ($gi->databaseType == GEOIP_LOCATIONA_EDITION)
|| ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION)
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
|| ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1)
|| ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6)
|| ($gi->databaseType == GEOIP_USERTYPE_EDITION)
|| ($gi->databaseType == GEOIP_USERTYPE_EDITION_V6)
|| ($gi->databaseType == GEOIP_ASNUM_EDITION)
|| ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)){
$gi->databaseSegments = 0;
$buf = fread($gi->filehandle,SEGMENT_RECORD_LENGTH);
for ($j = 0;$j < SEGMENT_RECORD_LENGTH;$j++){
$gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
}
if ( ( $gi->databaseType == GEOIP_ORG_EDITION )
|| ( $gi->databaseType == GEOIP_DOMAIN_EDITION )
|| ( $gi->databaseType == GEOIP_ISP_EDITION )
|| ( $gi->databaseType == GEOIP_ORG_EDITION_V6 )
|| ( $gi->databaseType == GEOIP_DOMAIN_EDITION_V6 )
|| ( $gi->databaseType == GEOIP_ISP_EDITION_V6 )) {
$gi->record_length = ORG_RECORD_LENGTH;
}
}
break;
} else {
fseek($gi->filehandle, -4, SEEK_CUR);
}
}
if (($gi->databaseType == GEOIP_COUNTRY_EDITION)||
($gi->databaseType == GEOIP_COUNTRY_EDITION_V6)||
($gi->databaseType == GEOIP_PROXY_EDITION)||
($gi->databaseType == GEOIP_NETSPEED_EDITION)){
$gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
}
fseek($gi->filehandle,$filepos,SEEK_SET);
}
return $gi;
}
function geoip_open($filename, $flags) {
$gi = new GeoIP;
$gi->flags = $flags;
if ($gi->flags & GEOIP_SHARED_MEMORY) {
$gi->shmid = @shmop_open (GEOIP_SHM_KEY, "a", 0, 0);
} else {
$gi->filehandle = fopen($filename,"rb") or die( "Can not open $filename\n" );
if ($gi->flags & GEOIP_MEMORY_CACHE) {
$s_array = fstat($gi->filehandle);
$gi->memory_buffer = fread($gi->filehandle, $s_array['size']);
}
}
$gi = _setup_segments($gi);
return $gi;
}
function geoip_close($gi) {
if ($gi->flags & GEOIP_SHARED_MEMORY) {
return true;
}
return fclose($gi->filehandle);
}
function geoip_country_id_by_name_v6($gi, $name) {
$rec = dns_get_record($name, DNS_AAAA);
if ( !$rec ) {
return false;
}
$addr = $rec[0]["ipv6"];
if (!$addr || $addr == $name) {
return false;
}
return geoip_country_id_by_addr_v6($gi, $addr);
}
function geoip_country_id_by_name($gi, $name) {
$addr = gethostbyname($name);
if (!$addr || $addr == $name) {
return false;
}
return geoip_country_id_by_addr($gi, $addr);
}
function geoip_country_code_by_name_v6($gi, $name) {
$country_id = geoip_country_id_by_name_v6($gi,$name);
if ($country_id !== false) {
return $gi->GEOIP_COUNTRY_CODES[$country_id];
}
return false;
}
function geoip_country_code_by_name($gi, $name) {
$country_id = geoip_country_id_by_name($gi,$name);
if ($country_id !== false) {
return $gi->GEOIP_COUNTRY_CODES[$country_id];
}
return false;
}
function geoip_country_name_by_name_v6($gi, $name) {
$country_id = geoip_country_id_by_name_v6($gi,$name);
if ($country_id !== false) {
return $gi->GEOIP_COUNTRY_NAMES[$country_id];
}
return false;
}
function geoip_country_name_by_name($gi, $name) {
$country_id = geoip_country_id_by_name($gi,$name);
if ($country_id !== false) {
return $gi->GEOIP_COUNTRY_NAMES[$country_id];
}
return false;
}
function geoip_country_id_by_addr_v6($gi, $addr) {
$ipnum = inet_pton($addr);
return _geoip_seek_country_v6($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
}
function geoip_country_id_by_addr($gi, $addr) {
$ipnum = ip2long($addr);
return _geoip_seek_country($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
}
function geoip_country_code_by_addr_v6($gi, $addr) {
$country_id = geoip_country_id_by_addr_v6($gi,$addr);
if ($country_id !== false) {
return $gi->GEOIP_COUNTRY_CODES[$country_id];
}
return false;
}
function geoip_country_code_by_addr($gi, $addr) {
if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
$record = geoip_record_by_addr($gi,$addr);
if ( $record !== false ) {
return $record->country_code;
}
} else {
$country_id = geoip_country_id_by_addr($gi,$addr);
if ($country_id !== false) {
return $gi->GEOIP_COUNTRY_CODES[$country_id];
}
}
return false;
}
function geoip_country_name_by_addr_v6($gi, $addr) {
$country_id = geoip_country_id_by_addr_v6($gi,$addr);
if ($country_id !== false) {
return $gi->GEOIP_COUNTRY_NAMES[$country_id];
}
return false;
}
function geoip_country_name_by_addr($gi, $addr) {
if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
$record = geoip_record_by_addr($gi,$addr);
return $record->country_name;
} else {
$country_id = geoip_country_id_by_addr($gi,$addr);
if ($country_id !== false) {
return $gi->GEOIP_COUNTRY_NAMES[$country_id];
}
}
return false;
}
function _geoip_seek_country_v6($gi, $ipnum) {
# arrays from unpack start with offset 1
# yet another php mystery. array_merge work around
# this broken behaviour
$v6vec = array_merge(unpack( "C16", $ipnum));
$offset = 0;
for ($depth = 127; $depth >= 0; --$depth) {
if ($gi->flags & GEOIP_MEMORY_CACHE) {
// workaround php's broken substr, strpos, etc handling with
// mbstring.func_overload and mbstring.internal_encoding
$enc = mb_internal_encoding();
mb_internal_encoding('ISO-8859-1');
$buf = substr($gi->memory_buffer,
2 * $gi->record_length * $offset,
2 * $gi->record_length);
mb_internal_encoding($enc);
} elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
$buf = @shmop_read ($gi->shmid,
2 * $gi->record_length * $offset,
2 * $gi->record_length );
} else {
fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
or die("fseek failed");
$buf = fread($gi->filehandle, 2 * $gi->record_length);
}
$x = array(0,0);
for ($i = 0; $i < 2; ++$i) {
for ($j = 0; $j < $gi->record_length; ++$j) {
$x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
}
}
$bnum = 127 - $depth;
$idx = $bnum >> 3;
$b_mask = 1 << ( $bnum & 7 ^ 7 );
if (($v6vec[$idx] & $b_mask) > 0) {
if ($x[1] >= $gi->databaseSegments) {
return $x[1];
}
$offset = $x[1];
} else {
if ($x[0] >= $gi->databaseSegments) {
return $x[0];
}
$offset = $x[0];
}
}
trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
return false;
}
function _geoip_seek_country($gi, $ipnum) {
$offset = 0;
for ($depth = 31; $depth >= 0; --$depth) {
if ($gi->flags & GEOIP_MEMORY_CACHE) {
// workaround php's broken substr, strpos, etc handling with
// mbstring.func_overload and mbstring.internal_encoding
$enc = mb_internal_encoding();
mb_internal_encoding('ISO-8859-1');
$buf = substr($gi->memory_buffer,
2 * $gi->record_length * $offset,
2 * $gi->record_length);
mb_internal_encoding($enc);
} elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
$buf = @shmop_read ($gi->shmid,
2 * $gi->record_length * $offset,
2 * $gi->record_length );
} else {
fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
or die("fseek failed");
$buf = fread($gi->filehandle, 2 * $gi->record_length);
}
$x = array(0,0);
for ($i = 0; $i < 2; ++$i) {
for ($j = 0; $j < $gi->record_length; ++$j) {
$x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
}
}
if ($ipnum & (1 << $depth)) {
if ($x[1] >= $gi->databaseSegments) {
return $x[1];
}
$offset = $x[1];
} else {
if ($x[0] >= $gi->databaseSegments) {
return $x[0];
}
$offset = $x[0];
}
}
trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
return false;
}
function _common_get_org($gi, $seek_org){
$record_pointer = $seek_org + (2 * $gi->record_length - 1) * $gi->databaseSegments;
if ($gi->flags & GEOIP_SHARED_MEMORY) {
$org_buf = @shmop_read ($gi->shmid, $record_pointer, MAX_ORG_RECORD_LENGTH);
} else {
fseek($gi->filehandle, $record_pointer, SEEK_SET);
$org_buf = fread($gi->filehandle,MAX_ORG_RECORD_LENGTH);
}
// workaround php's broken substr, strpos, etc handling with
// mbstring.func_overload and mbstring.internal_encoding
$enc = mb_internal_encoding();
mb_internal_encoding('ISO-8859-1');
$org_buf = substr($org_buf, 0, strpos($org_buf, "\0"));
mb_internal_encoding($enc);
return $org_buf;
}
function _get_org_v6($gi,$ipnum){
$seek_org = _geoip_seek_country_v6($gi,$ipnum);
if ($seek_org == $gi->databaseSegments) {
return NULL;
}
return _common_get_org($gi, $seek_org);
}
function _get_org($gi,$ipnum){
$seek_org = _geoip_seek_country($gi,$ipnum);
if ($seek_org == $gi->databaseSegments) {
return NULL;
}
return _common_get_org($gi, $seek_org);
}
function geoip_name_by_addr_v6 ($gi,$addr) {
if ($addr == NULL) {
return 0;
}
$ipnum = inet_pton($addr);
return _get_org_v6($gi, $ipnum);
}
function geoip_name_by_addr ($gi,$addr) {
if ($addr == NULL) {
return 0;
}
$ipnum = ip2long($addr);
return _get_org($gi, $ipnum);
}
function geoip_org_by_addr ($gi,$addr) {
return geoip_name_by_addr($gi, $addr);
}
function _get_region($gi,$ipnum){
if ($gi->databaseType == GEOIP_REGION_EDITION_REV0){
$seek_region = _geoip_seek_country($gi,$ipnum) - GEOIP_STATE_BEGIN_REV0;
if ($seek_region >= 1000){
$country_code = "US";
$region = chr(($seek_region - 1000)/26 + 65) . chr(($seek_region - 1000)%26 + 65);
} else {
$country_code = $gi->GEOIP_COUNTRY_CODES[$seek_region];
$region = "";
}
return array ($country_code,$region);
} else if ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
$seek_region = _geoip_seek_country($gi,$ipnum) - GEOIP_STATE_BEGIN_REV1;
//print $seek_region;
if ($seek_region < US_OFFSET){
$country_code = "";
$region = "";
} else if ($seek_region < CANADA_OFFSET) {
$country_code = "US";
$region = chr(($seek_region - US_OFFSET)/26 + 65) . chr(($seek_region - US_OFFSET)%26 + 65);
} else if ($seek_region < WORLD_OFFSET) {
$country_code = "CA";
$region = chr(($seek_region - CANADA_OFFSET)/26 + 65) . chr(($seek_region - CANADA_OFFSET)%26 + 65);
} else {
$country_code = $gi->GEOIP_COUNTRY_CODES[($seek_region - WORLD_OFFSET) / FIPS_RANGE];
$region = "";
}
return array ($country_code,$region);
}
}
function geoip_region_by_addr ($gi,$addr) {
if ($addr == NULL) {
return 0;
}
$ipnum = ip2long($addr);
return _get_region($gi, $ipnum);
}
function getdnsattributes ($l,$ip){
$r = new Net_DNS_Resolver();
$r->nameservers = array("ws1.maxmind.com");
$p = $r->search($l."." . $ip .".s.maxmind.com","TXT","IN");
$str = is_object($p->answer[0])?$p->answer[0]->string():'';
$str = substr( $str, 1, -1 );
return $str;
}
?>

View File

@ -1,27 +0,0 @@
<html>
<head>
<title>PHP-gettext examples</title>
</head>
<body>
<h1>PHP-gettext</h1>
<h2>Introduction</h2>
<p>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.</p>
<p>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)</p>
<h2>Examples</h2>
<ul>
<li><a href="pigs_dropin.php">PHP-gettext as a dropin replacement</a></li>
<li><a href="pigs_fallback.php">PHP-gettext as a fallback solution</a></li>
</ul>
<hr />
<p>Copyright (c) 2003-2006 Danilo Segan</p>
<p>Copyright (c) 2005-2006 Steven Armstrong</p>
</body>
</html>

View File

@ -1,30 +0,0 @@
# Sample translation for PHP-gettext 1.0
# Copyright (c) 2003 Danilo Segan <danilo@kvota.net>
#
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 <danilo@kvota.net>\n"
"Language-Team: Serbian (sr) <danilo@kvota.net>\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"

View File

@ -1,30 +0,0 @@
# Sample translation for PHP-gettext 1.0
# Copyright (c) 2003,2006 Danilo Segan <danilo@kvota.net>
#
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 <danilo@kvota.net>\n"
"Language-Team: Serbian (sr) <danilo@kvota.net>\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"

View File

@ -1,89 +0,0 @@
<?php
/*
Copyright (c) 2003,2004,2005,2009 Danilo Segan <danilo@kvota.net>.
Copyright (c) 2005,2006 Steven Armstrong <sa@c-area.ch>
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");
?>
<html>
<head>
<title>PHP-gettext dropin example</title>
</head>
<body>
<h1>PHP-gettext as a dropin replacement</h1>
<p>Example showing how to use PHP-gettext as a dropin replacement for the native gettext library.</p>
<?php
print "<p>";
foreach($supported_locales as $l) {
print "[<a href=\"?lang=$l\">$l</a>] ";
}
print "</p>\n";
if (!locale_emulation()) {
print "<p>locale '$locale' is supported by your system, using native gettext implementation.</p>\n";
}
else {
print "<p>locale '$locale' is _not_ supported on your system, using the default locale '". DEFAULT_LOCALE ."'.</p>\n";
}
?>
<hr />
<?php
// using PHP-gettext
print "<pre>";
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 "</pre>\n";
?>
<hr />
<p>&laquo; <a href="./">back</a></p>
</body>
</html>

View File

@ -1,88 +0,0 @@
<?php
/*
Copyright (c) 2003,2004,2005,2009 Danilo Segan <danilo@kvota.net>.
Copyright (c) 2005,2006 Steven Armstrong <sa@c-area.ch>
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");
?>
<html>
<head>
<title>PHP-gettext fallback example</title>
</head>
<body>
<h1>PHP-gettext as a fallback solution</h1>
<p>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.</p>
<?php
print "<p>";
foreach($supported_locales as $l) {
print "[<a href=\"?lang=$l\">$l</a>] ";
}
print "</p>\n";
if (!locale_emulation()) {
print "<p>locale '$locale' is supported by your system, using native gettext implementation.</p>\n";
}
else {
print "<p>locale '$locale' is <strong>not</strong> supported on your system, using custom gettext implementation.</p>\n";
}
?>
<hr />
<?php
// using PHP-gettext
print "<pre>";
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 "</pre>\n";
?>
<hr />
<p>&laquo; <a href="./">back</a></p>
</body>
</html>

View File

@ -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|<basename>]"
fi
fi

View File

@ -1,75 +0,0 @@
<?php
require_once('PHPUnit/Framework.php');
require_once('gettext.inc');
class LocaleTest extends PHPUnit_Framework_TestCase
{
public function test_setlocale()
{
putenv("LC_ALL=");
// _setlocale defaults to a locale name from environment variable LANG.
putenv("LANG=sr_RS");
$this->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(""));
}
}
?>

View File

@ -1,60 +0,0 @@
<?php
require_once('PHPUnit/Framework.php');
//require_once('gettext.php');
class ParsingTest extends PHPUnit_Framework_TestCase
{
public function test_extract_plural_forms_header_from_po_header()
{
$parser = new gettext_reader(NULL);
// It defaults to a "Western-style" plural header.
$this->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"),
);
}
}
?>

26
inc/lib/webm/README.md Normal file
View File

@ -0,0 +1,26 @@
This directory contains files being the integration of containerchan with vichan-devel imageboards.
Containerchan allows posting of webm files, like they were the regular images.
An original board using this code can be found at:
http://containerchan.org/tb/demo/
The original repo containing the containerchan (possibly with no Tinyboard integration) can be found here:
https://github.com/ccd0/containerchan
Be aware that this is beta software. Please report any bugs you find.
Installation
------------
Add these lines to inc/instance-config.php:
$config['allowed_ext_files'][] = 'webm';
$config['additional_javascript'][] = 'js/webm-settings.js';
$config['additional_javascript'][] = 'js/expand-video.js';
License
-------
See [LICENSE.md](https://github.com/ccd0/containerchan/blob/master/LICENSE.md).

View File

@ -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

524
inc/lib/webm/matroska.php Normal file
View File

@ -0,0 +1,524 @@
<?php
/* This file is dedicated to the public domain; you may do as you wish with it. */
// Information needed to parse an element type
class EBMLElementType {
public $name;
public $datatype;
public $validParents;
}
// Information needed to parse all possible element types in a document
class EBMLElementTypeList {
private $_els;
private $_ids;
public function __construct($filename) {
$lines = file($filename);
foreach($lines as $line) {
$fields = explode(' ', trim($line));
$t = new EBMLElementType;
$id = hexdec($fields[0]);
$t->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;
}

View File

@ -0,0 +1,49 @@
<?php
// Glue code for handling a Tinyboard post.
// Portions of this file are derived from Tinyboard code.
function postHandler($post) {
global $board, $config;
if ($post->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'];
}
}
}
}
}

173
inc/lib/webm/videodata.php Normal file
View File

@ -0,0 +1,173 @@
<?php
/* This file is dedicated to the public domain; you may do as you wish with it. */
require dirname(__FILE__) . '/matroska.php';
function matroskaSeekElement($name, $pos) {
return ebmlEncodeElement('Seek',
ebmlEncodeElement('SeekID', ebmlEncodeElementName($name))
. ebmlEncodeElement('SeekPosition', pack('N', $pos))
);
}
// Make video from single WebM keyframe
function muxWebMFrame($videoTrack, $frame) {
$lenSeekHead = 73;
$lenCues = 24;
// Determine version for EBML header
$version = 2;
$videoAttr = $videoTrack->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;
}

View File

@ -0,0 +1 @@
l10n = {"Style: ":"Estilo: ","File":"Archivo","hide":"ocultar","show":"mostrar","Show locked threads":"Mostrar hilos bloqueados","Hide locked threads":"Ocultar hilos bloqueados","URL":"URL","Select":"Seleccionar","Remote":"Remoto","Embed":"Incrustar","Oekaki":"Oekaki","hidden":"oculto","Show images":"Mostrar imagenes","Hide images":"Ocultar imagenes","Password":"Contrase\u00f1a","Delete file only":"Eliminar s\u00f3lo archivo","Delete":"Eliminar","Reason":"Raz\u00f3n","Report":"Reportar","Click reply to view.":"Click responder para ver.","Click to expand":"Click para expandir","Hide expanded replies":"Ocultar respuestas expandidas","Brush size":"Tama\u00f1o brush","Set text":"Establecer texto","Clear":"Limpiar","Save":"Guardar","Load":"Cargar","Toggle eraser":"Borrar marca","Get color":"Seleccionar color","Fill":"Llenar","Use oekaki instead of file?":"Usar oekaki en vez del archivo?","Edit in oekaki":"Editar en oekaki","Enter some text":"Pon alg\u00fan texto","Enter font or leave empty":"Pon una fuente o dejalo vac\u00edo","Forced anonymity":"Forzar anonimato","enabled":"activado","disabled":"desactivado","Sun":"Dom","Mon":"Lun","Tue":"Mar","Wed":"Mie","Thu":"Jue","Fri":"Vie","Sat":"S\u00e1","Catalog":"Cat\u00e1logo","Submit":"Enviar","Quick reply":"Respuesta r\u00e1pida","Posting mode: Replying to <small>&gt;&gt;{0}<\/small>":"Respondiendo a <small>&gt;&gt;{0}<\/small>","Return":"Volver","Expand all images":"Expandir todas las im\u00e1genes","Hello!":"Hola!","{0} users":"{0} usuarios","(hide threads from this board)":"(ocultar hilos de este tabl\u00f3n)","(show threads from this board)":"(mostrar hilos de este tabl\u00f3n)","No more threads to display":"No hay m\u00e1s hilos para mostrar","Loading...":"Cargando...","Save as original filename":"Guardar con el nombre original del archivo","Reported post(s).":"Post(s) reportados.","An unknown error occured!":"Ocurri\u00f3 un error desconocido!","Something went wrong... An unknown error occured!":"Algo fue mal... Ocurri\u00f3 un error desconocido!","Working...":"Trabajando...","Posting... (#%)":"Posteando... (#%)","Posted...":"Posteado...","An unknown error occured when posting!":"Ocurri\u00f3 un error desconocido mientras posteabas!","Posting...":"Posteando...","Upload URL":"Subir URL","Spoiler Image":"Imagen Spoiler","Comment":"Comentario","Quick Reply":"Respuesta r\u00e1pida","Stop watching this thread":"Para de ver este hilo","Watch this thread":"Ver este hilo","Unpin this board":"Desmarcar este hilo","Pin this board":"Marcar este hilo","Stop watching this board":"Para de ver este hilo","Watch this board":"Ver este hilo","Click on any image on this site to load it into oekaki applet":"Click en cualquier sitio para cargar el oekaki applet","Sunday":"Domingo","Monday":"Lunes","Tuesday":"Martes","Wednesday":"Mi\u00e9rcoles","Thursday":"Jueves","Friday":"Viernes","Saturday":"S\u00e1bado","January":"Enero","February":"Febrero","March":"Marzo","April":"Abril","May":"Mayo","June":"Junio","July":"Julio","August":"Agosto","September":"Septiembre","October":"Octubre","November":"Noviembre","December":"Diciembre","Jan":"Ene","Feb":"Feb","Mar":"Mar","Apr":"Abr","Jun":"Jun","Jul":"Jul","Aug":"Aug","Sep":"Sep","Oct":"Oct","Nov":"Nov","Dec":"Dic","AM":"AM","PM":"PM","am":"am","pm":"pm"};

View File

@ -0,0 +1,533 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-23 19:40+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../../../../js/style-select.js:40 ../../../../js/style-select.js:41
msgid "Style: "
msgstr "Estilo: "
#: ../../../../js/hide-images.js:50 ../../../../js/upload-selection.js:51
#: ../../../../js/quick-post-controls.js:30 ../../../../js/hide-images.js:51
#: ../../../../js/quick-post-controls.js:32
#: ../../../../js/upload-selection.js:61
msgid "File"
msgstr "Archivo"
#: ../../../../js/hide-images.js:50 ../../../../js/hide-images.js:51
msgid "hide"
msgstr "ocultar"
#: ../../../../js/hide-images.js:56 ../../../../js/hide-images.js:57
msgid "show"
msgstr "mostrar"
#: ../../../../js/toggle-locked-threads.js:39
#: ../../../../js/toggle-locked-threads.js:54
#: ../../../../js/toggle-locked-threads.js:40
#: ../../../../js/toggle-locked-threads.js:55
#: ../../../../js/toggle-locked-threads.js:41
#: ../../../../js/toggle-locked-threads.js:56
msgid "Show locked threads"
msgstr "Mostrar hilos bloqueados"
#: ../../../../js/toggle-locked-threads.js:39
#: ../../../../js/toggle-locked-threads.js:54
#: ../../../../js/toggle-locked-threads.js:40
#: ../../../../js/toggle-locked-threads.js:55
#: ../../../../js/toggle-locked-threads.js:41
#: ../../../../js/toggle-locked-threads.js:56
msgid "Hide locked threads"
msgstr "Ocultar hilos bloqueados"
#: ../../../../js/upload-selection.js:32 ../../../../js/upload-selection.js:45
msgid "URL"
msgstr "URL"
#: ../../../../js/upload-selection.js:50 ../../../../js/upload-selection.js:60
msgid "Select"
msgstr "Seleccionar"
#: ../../../../js/upload-selection.js:53 ../../../../js/upload-selection.js:63
msgid "Remote"
msgstr "Remoto"
#: ../../../../js/upload-selection.js:56 ../../../../js/upload-selection.js:66
msgid "Embed"
msgstr "Incrustar"
#: ../../../../js/upload-selection.js:59 ../../../../js/upload-selection.js:69
msgid "Oekaki"
msgstr "Oekaki"
#: ../../../../js/toggle-images.js:41 ../../../../js/toggle-images.js:42
msgid "hidden"
msgstr "oculto"
#: ../../../../js/toggle-images.js:57 ../../../../js/toggle-images.js:70
#: ../../../../js/toggle-images.js:58 ../../../../js/toggle-images.js:71
msgid "Show images"
msgstr "Mostrar imagenes"
#: ../../../../js/toggle-images.js:57 ../../../../js/toggle-images.js:70
#: ../../../../js/toggle-images.js:58 ../../../../js/toggle-images.js:71
msgid "Hide images"
msgstr "Ocultar imagenes"
#: ../../../../js/quick-post-controls.js:27
#: ../../../../js/quick-post-controls.js:29
msgid "Password"
msgstr "Contraseña"
#: ../../../../js/quick-post-controls.js:29
#: ../../../../js/quick-post-controls.js:31
msgid "Delete file only"
msgstr "Eliminar sólo archivo"
#: ../../../../js/quick-post-controls.js:31
#: ../../../../js/quick-post-controls.js:33
msgid "Delete"
msgstr "Eliminar"
#: ../../../../js/quick-post-controls.js:35
#: ../../../../js/quick-post-controls.js:37
msgid "Reason"
msgstr "Razón"
#: ../../../../js/quick-post-controls.js:37
#: ../../../../js/quick-post-controls.js:39
msgid "Report"
msgstr "Reportar"
#: ../../../../js/expand.js:20 ../../../../js/expand.js:22
msgid "Click reply to view."
msgstr "Click responder para ver."
#: ../../../../js/expand.js:20 ../../../../js/expand.js:22
msgid "Click to expand"
msgstr "Click para expandir"
#: ../../../../js/expand.js:44 ../../../../js/expand.js:46
msgid "Hide expanded replies"
msgstr "Ocultar respuestas expandidas"
#: ../../../../js/oekaki.js:10
msgid "Brush size"
msgstr "Tamaño brush"
#: ../../../../js/oekaki.js:10
msgid "Set text"
msgstr "Establecer texto"
#: ../../../../js/oekaki.js:10
msgid "Clear"
msgstr "Limpiar"
#: ../../../../js/oekaki.js:10
msgid "Save"
msgstr "Guardar"
#: ../../../../js/oekaki.js:10
msgid "Load"
msgstr "Cargar"
#: ../../../../js/oekaki.js:11
msgid "Toggle eraser"
msgstr "Borrar marca"
#: ../../../../js/oekaki.js:11
msgid "Get color"
msgstr "Seleccionar color"
#: ../../../../js/oekaki.js:11
msgid "Fill"
msgstr "Llenar"
#: ../../../../js/oekaki.js:12
msgid "Use oekaki instead of file?"
msgstr "Usar oekaki en vez del archivo?"
#: ../../../../js/oekaki.js:21
msgid "Edit in oekaki"
msgstr "Editar en oekaki"
#: ../../../../js/oekaki.js:152
msgid "Enter some text"
msgstr "Pon algún texto"
#: ../../../../js/oekaki.js:153
msgid "Enter font or leave empty"
msgstr "Pon una fuente o dejalo vacío"
#: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:65
#: ../../../../js/forced-anon.js:69 ../../../../js/forced-anon.js:60
#: ../../../../js/forced-anon.js:66 ../../../../js/forced-anon.js:70
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:67
#: ../../../../js/forced-anon.js:71
msgid "Forced anonymity"
msgstr "Forzar anonimato"
#: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:65
#: ../../../../js/forced-anon.js:60 ../../../../js/forced-anon.js:66
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:67
msgid "enabled"
msgstr "activado"
#: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:69
#: ../../../../js/forced-anon.js:60 ../../../../js/forced-anon.js:70
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:71
msgid "disabled"
msgstr "desactivado"
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
#: ../../../../js/local-time.js:30
msgid "Sun"
msgstr "Dom"
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
#: ../../../../js/local-time.js:30
msgid "Mon"
msgstr "Lun"
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
#: ../../../../js/local-time.js:30
msgid "Tue"
msgstr "Mar"
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
#: ../../../../js/local-time.js:30
msgid "Wed"
msgstr "Mie"
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
#: ../../../../js/local-time.js:30
msgid "Thu"
msgstr "Jue"
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
#: ../../../../js/local-time.js:30
msgid "Fri"
msgstr "Vie"
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
#: ../../../../js/local-time.js:30
msgid "Sat"
msgstr "Sá"
#: ../../../../js/catalog-link.js:21 ../../../../js/catalog-link.js:32
#: ../../../../js/catalog-link.js:40 ../../../../js/catalog-link.js:33
#: ../../../../js/catalog-link.js:44 ../../../../js/catalog-link.js:52
msgid "Catalog"
msgstr "Catálogo"
#: ../../../../js/quick-reply.js:21 ../../../../js/quick-reply-old.js:21
#: ../../../../js/quick-reply-old.js:23
msgid "Submit"
msgstr "Enviar"
#: ../../../../js/quick-reply.js:31 ../../../../js/quick-reply-old.js:31
#: ../../../../js/quick-reply-old.js:33
msgid "Quick reply"
msgstr "Respuesta rápida"
#: ../../../../js/quick-reply.js:33 ../../../../js/quick-reply-old.js:33
#: ../../../../js/quick-reply-old.js:35
#, python-brace-format
msgid "Posting mode: Replying to <small>&gt;&gt;{0}</small>"
msgstr "Respondiendo a <small>&gt;&gt;{0}</small>"
#: ../../../../js/quick-reply.js:33 ../../../../js/quick-reply-old.js:33
#: ../../../../js/quick-reply-old.js:35
msgid "Return"
msgstr "Volver"
#: ../../../../js/expand-all-images.js:20
#: ../../../../js/expand-all-images.js:21
#: ../../../../js/expand-all-images.js:22
msgid "Expand all images"
msgstr "Expandir todas las imágenes"
#: ../../../../templates/main.js:6
msgid "Hello!"
msgstr "Hola!"
#: ../../../../templates/main.js:18
#, python-brace-format
msgid "{0} users"
msgstr "{0} usuarios"
#: ../../../../templates/themes/ukko/ukko.js:28
#: ../../../../templates/themes/ukko/ukko.js:39
#: ../../../../templates/themes/ukko/ukko.js:29
#: ../../../../templates/themes/ukko/ukko.js:40
msgid "(hide threads from this board)"
msgstr "(ocultar hilos de este tablón)"
#: ../../../../templates/themes/ukko/ukko.js:32
#: ../../../../templates/themes/ukko/ukko.js:44
#: ../../../../templates/themes/ukko/ukko.js:33
#: ../../../../templates/themes/ukko/ukko.js:45
msgid "(show threads from this board)"
msgstr "(mostrar hilos de este tablón)"
#: ../../../../templates/themes/ukko/ukko.js:57
#: ../../../../templates/themes/ukko/ukko.js:58
msgid "No more threads to display"
msgstr "No hay más hilos para mostrar"
#: ../../../../templates/themes/ukko/ukko.js:79
#: ../../../../templates/themes/ukko/ukko.js:80
msgid "Loading..."
msgstr "Cargando..."
#: ../../../../js/download-original.js:32
#: ../../../../js/download-original.js:33
msgid "Save as original filename"
msgstr "Guardar con el nombre original del archivo"
#: ../../../../js/ajax-post-controls.js:43
msgid "Reported post(s)."
msgstr "Post(s) reportados."
#: ../../../../js/ajax-post-controls.js:53
msgid "An unknown error occured!"
msgstr "Ocurrió un error desconocido!"
#: ../../../../js/ajax-post-controls.js:60
msgid "Something went wrong... An unknown error occured!"
msgstr "Algo fue mal... Ocurrió un error desconocido!"
#: ../../../../js/ajax-post-controls.js:68
msgid "Working..."
msgstr "Trabajando..."
#: ../../../../js/ajax.js:42 ../../../../js/ajax.js:45
msgid "Posting... (#%)"
msgstr "Posteando... (#%)"
#: ../../../../js/ajax.js:104 ../../../../js/ajax.js:109
msgid "Posted..."
msgstr "Posteado..."
#: ../../../../js/ajax.js:106 ../../../../js/ajax.js:111
msgid "An unknown error occured when posting!"
msgstr "Ocurrió un error desconocido mientras posteabas!"
#: ../../../../js/ajax.js:130 ../../../../js/ajax.js:135
msgid "Posting..."
msgstr "Posteando..."
#: ../../../../js/quick-reply.js:223 ../../../../js/quick-reply.js:224
msgid "Upload URL"
msgstr "Subir URL"
#: ../../../../js/quick-reply.js:266 ../../../../js/quick-reply.js:267
msgid "Spoiler Image"
msgstr "Imagen Spoiler"
#: ../../../../js/quick-reply.js:277 ../../../../js/quick-reply.js:278
msgid "Comment"
msgstr "Comentario"
#: ../../../../js/quick-reply.js:285 ../../../../js/quick-reply.js:406
#: ../../../../js/quick-reply.js:286 ../../../../js/quick-reply.js:407
msgid "Quick Reply"
msgstr "Respuesta rápida"
#: ../../../../js/watch.js:249 ../../../../js/watch.js:250
#: ../../../../js/watch.js:288 ../../../../js/watch.js:289
#: ../../../../js/watch.js:330 ../../../../js/watch.js:331
msgid "Stop watching this thread"
msgstr "Para de ver este hilo"
#: ../../../../js/watch.js:249 ../../../../js/watch.js:250
#: ../../../../js/watch.js:288 ../../../../js/watch.js:289
#: ../../../../js/watch.js:330 ../../../../js/watch.js:331
msgid "Watch this thread"
msgstr "Ver este hilo"
#: ../../../../js/watch.js:260 ../../../../js/watch.js:261
#: ../../../../js/watch.js:269 ../../../../js/watch.js:299
#: ../../../../js/watch.js:300 ../../../../js/watch.js:308
#: ../../../../js/watch.js:341 ../../../../js/watch.js:342
#: ../../../../js/watch.js:350
msgid "Unpin this board"
msgstr "Desmarcar este hilo"
#: ../../../../js/watch.js:260 ../../../../js/watch.js:261
#: ../../../../js/watch.js:269 ../../../../js/watch.js:299
#: ../../../../js/watch.js:300 ../../../../js/watch.js:308
#: ../../../../js/watch.js:341 ../../../../js/watch.js:342
#: ../../../../js/watch.js:350
msgid "Pin this board"
msgstr "Marcar este hilo"
#: ../../../../js/watch.js:262 ../../../../js/watch.js:267
#: ../../../../js/watch.js:268 ../../../../js/watch.js:301
#: ../../../../js/watch.js:306 ../../../../js/watch.js:307
#: ../../../../js/watch.js:343 ../../../../js/watch.js:348
#: ../../../../js/watch.js:349
msgid "Stop watching this board"
msgstr "Para de ver este hilo"
#: ../../../../js/watch.js:262 ../../../../js/watch.js:267
#: ../../../../js/watch.js:268 ../../../../js/watch.js:301
#: ../../../../js/watch.js:306 ../../../../js/watch.js:307
#: ../../../../js/watch.js:343 ../../../../js/watch.js:348
#: ../../../../js/watch.js:349
msgid "Watch this board"
msgstr "Ver este hilo"
#: ../../../../js/wpaint.js:113
msgid "Click on any image on this site to load it into oekaki applet"
msgstr "Click en cualquier sitio para cargar el oekaki applet"
#: ../../../../js/local-time.js:29
msgid "Sunday"
msgstr "Domingo"
#: ../../../../js/local-time.js:29
msgid "Monday"
msgstr "Lunes"
#: ../../../../js/local-time.js:29
msgid "Tuesday"
msgstr "Martes"
#: ../../../../js/local-time.js:29
msgid "Wednesday"
msgstr "Miércoles"
#: ../../../../js/local-time.js:29
msgid "Thursday"
msgstr "Jueves"
#: ../../../../js/local-time.js:29
msgid "Friday"
msgstr "Viernes"
#: ../../../../js/local-time.js:29
msgid "Saturday"
msgstr "Sábado"
#: ../../../../js/local-time.js:31
msgid "January"
msgstr "Enero"
#: ../../../../js/local-time.js:31
msgid "February"
msgstr "Febrero"
#: ../../../../js/local-time.js:31
msgid "March"
msgstr "Marzo"
#: ../../../../js/local-time.js:31
msgid "April"
msgstr "Abril"
#: ../../../../js/local-time.js:31 ../../../../js/local-time.js:32
msgid "May"
msgstr "Mayo"
#: ../../../../js/local-time.js:31
msgid "June"
msgstr "Junio"
#: ../../../../js/local-time.js:31
msgid "July"
msgstr "Julio"
#: ../../../../js/local-time.js:31
msgid "August"
msgstr "Agosto"
#: ../../../../js/local-time.js:31
msgid "September"
msgstr "Septiembre"
#: ../../../../js/local-time.js:31
msgid "October"
msgstr "Octubre"
#: ../../../../js/local-time.js:31
msgid "November"
msgstr "Noviembre"
#: ../../../../js/local-time.js:31
msgid "December"
msgstr "Diciembre"
#: ../../../../js/local-time.js:32
msgid "Jan"
msgstr "Ene"
#: ../../../../js/local-time.js:32
msgid "Feb"
msgstr "Feb"
#: ../../../../js/local-time.js:32
msgid "Mar"
msgstr "Mar"
#: ../../../../js/local-time.js:32
msgid "Apr"
msgstr "Abr"
#: ../../../../js/local-time.js:32
msgid "Jun"
msgstr "Jun"
#: ../../../../js/local-time.js:32
msgid "Jul"
msgstr "Jul"
#: ../../../../js/local-time.js:32
msgid "Aug"
msgstr "Aug"
#: ../../../../js/local-time.js:32
msgid "Sep"
msgstr "Sep"
#: ../../../../js/local-time.js:32
msgid "Oct"
msgstr "Oct"
#: ../../../../js/local-time.js:32
msgid "Nov"
msgstr "Nov"
#: ../../../../js/local-time.js:32
msgid "Dec"
msgstr "Dic"
#: ../../../../js/local-time.js:33
msgid "AM"
msgstr "AM"
#: ../../../../js/local-time.js:34
msgid "PM"
msgstr "PM"
#: ../../../../js/local-time.js:35
msgid "am"
msgstr "am"
#: ../../../../js/local-time.js:36
msgid "pm"
msgstr "pm"

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,857 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# CHAFIK <admin@cable6.net>, 2014.
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-04-21 11:29-0400\n"
"PO-Revision-Date: 2014-01-20 07:05+0200\n"
"Last-Translator: CHAFIK <admin@cable6.net>\n"
"Language-Team: cable6.net\n"
"Language: fr\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"
"X-Generator: Virtaal 0.7.1\n"
#: ../../inc/lib/gettext/examples/pigs_dropin.php:77
msgid ""
"This is how the story goes.\n"
"\n"
msgstr ""
"Il y a un début à toute chose.\n"
"\n"
#: ../../inc/functions.php:1046 ../../inc/functions.php:1060
msgid "Previous"
msgstr "Précédent"
#: ../../inc/functions.php:1065 ../../inc/functions.php:1074
msgid "Next"
msgstr "Suivant"
#: ../../inc/display.php:91 ../../inc/mod/pages.php:62
msgid "Login"
msgstr "Identifiant"
#: ../../inc/config.php:687
msgid "Lurk some more before posting."
msgstr "Rôde plus avant de poster."
#: ../../inc/config.php:688
msgid "You look like a bot."
msgstr "Tu ressembles à un bot."
#: ../../inc/config.php:689
msgid "Your browser sent an invalid or no HTTP referer."
msgstr "Votre navigateur nous a envoyé un référant invalide ou aucun référant."
#: ../../inc/config.php:690
#, php-format
msgid "The %s field was too long."
msgstr "Le champ %s comporte trop de caractères."
#: ../../inc/config.php:691
msgid "The body was too long."
msgstr "Vous avez atteint la limite de caractères pour le texte."
#: ../../inc/config.php:692
msgid "The body was too short or empty."
msgstr "Ce texte est trop court ou vide."
#: ../../inc/config.php:693
msgid "You must upload an image."
msgstr "Vous devez mettre en ligne une image."
#: ../../inc/config.php:694
msgid "The server failed to handle your upload."
msgstr "Le serveur a échoué la mise en ligne de votre image."
#: ../../inc/config.php:695
msgid "Unsupported image format."
msgstr "Format d'image non-supporté."
#: ../../inc/config.php:696
msgid "Invalid board!"
msgstr "Planche invalide."
#: ../../inc/config.php:697
msgid "Thread specified does not exist."
msgstr "Le fil spécifié n'existe pas."
#: ../../inc/config.php:698
msgid "Thread locked. You may not reply at this time."
msgstr "Fil verrouillé."
#: ../../inc/config.php:699
msgid "You didn't make a post."
msgstr "Vous n'avez pas écrit de message."
#: ../../inc/config.php:700
msgid "Flood detected; Post discarded."
msgstr "Flood détecté ; Message ignoré."
#: ../../inc/config.php:701
msgid "Your request looks automated; Post discarded."
msgstr "Votre requête semble automatisée ; Message ignoré."
#: ../../inc/config.php:702
msgid "Unoriginal content!"
msgstr "Ce contenu n'est pas original."
#: ../../inc/config.php:703
#, php-format
msgid "Unoriginal content! You have been muted for %d seconds."
msgstr "Ce contenu n'est pas original. Vous avez été muté pour %d secondes."
#: ../../inc/config.php:704
#, php-format
msgid "You are muted! Expires in %d seconds."
msgstr "Tu as été muté. Interdiction de poster pendant %d secondes."
#: ../../inc/config.php:705
#, php-format
msgid "Your IP address is listed in %s."
msgstr "Votre addresse IP est listée en %s."
#: ../../inc/config.php:706
msgid "Too many links; flood detected."
msgstr "Trop de liens ; Flood détecté."
#: ../../inc/config.php:707
msgid "Too many cites; post discarded."
msgstr "Trop de citations ; Message ignoré."
#: ../../inc/config.php:708
msgid "Too many cross-board links; post discarded."
msgstr "Trop de liens cross-planches ; message ignoré."
#: ../../inc/config.php:709
msgid "You didn't select anything to delete."
msgstr "Vous n'avez rien sélectionné à supprimer."
#: ../../inc/config.php:710
msgid "You didn't select anything to report."
msgstr "Vous n'avez rien sélectionné à reporter."
#: ../../inc/config.php:711
msgid "You can't report that many posts at once."
msgstr "Vous ne pouvez pas reporter autant de messages à la fois."
#: ../../inc/config.php:712
msgid "Wrong password…"
msgstr "Mot de passe incorrect."
#: ../../inc/config.php:713
msgid "Invalid image."
msgstr "Image invalide."
#: ../../inc/config.php:714
msgid "Unknown file extension."
msgstr "Fichier d'extension inconnu."
#: ../../inc/config.php:715
msgid "Maximum file size: %maxsz% bytes<br>Your file's size: %filesz% bytes"
msgstr ""
"Maximum de la taille d'un fichier requis : %maxsz% octets<br>La taille de "
"votre fichier : %filesz% octets"
#: ../../inc/config.php:716
msgid "The file was too big."
msgstr "Ce fichier est trop volumineux."
#: ../../inc/config.php:717
msgid "Invalid archive!"
msgstr "Archive invalide !"
#: ../../inc/config.php:718
#, php-format
msgid "That file <a href=\"%s\">already exists</a>!"
msgstr "Le fichier <a href=\"%s\">a déjà été mis en ligne ici : </a>"
#: ../../inc/config.php:719
#, php-format
msgid "That file <a href=\"%s\">already exists</a> in this thread!"
msgstr "Ce fichier <a href=\"%s\">existe déjà</a> dans ce fil."
#: ../../inc/config.php:720
#, php-format
msgid "You'll have to wait another %s before deleting that."
msgstr "Vous devez attendre encore %s avant de supprimer votre message."
#: ../../inc/config.php:721
msgid "MIME type detection XSS exploit (IE) detected; post discarded."
msgstr "Exploitation XSS de type MIME (IE) détecté; Message ignoré."
#: ../../inc/config.php:722
msgid "Couldn't make sense of the URL of the video you tried to embed."
msgstr "L'URL de votre vidéo est fausse."
#: ../../inc/config.php:723
msgid "You seem to have mistyped the verification."
msgstr "Vous semblez avoir fait une erreur lors de votre vérification."
#: ../../inc/config.php:726
msgid "Invalid username and/or password."
msgstr "Identifiant et/ou mot de passe inválide(s)."
#: ../../inc/config.php:727
msgid "You are not a mod…"
msgstr "Vous n'êtes pas modérateurs."
#: ../../inc/config.php:728
msgid ""
"Invalid username and/or password. Your user may have been deleted or changed."
msgstr ""
"Identifiant et/ou mot de passe inválide(s). L'identifiant a pu être supprimé "
"ou modifié."
#: ../../inc/config.php:729
msgid "Invalid/malformed cookies."
msgstr "Cookies inválides ou mal formés."
#: ../../inc/config.php:730
msgid "Your browser didn't submit an input when it should have."
msgstr "Votre navigateur n'a pas envoyé de données lorsqu'il devait le faire."
#: ../../inc/config.php:731
#, php-format
msgid "The %s field is required."
msgstr "Le champ %s est obligatoire."
#: ../../inc/config.php:732
#, php-format
msgid "The %s field was invalid."
msgstr "Le champ %s est invalide."
#: ../../inc/config.php:733
#, php-format
msgid "There is already a %s board."
msgstr "Il existe déjà une planche %s."
#: ../../inc/config.php:734
msgid "You don't have permission to do that."
msgstr "Vous n'avez pas la permission de le faire."
#: ../../inc/config.php:735
msgid "That post doesn't exist…"
msgstr "Ce message n'existe pas."
#: ../../inc/config.php:736
msgid "Page not found."
msgstr "Page introuvable."
#: ../../inc/config.php:737
#, php-format
msgid "That mod <a href=\"?/users/%d\">already exists</a>!"
msgstr "Le modo <a href=\"?/users/%d\"> existe déjà : </a>"
#: ../../inc/config.php:738
msgid "That theme doesn't exist!"
msgstr "Ce thème n'existe pas."
#: ../../inc/config.php:739
msgid "Invalid security token! Please go back and try again."
msgstr ""
"Le Token de securité est invalide. Veuillez retourner à la page précédent et "
"recommencer."
#: ../../inc/mod/pages.php:66
msgid "Confirm action"
msgstr "Confirmer cette action."
#: ../../inc/mod/pages.php:110
msgid "Could not find current version! (Check .installed)"
msgstr "Version actuelle introuvable. (Verifiez .installed)"
#: ../../inc/mod/pages.php:151
msgid "Dashboard"
msgstr "Panneau de Configuration"
#: ../../inc/mod/pages.php:228
msgid "Edit board"
msgstr "Editer cette planche"
#: ../../inc/mod/pages.php:261
msgid "Couldn't open board after creation."
msgstr "Ouverture de cette planche impossible après sa création."
#: ../../inc/mod/pages.php:276
msgid "New board"
msgstr "Nouvelle planche"
#: ../../inc/mod/pages.php:322
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:96
msgid "Noticeboard"
msgstr "Notifications"
#: ../../inc/mod/pages.php:382
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:166
msgid "News"
msgstr "Nouvelles"
#: ../../inc/mod/pages.php:422 ../../inc/mod/pages.php:449
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:255
msgid "Moderation log"
msgstr "Modération"
#: ../../inc/mod/pages.php:592
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:247
#: ../../templates/cache/18/9c/c365d711719f494c684aab98a4ae.php:65
msgid "IP"
msgstr "IP"
#: ../../inc/mod/pages.php:602 ../../inc/mod/pages.php:993
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:377
msgid "New ban"
msgstr "Nouveau banni"
#: ../../inc/mod/pages.php:670
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:224
msgid "Ban list"
msgstr "Liste des bannis"
#: ../../inc/mod/pages.php:765
#, fuzzy
msgid "Target and source board are the same."
msgstr "La cible et la source de la planche sont les mêmes."
#: ../../inc/mod/pages.php:927
msgid "Impossible to move thread; there is only one board."
msgstr "Impossible de déplacer ce fil ; il n'y a qu'une seule planche."
#: ../../inc/mod/pages.php:931
msgid "Move thread"
msgstr "Déplacer fil"
#: ../../inc/mod/pages.php:1045
msgid "Edit post"
msgstr "Éditer message"
#: ../../inc/mod/pages.php:1271 ../../inc/mod/pages.php:1320
msgid "Edit user"
msgstr "Éditer identifiant"
#: ../../inc/mod/pages.php:1333
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:232
msgid "Manage users"
msgstr "Administration"
#: ../../inc/mod/pages.php:1395 ../../inc/mod/pages.php:1467
msgid "New PM for"
msgstr "Nouveau MP de"
#: ../../inc/mod/pages.php:1399
msgid "Private message"
msgstr "Message privé"
#: ../../inc/mod/pages.php:1420
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:171
msgid "PM inbox"
msgstr "Messagerie"
#: ../../inc/mod/pages.php:1531 ../../inc/mod/pages.php:1535
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:263
msgid "Rebuild"
msgstr "Reconstruire"
#: ../../inc/mod/pages.php:1621
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:207
msgid "Report queue"
msgstr "Fil des reports"
#: ../../inc/mod/pages.php:1743
msgid "Config editor"
msgstr "Éditer la configuration"
#: ../../inc/mod/pages.php:1753
msgid "Themes directory doesn't exist!"
msgstr "Le répertoire de thèmes n'existe pas."
#: ../../inc/mod/pages.php:1755
msgid "Cannot open themes directory; check permissions."
msgstr "Vous n'avez pas la permission de créer un nouveau répertoire"
#: ../../inc/mod/pages.php:1769
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:247
msgid "Manage themes"
msgstr "Gérer les thèmes"
#: ../../inc/mod/pages.php:1831
#, php-format
msgid "Installed theme: %s"
msgstr "Thème installé : %s"
#: ../../inc/mod/pages.php:1841
#, php-format
msgid "Configuring theme: %s"
msgstr "Thème configuré : %s"
#: ../../inc/mod/pages.php:1869
#, php-format
msgid "Rebuilt theme: %s"
msgstr "Thème reconstruit : %s"
#: ../../inc/mod/pages.php:1908
msgid "Debug: Anti-spam"
msgstr "Debug : Anti-spam"
#: ../../inc/mod/pages.php:1932
msgid "Debug: Recent posts"
msgstr "Debug : Messages récents"
#: ../../inc/mod/pages.php:1956
msgid "Debug: SQL"
msgstr "Debug : SQL"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:19
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:29
msgid "Boards"
msgstr "Planches"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:57
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:183
msgid "edit"
msgstr "Éditer"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:74
msgid "Create new board"
msgstr "Créer une nouvelle planche"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:84
msgid "Messages"
msgstr "Messages"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:120
#: ../../templates/cache/26/6f/05ca0da8ac09e2c2216cba2b6f95.php:98
#: ../../templates/cache/c8/8b/242bf87b3b6a29a67cdd09a3afeb.php:125
msgid "no subject"
msgstr "Pas de sujet"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:161
msgid "View all noticeboard entries"
msgstr "Voir toutes les notices"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:192
msgid "Administration"
msgstr "Administration"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:239
msgid "Change password"
msgstr "Changer son mot de passe"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:271
msgid "Configuration"
msgstr "Configuration"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:282
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:293
msgid "Search"
msgstr "Rechercher"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:289
msgid "Phrase:"
msgstr "Phrase :"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:297
msgid ""
"(Search is case-insensitive, and based on keywords. To match exact phrases, "
"use \"quotes\". Use an asterisk (*) for wildcard.)"
msgstr ""
"(Cette recherche n'a pas de sensibilité à la casse et est basé sur des mots-"
"clefs. Utilisez les \"guillemets\" pour rechercher des phrases exactes. "
"Utilisez un astérisque (*) en guise de méta-caractère.)"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:309
msgid "Debug"
msgstr "Debug"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:313
msgid "Anti-spam"
msgstr "Anti-spam"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:316
msgid "Recent posts"
msgstr "Messages récents"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:322
msgid "SQL"
msgstr "SQL"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:360
msgid "User account"
msgstr "Compte de l'utilisateur"
#: ../../templates/cache/3a/df/ab38a77244cb9c729b4c6f99759a.php:365
msgid "Logout"
msgstr "Déconnexion"
#: ../../templates/cache/26/6f/05ca0da8ac09e2c2216cba2b6f95.php:21
#: ../../templates/cache/c8/8b/242bf87b3b6a29a67cdd09a3afeb.php:21
msgid "New post"
msgstr "Nouveau message"
#: ../../templates/cache/26/6f/05ca0da8ac09e2c2216cba2b6f95.php:27
#: ../../templates/cache/c8/8b/242bf87b3b6a29a67cdd09a3afeb.php:31
#: ../../templates/cache/c8/8b/242bf87b3b6a29a67cdd09a3afeb.php:36
#: ../../templates/cache/39/42/cbc36382096edfa72a8bc26e4514.php:27
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:55
msgid "Name"
msgstr "Nom"
#: ../../templates/cache/26/6f/05ca0da8ac09e2c2216cba2b6f95.php:36
#: ../../templates/cache/c8/8b/242bf87b3b6a29a67cdd09a3afeb.php:63
#: ../../templates/cache/39/42/cbc36382096edfa72a8bc26e4514.php:53
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:98
msgid "Subject"
msgstr "Sujet"
#: ../../templates/cache/26/6f/05ca0da8ac09e2c2216cba2b6f95.php:42
#: ../../templates/cache/c8/8b/242bf87b3b6a29a67cdd09a3afeb.php:69
msgid "Body"
msgstr "Message"
#: ../../templates/cache/26/6f/05ca0da8ac09e2c2216cba2b6f95.php:49
msgid "Post to noticeboard"
msgstr "Poster dans les notifications"
#: ../../templates/cache/26/6f/05ca0da8ac09e2c2216cba2b6f95.php:73
#: ../../templates/cache/c8/8b/242bf87b3b6a29a67cdd09a3afeb.php:100
msgid "delete"
msgstr "Suppression"
#: ../../templates/cache/26/6f/05ca0da8ac09e2c2216cba2b6f95.php:106
#: ../../templates/cache/c8/8b/242bf87b3b6a29a67cdd09a3afeb.php:133
msgid "by"
msgstr "par"
#: ../../templates/cache/26/6f/05ca0da8ac09e2c2216cba2b6f95.php:118
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:112
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:344
msgid "deleted?"
msgstr "supprimé ?"
#: ../../templates/cache/26/6f/05ca0da8ac09e2c2216cba2b6f95.php:125
#: ../../templates/cache/c8/8b/242bf87b3b6a29a67cdd09a3afeb.php:136
msgid "at"
msgstr "à"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:74
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:169
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:331
msgid "Staff"
msgstr "Staff"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:77
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:179
msgid "Note"
msgstr "Note"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:80
msgid "Date"
msgstr "Date"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:86
msgid "Actions"
msgstr "Actions"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:142
msgid "remove"
msgstr "retirer"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:189
msgid "New note"
msgstr "Nouvelle note"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:226
msgid "Status"
msgstr "Statut"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:233
msgid "Expired"
msgstr "Expiré"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:238
msgid "Active"
msgstr "Actif"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:256
#: ../../templates/cache/82/40/4c4a4b82f787181e6500ce83494d.php:32
#: ../../templates/cache/9c/7b/891291bc84f8844c30cefdb949cf.php:30
#: ../../templates/cache/18/9c/c365d711719f494c684aab98a4ae.php:90
msgid "Reason"
msgstr "Raison"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:269
msgid "no reason"
msgstr "Pas de justification"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:278
#: ../../templates/cache/9c/7b/891291bc84f8844c30cefdb949cf.php:20
#: ../../templates/cache/18/9c/c365d711719f494c684aab98a4ae.php:142
msgid "Board"
msgstr "Planche"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:291
#: ../../templates/cache/18/9c/c365d711719f494c684aab98a4ae.php:150
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:83
msgid "all boards"
msgstr "Toutes les planches"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:300
msgid "Set"
msgstr "Configurer"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:309
msgid "Expires"
msgstr "Expire le"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:322
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:137
msgid "never"
msgstr "jamais"
#: ../../templates/cache/24/a0/f1ddafed7a8f9625e747a5ca33f5.php:357
msgid "Remove ban"
msgstr "Débannir"
#: ../../templates/cache/72/55/0d64283f30702de83ecfcb71f86a.php:25
msgid "There are no reports."
msgstr "Il n'y a pas de reports."
#: ../../templates/cache/82/40/4c4a4b82f787181e6500ce83494d.php:19
msgid "Delete Post"
msgstr "Supprimer message"
#: ../../templates/cache/82/40/4c4a4b82f787181e6500ce83494d.php:22
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:218
msgid "File"
msgstr "Fichier"
#: ../../templates/cache/82/40/4c4a4b82f787181e6500ce83494d.php:23
#: ../../templates/cache/04/54/656aa217f895c90eae78024fa060.php:41
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:310
msgid "Password"
msgstr "Mot de passe"
#: ../../templates/cache/82/40/4c4a4b82f787181e6500ce83494d.php:27
msgid "Delete"
msgstr "Supprimer"
#: ../../templates/cache/82/40/4c4a4b82f787181e6500ce83494d.php:36
msgid "Report"
msgstr "Reporter"
#: ../../templates/cache/04/54/656aa217f895c90eae78024fa060.php:28
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:23
msgid "Username"
msgstr "Identifiant"
#: ../../templates/cache/04/54/656aa217f895c90eae78024fa060.php:52
msgid "Continue"
msgstr "Continuer"
#: ../../templates/cache/f5/e3/343716327c6183713f70a3fb57f1.php:94
#: ../../templates/cache/aa/f6/f10fd83961bcd8c947af6ddf919d.php:175
#: ../../templates/cache/62/8c/21348d46377c3e1b3f8c476ba376.php:63
msgid "Return to dashboard"
msgstr "Retourner au panneau de configuration"
#: ../../templates/cache/9c/7b/891291bc84f8844c30cefdb949cf.php:36
msgid "Report date"
msgstr "Date du report"
#: ../../templates/cache/9c/7b/891291bc84f8844c30cefdb949cf.php:45
msgid "Reported by"
msgstr "Reporté par"
#: ../../templates/cache/9c/7b/891291bc84f8844c30cefdb949cf.php:63
msgid "Discard abuse report"
msgstr "Ignorer ce report"
#: ../../templates/cache/9c/7b/891291bc84f8844c30cefdb949cf.php:80
msgid "Discard all abuse reports by this IP address"
msgstr "Ignorer tous les reports de cette addresse IP"
#: ../../templates/cache/aa/f6/f10fd83961bcd8c947af6ddf919d.php:183
msgid "Posting mode: Reply"
msgstr "Mode de messagerie : Réponse"
#: ../../templates/cache/aa/f6/f10fd83961bcd8c947af6ddf919d.php:186
#: ../../templates/cache/aa/f6/f10fd83961bcd8c947af6ddf919d.php:232
msgid "Return"
msgstr "Retour"
#: ../../templates/cache/c8/8b/242bf87b3b6a29a67cdd09a3afeb.php:76
msgid "Post news entry"
msgstr "Poster une nouvelle"
#: ../../templates/cache/18/9c/c365d711719f494c684aab98a4ae.php:66
msgid "(or subnet)"
msgstr "(ou subnet)"
#: ../../templates/cache/18/9c/c365d711719f494c684aab98a4ae.php:80
msgid "hidden"
msgstr "caché"
#: ../../templates/cache/18/9c/c365d711719f494c684aab98a4ae.php:107
msgid "Message"
msgstr "Message"
#: ../../templates/cache/18/9c/c365d711719f494c684aab98a4ae.php:117
msgid "public; attached to post"
msgstr "Public ; attaché à ce message"
#: ../../templates/cache/18/9c/c365d711719f494c684aab98a4ae.php:133
msgid "Length"
msgstr "Longueur"
#: ../../templates/cache/18/9c/c365d711719f494c684aab98a4ae.php:192
msgid "New Ban"
msgstr "Nouveau ban"
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:20
msgid "ID"
msgstr "ID"
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:26
msgid "Type"
msgstr "Type"
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:35
msgid "Last action"
msgstr "Dernière action"
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:61
msgid "Janitor"
msgstr "Concièrge"
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:64
msgid "Mod"
msgstr "Modo"
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:67
msgid "Admin"
msgstr "Admin"
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:78
msgid "none"
msgstr "aucun"
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:153
msgid "Promote"
msgstr "Promouvoir"
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:163
msgid "Demote"
msgstr "Rétrograder"
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:173
msgid "log"
msgstr "registre"
#: ../../templates/cache/c5/a7/fac83da087ee6e24edaf09e01122.php:193
msgid "PM"
msgstr "MP"
#: ../../templates/cache/d8/f2/7780eb1adcdbda7e332659e3fb4f.php:105
msgid "File:"
msgstr "Fichier :"
#: ../../templates/cache/d8/f2/7780eb1adcdbda7e332659e3fb4f.php:117
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:129
msgid "Spoiler Image"
msgstr "Image sous Spoiler"
#: ../../templates/cache/d8/f2/7780eb1adcdbda7e332659e3fb4f.php:463
msgid "Reply"
msgstr "Réponse"
#: ../../templates/cache/d8/f2/7780eb1adcdbda7e332659e3fb4f.php:490
msgid "1 post"
msgid_plural "%count% posts"
msgstr[0] "1 message"
msgstr[1] "%count% messages"
#: ../../templates/cache/d8/f2/7780eb1adcdbda7e332659e3fb4f.php:496
msgid "and"
msgstr "et"
#: ../../templates/cache/d8/f2/7780eb1adcdbda7e332659e3fb4f.php:507
msgid "1 image reply"
msgid_plural "%count% image replies"
msgstr[0] "1 image en réponse"
msgstr[1] "%count% images en réponse"
#: ../../templates/cache/d8/f2/7780eb1adcdbda7e332659e3fb4f.php:512
msgid "omitted. Click reply to view."
msgstr "cachés. Cliquez sur Répondre pour visualiser."
#: ../../templates/cache/39/42/cbc36382096edfa72a8bc26e4514.php:40
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:76
msgid "Email"
msgstr "E-mail"
#: ../../templates/cache/39/42/cbc36382096edfa72a8bc26e4514.php:62
msgid "Update"
msgstr "Actualiser"
#: ../../templates/cache/39/42/cbc36382096edfa72a8bc26e4514.php:69
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:138
msgid "Comment"
msgstr "Commentaire"
#: ../../templates/cache/39/42/cbc36382096edfa72a8bc26e4514.php:89
#, fuzzy
msgid "Currently editing raw HTML."
msgstr "Actuellement en train d'éditer l'HTML brut."
#: ../../templates/cache/39/42/cbc36382096edfa72a8bc26e4514.php:96
#, fuzzy
msgid "Edit markup instead?"
msgstr "Éditer l'annotation à la place ?"
#: ../../templates/cache/39/42/cbc36382096edfa72a8bc26e4514.php:105
#, fuzzy
msgid "Edit raw HTML instead?"
msgstr "Éditer l'HTML brut à la place ?"
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:111
msgid "Submit"
msgstr "Envoyer"
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:159
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:185
msgid "Verification"
msgstr "Vérification"
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:236
msgid "Embed"
msgstr "Insérer"
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:259
#, fuzzy
msgid "Flags"
msgstr "Drapeaux"
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:268
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:271
msgid "Sticky"
msgstr "Épinglé"
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:280
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:283
msgid "Lock"
msgstr "Verrouiller"
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:292
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:295
msgid "Raw HTML"
msgstr "HTML Brut"
#: ../../templates/cache/0c/37/9331df01df7c2986d77a02d3beb0.php:319
msgid "(For file deletion.)"
msgstr "(Pour supprimer le fichier)"

View File

@ -0,0 +1,391 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-20 20:19+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../../../../js/expand.js:20 ../../../../js/expand.js:22
msgid "Click reply to view."
msgstr ""
#: ../../../../js/expand.js:20 ../../../../js/expand.js:22
msgid "Click to expand"
msgstr ""
#: ../../../../js/quick-reply.js:30 ../../../../js/quick-reply.js:31
#: ../../../../js/quick-reply-old.js:31 ../../../../js/quick-reply-old.js:33
msgid "Quick reply"
msgstr ""
#: ../../../../js/quick-reply.js:32 ../../../../js/quick-reply.js:33
#: ../../../../js/quick-reply-old.js:33 ../../../../js/quick-reply-old.js:35
#, python-brace-format
msgid "Posting mode: Replying to <small>&gt;&gt;{0}</small>"
msgstr ""
#: ../../../../js/quick-reply.js:32 ../../../../js/quick-reply.js:33
#: ../../../../js/quick-reply-old.js:33 ../../../../js/quick-reply-old.js:35
msgid "Return"
msgstr ""
#: ../../../../js/quick-reply.js:20 ../../../../js/quick-reply.js:21
#: ../../../../js/quick-reply-old.js:21 ../../../../js/quick-reply-old.js:23
msgid "Submit"
msgstr ""
#: ../../../../js/toggle-locked-threads.js:39
#: ../../../../js/toggle-locked-threads.js:54
#: ../../../../js/toggle-locked-threads.js:40
#: ../../../../js/toggle-locked-threads.js:55
#: ../../../../js/toggle-locked-threads.js:41
#: ../../../../js/toggle-locked-threads.js:56
msgid "Show locked threads"
msgstr ""
#: ../../../../js/toggle-locked-threads.js:39
#: ../../../../js/toggle-locked-threads.js:54
#: ../../../../js/toggle-locked-threads.js:40
#: ../../../../js/toggle-locked-threads.js:55
#: ../../../../js/toggle-locked-threads.js:41
#: ../../../../js/toggle-locked-threads.js:56
msgid "Hide locked threads"
msgstr ""
#: ../../../../js/quick-post-controls.js:27
#: ../../../../js/quick-post-controls.js:29
msgid "Password"
msgstr ""
#: ../../../../js/quick-post-controls.js:29
#: ../../../../js/quick-post-controls.js:31
msgid "Delete file only"
msgstr ""
#: ../../../../js/quick-post-controls.js:30 ../../../../js/hide-images.js:50
#: ../../../../js/upload-selection.js:51 ../../../../js/hide-images.js:51
#: ../../../../js/quick-post-controls.js:32
#: ../../../../js/upload-selection.js:61
msgid "File"
msgstr ""
#: ../../../../js/quick-post-controls.js:31
#: ../../../../js/quick-post-controls.js:33
msgid "Delete"
msgstr ""
#: ../../../../js/quick-post-controls.js:35
#: ../../../../js/quick-post-controls.js:37
msgid "Reason"
msgstr ""
#: ../../../../js/quick-post-controls.js:37
#: ../../../../js/quick-post-controls.js:39
msgid "Report"
msgstr ""
#: ../../../../js/expand.js:41 ../../../../js/expand.js:43
#: ../../../../js/expand.js:44 ../../../../js/expand.js:46
msgid "Hide expanded replies"
msgstr ""
#: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:65
#: ../../../../js/forced-anon.js:69 ../../../../js/forced-anon.js:60
#: ../../../../js/forced-anon.js:66 ../../../../js/forced-anon.js:70
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:67
#: ../../../../js/forced-anon.js:71
msgid "Forced anonymity"
msgstr ""
#: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:65
#: ../../../../js/forced-anon.js:60 ../../../../js/forced-anon.js:66
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:67
msgid "enabled"
msgstr ""
#: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:69
#: ../../../../js/forced-anon.js:60 ../../../../js/forced-anon.js:70
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:71
msgid "disabled"
msgstr ""
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
msgid "Sun"
msgstr ""
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
msgid "Mon"
msgstr ""
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
msgid "Tue"
msgstr ""
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
msgid "Wed"
msgstr ""
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
msgid "Thu"
msgstr ""
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
msgid "Fri"
msgstr ""
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
msgid "Sat"
msgstr ""
#: ../../../../js/style-select.js:40 ../../../../js/style-select.js:41
msgid "Style: "
msgstr ""
#: ../../../../js/hide-images.js:50 ../../../../js/hide-images.js:51
msgid "hide"
msgstr ""
#: ../../../../js/hide-images.js:56 ../../../../js/hide-images.js:57
msgid "show"
msgstr ""
#: ../../../../js/toggle-images.js:41 ../../../../js/toggle-images.js:42
msgid "hidden"
msgstr ""
#: ../../../../js/toggle-images.js:57 ../../../../js/toggle-images.js:70
#: ../../../../js/toggle-images.js:58 ../../../../js/toggle-images.js:71
msgid "Show images"
msgstr ""
#: ../../../../js/toggle-images.js:57 ../../../../js/toggle-images.js:70
#: ../../../../js/toggle-images.js:58 ../../../../js/toggle-images.js:71
msgid "Hide images"
msgstr ""
#: ../../../../templates/main.js:6
msgid "Hello!"
msgstr ""
#: ../../../../templates/main.js:18
#, python-brace-format
msgid "{0} users"
msgstr ""
#: ../../../../templates/themes/ukko/ukko.js:28
#: ../../../../templates/themes/ukko/ukko.js:39
#: ../../../../templates/themes/ukko/ukko.js:29
#: ../../../../templates/themes/ukko/ukko.js:40
msgid "(hide threads from this board)"
msgstr ""
#: ../../../../templates/themes/ukko/ukko.js:32
#: ../../../../templates/themes/ukko/ukko.js:44
#: ../../../../templates/themes/ukko/ukko.js:33
#: ../../../../templates/themes/ukko/ukko.js:45
msgid "(show threads from this board)"
msgstr ""
#: ../../../../templates/themes/ukko/ukko.js:57
#: ../../../../templates/themes/ukko/ukko.js:58
msgid "No more threads to display"
msgstr ""
#: ../../../../templates/themes/ukko/ukko.js:79
#: ../../../../templates/themes/ukko/ukko.js:80
msgid "Loading..."
msgstr ""
#: ../../../../js/upload-selection.js:32 ../../../../js/upload-selection.js:45
msgid "URL"
msgstr ""
#: ../../../../js/upload-selection.js:50 ../../../../js/upload-selection.js:60
msgid "Select"
msgstr ""
#: ../../../../js/upload-selection.js:53 ../../../../js/upload-selection.js:63
msgid "Remote"
msgstr ""
#: ../../../../js/upload-selection.js:56 ../../../../js/upload-selection.js:66
msgid "Embed"
msgstr ""
#: ../../../../js/upload-selection.js:59 ../../../../js/upload-selection.js:69
msgid "Oekaki"
msgstr ""
#: ../../../../js/oekaki.js:10
msgid "Brush size"
msgstr ""
#: ../../../../js/oekaki.js:10
msgid "Set text"
msgstr ""
#: ../../../../js/oekaki.js:10
msgid "Clear"
msgstr ""
#: ../../../../js/oekaki.js:10
msgid "Save"
msgstr ""
#: ../../../../js/oekaki.js:10
msgid "Load"
msgstr ""
#: ../../../../js/oekaki.js:11
msgid "Toggle eraser"
msgstr ""
#: ../../../../js/oekaki.js:11
msgid "Get color"
msgstr ""
#: ../../../../js/oekaki.js:11
msgid "Fill"
msgstr ""
#: ../../../../js/oekaki.js:12
msgid "Use oekaki instead of file?"
msgstr ""
#: ../../../../js/oekaki.js:21
msgid "Edit in oekaki"
msgstr ""
#: ../../../../js/oekaki.js:152
msgid "Enter some text"
msgstr ""
#: ../../../../js/oekaki.js:153
msgid "Enter font or leave empty"
msgstr ""
#: ../../../../js/catalog-link.js:21 ../../../../js/catalog-link.js:32
#: ../../../../js/catalog-link.js:40 ../../../../js/catalog-link.js:33
#: ../../../../js/catalog-link.js:44 ../../../../js/catalog-link.js:52
msgid "Catalog"
msgstr ""
#: ../../../../js/expand-all-images.js:20
#: ../../../../js/expand-all-images.js:21
#: ../../../../js/expand-all-images.js:22
msgid "Expand all images"
msgstr ""
#: ../../../../js/download-original.js:32
#: ../../../../js/download-original.js:33
msgid "Save as original filename"
msgstr ""
#: ../../../../js/ajax-post-controls.js:43
msgid "Reported post(s)."
msgstr ""
#: ../../../../js/ajax-post-controls.js:53
msgid "An unknown error occured!"
msgstr ""
#: ../../../../js/ajax-post-controls.js:60
msgid "Something went wrong... An unknown error occured!"
msgstr ""
#: ../../../../js/ajax-post-controls.js:68
msgid "Working..."
msgstr ""
#: ../../../../js/ajax.js:42 ../../../../js/ajax.js:45
msgid "Posting... (#%)"
msgstr ""
#: ../../../../js/ajax.js:104 ../../../../js/ajax.js:109
msgid "Posted..."
msgstr ""
#: ../../../../js/ajax.js:106 ../../../../js/ajax.js:111
msgid "An unknown error occured when posting!"
msgstr ""
#: ../../../../js/ajax.js:130 ../../../../js/ajax.js:135
msgid "Posting..."
msgstr ""
#: ../../../../js/quick-reply.js:223 ../../../../js/quick-reply.js:224
msgid "Upload URL"
msgstr ""
#: ../../../../js/quick-reply.js:266 ../../../../js/quick-reply.js:267
msgid "Spoiler Image"
msgstr ""
#: ../../../../js/quick-reply.js:277 ../../../../js/quick-reply.js:278
msgid "Comment"
msgstr ""
#: ../../../../js/quick-reply.js:285 ../../../../js/quick-reply.js:406
#: ../../../../js/quick-reply.js:286 ../../../../js/quick-reply.js:407
msgid "Quick Reply"
msgstr ""
#: ../../../../js/watch.js:249 ../../../../js/watch.js:250
#: ../../../../js/watch.js:288 ../../../../js/watch.js:289
#: ../../../../js/watch.js:330 ../../../../js/watch.js:331
msgid "Stop watching this thread"
msgstr ""
#: ../../../../js/watch.js:249 ../../../../js/watch.js:250
#: ../../../../js/watch.js:288 ../../../../js/watch.js:289
#: ../../../../js/watch.js:330 ../../../../js/watch.js:331
msgid "Watch this thread"
msgstr ""
#: ../../../../js/watch.js:260 ../../../../js/watch.js:261
#: ../../../../js/watch.js:269 ../../../../js/watch.js:299
#: ../../../../js/watch.js:300 ../../../../js/watch.js:308
#: ../../../../js/watch.js:341 ../../../../js/watch.js:342
#: ../../../../js/watch.js:350
msgid "Unpin this board"
msgstr ""
#: ../../../../js/watch.js:260 ../../../../js/watch.js:261
#: ../../../../js/watch.js:269 ../../../../js/watch.js:299
#: ../../../../js/watch.js:300 ../../../../js/watch.js:308
#: ../../../../js/watch.js:341 ../../../../js/watch.js:342
#: ../../../../js/watch.js:350
msgid "Pin this board"
msgstr ""
#: ../../../../js/watch.js:262 ../../../../js/watch.js:267
#: ../../../../js/watch.js:268 ../../../../js/watch.js:301
#: ../../../../js/watch.js:306 ../../../../js/watch.js:307
#: ../../../../js/watch.js:343 ../../../../js/watch.js:348
#: ../../../../js/watch.js:349
msgid "Stop watching this board"
msgstr ""
#: ../../../../js/watch.js:262 ../../../../js/watch.js:267
#: ../../../../js/watch.js:268 ../../../../js/watch.js:301
#: ../../../../js/watch.js:306 ../../../../js/watch.js:307
#: ../../../../js/watch.js:343 ../../../../js/watch.js:348
#: ../../../../js/watch.js:349
msgid "Watch this board"
msgstr ""
#: ../../../../js/wpaint.js:113
msgid "Click on any image on this site to load it into oekaki applet"
msgstr ""

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
l10n = {"Submit":"Wy\u015blij","Quick reply":"Szybka odpowied\u017a","Posting mode: Replying to <small>&gt;&gt;{0}<\/small>":"Tryb postowania: Odpowied\u017a na <small>&gt;&gt;{0}<\/small>","Return":"Powr\u00f3t","Click reply to view.":"Kliknij Odpowied\u017a aby zobaczy\u0107.","Click to expand":"Kliknij aby rozwin\u0105\u0107","Hide expanded replies":"Schowaj rozwini\u0119te odpowiedzi","Mon":"pon","Tue":"wto","Wed":"\u015bro","Thu":"czw","Fri":"pi\u0105","Sat":"sob","Sun":"nie","Show locked threads":"Poka\u017c zablokowane tematy","Hide locked threads":"Schowaj zablokowane tematy","Forced anonymity":"Wymuszona anonimowo\u015b\u0107","enabled":"w\u0142\u0105czona","disabled":"wy\u0142\u0105czona","Password":"Has\u0142o","Delete file only":"Usu\u0144 tylko plik","File":"Plik","Delete":"Usu\u0144","Reason":"Pow\u00f3d","Report":"Zg\u0142oszenie","hide":"ukryj","show":"poka\u017c","hidden":"ukryte","Show images":"Poka\u017c obrazki","Hide images":"Ukryj obrazki","Style: ":"Styl: ","Hello!":"Witaj!","{0} users":"{0} u\u017cytkownik\u00f3w","(hide threads from this board)":"(schowaj w\u0105tki z tego boardu)","(show threads from this board)":"(poka\u017c w\u0105tki z tego boardu)","No more threads to display":"Nie ma wi\u0119cej w\u0105tk\u00f3w do wy\u015bwietlenia","Loading...":"\u0141adowanie...","URL":"URL","Select":"Wybierz","Remote":"Zdalny","Embed":"Osad\u017a","Oekaki":"Oekaki","Brush size":"Rozmiar p\u0119dzla","Set text":"Ustaw tekst","Clear":"Wyczy\u015b\u0107","Save":"Zapisz","Load":"Za\u0142aduj","Toggle eraser":"Prze\u0142\u0105cz gumk\u0119","Get color":"Wybierz kolor","Fill":"Wype\u0142nij","Use oekaki instead of file?":"U\u017cy\u0107 oekaki zamiast pliku?","Edit in oekaki":"Edytuj w oekaki","Enter some text":"Podaj jaki\u015b tekst","Enter font or leave empty":"Podaj czcionk\u0119, b\u0105d\u017a pozostaw puste","Catalog":"Katalog","Expand all images":"Rozwi\u0144 wszystkie obrazki","Save as original filename":"Zapisz z oryginaln\u0105 nazw\u0105 pliku","Reported post(s).":"Zaraportowano post(y).","An unknown error occured!":"Wyst\u0105pi\u0142 nieznany b\u0142\u0105d!","Something went wrong... An unknown error occured!":"Co\u015b posz\u0142o \u017ale... wyst\u0105pi\u0142 nieznany b\u0142\u0105d!","Working...":"Przetwarzanie...","Posting... (#%)":"Postowanie... (#%)","Posted...":"Zapostowano...","An unknown error occured when posting!":"Wyst\u0105pi\u0142 nieznany b\u0142\u0105d podczas postowania!","Posting...":"Postowanie...","Upload URL":"Wy\u015blij URL","Spoiler Image":"Schowaj obrazek","Comment":"Komentarz","Quick Reply":"Szybka odpowied\u017a","Stop watching this thread":"Przesta\u0144 obserwowa\u0107 ten w\u0105tek","Watch this thread":"Obserwuj ten w\u0105tek","Unpin this board":"Odepnij ten board","Pin this board":"Przypnij ten board","Stop watching this board":"Przesta\u0144 oberwowa\u0107 ten board","Watch this board":"Obserwuj ten board"}; l10n = {"Submit":"Wy\u015blij","Quick reply":"Szybka odpowied\u017a","Posting mode: Replying to <small>&gt;&gt;{0}<\/small>":"Tryb postowania: Odpowied\u017a na <small>&gt;&gt;{0}<\/small>","Return":"Powr\u00f3t","Click reply to view.":"Kliknij Odpowied\u017a aby zobaczy\u0107.","Click to expand":"Kliknij aby rozwin\u0105\u0107","Hide expanded replies":"Schowaj rozwini\u0119te odpowiedzi","Mon":"pon","Tue":"wto","Wed":"\u015bro","Thu":"czw","Fri":"pi\u0105","Sat":"sob","Sun":"nie","Show locked threads":"Poka\u017c zablokowane tematy","Hide locked threads":"Schowaj zablokowane tematy","Forced anonymity":"Wymuszona anonimowo\u015b\u0107","enabled":"w\u0142\u0105czona","disabled":"wy\u0142\u0105czona","Password":"Has\u0142o","Delete file only":"Usu\u0144 tylko plik","File":"Plik","Delete":"Usu\u0144","Reason":"Pow\u00f3d","Report":"Zg\u0142oszenie","hide":"ukryj","show":"poka\u017c","hidden":"ukryte","Show images":"Poka\u017c obrazki","Hide images":"Ukryj obrazki","Style: ":"Styl: ","Hello!":"Witaj!","{0} users":"{0} u\u017cytkownik\u00f3w","(hide threads from this board)":"(schowaj w\u0105tki z tego boardu)","(show threads from this board)":"(poka\u017c w\u0105tki z tego boardu)","No more threads to display":"Nie ma wi\u0119cej w\u0105tk\u00f3w do wy\u015bwietlenia","Loading...":"\u0141adowanie...","URL":"URL","Select":"Wybierz","Remote":"Zdalny","Embed":"Osad\u017a","Oekaki":"Oekaki","Brush size":"Rozmiar p\u0119dzla","Set text":"Ustaw tekst","Clear":"Wyczy\u015b\u0107","Save":"Zapisz","Load":"Za\u0142aduj","Toggle eraser":"Prze\u0142\u0105cz gumk\u0119","Get color":"Wybierz kolor","Fill":"Wype\u0142nij","Use oekaki instead of file?":"U\u017cy\u0107 oekaki zamiast pliku?","Edit in oekaki":"Edytuj w oekaki","Enter some text":"Podaj jaki\u015b tekst","Enter font or leave empty":"Podaj czcionk\u0119, b\u0105d\u017a pozostaw puste","Catalog":"Katalog","Expand all images":"Rozwi\u0144 wszystkie obrazki","Save as original filename":"Zapisz z oryginaln\u0105 nazw\u0105 pliku","Reported post(s).":"Zaraportowano post(y).","An unknown error occured!":"Wyst\u0105pi\u0142 nieznany b\u0142\u0105d!","Something went wrong... An unknown error occured!":"Co\u015b posz\u0142o \u017ale... wyst\u0105pi\u0142 nieznany b\u0142\u0105d!","Working...":"Przetwarzanie...","Posting... (#%)":"Postowanie... (#%)","Posted...":"Zapostowano...","An unknown error occured when posting!":"Wyst\u0105pi\u0142 nieznany b\u0142\u0105d podczas postowania!","Posting...":"Postowanie...","Upload URL":"Wy\u015blij URL","Spoiler Image":"Schowaj obrazek","Comment":"Komentarz","Quick Reply":"Szybka odpowied\u017a","Stop watching this thread":"Przesta\u0144 obserwowa\u0107 ten w\u0105tek","Watch this thread":"Obserwuj ten w\u0105tek","Unpin this board":"Odepnij ten board","Pin this board":"Przypnij ten board","Stop watching this board":"Przesta\u0144 oberwowa\u0107 ten board","Watch this board":"Obserwuj ten board","Sunday":"Niedziela","Monday":"Poniedzia\u0142ek","Tuesday":"Wtorek","Wednesday":"\u015aroda","Thursday":"Czwartek","Friday":"Pi\u0105tek","Saturday":"Sobota","January":"stycznia","February":"lutego","March":"marca","April":"kwietnia","May":"maj","June":"czerwca","July":"lipca","August":"sierpnia","September":"wrze\u015bnia","October":"pa\u017adziernika","November":"listopada","December":"grudnia","Jan":"sty","Feb":"lut","Mar":"mar","Apr":"kwi","Jun":"cze","Jul":"lip","Aug":"sie","Sep":"wrz","Oct":"pa\u017a","Nov":"lis","Dec":"gru","AM":"AM","PM":"PM","am":"am","pm":"pm"};

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-12-29 01:35+0100\n" "POT-Creation-Date: 2014-02-23 19:40+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -18,64 +18,72 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: ../../../../js/quick-reply.js:20 ../../../../js/quick-reply.js:21 #: ../../../../js/quick-reply.js:20 ../../../../js/quick-reply.js:21
#: ../../../../js/quick-reply-old.js:21 #: ../../../../js/quick-reply-old.js:21 ../../../../js/quick-reply-old.js:23
msgid "Submit" msgid "Submit"
msgstr "Wyślij" msgstr "Wyślij"
#: ../../../../js/quick-reply.js:30 ../../../../js/quick-reply.js:31 #: ../../../../js/quick-reply.js:30 ../../../../js/quick-reply.js:31
#: ../../../../js/quick-reply-old.js:31 #: ../../../../js/quick-reply-old.js:31 ../../../../js/quick-reply-old.js:33
msgid "Quick reply" msgid "Quick reply"
msgstr "Szybka odpowiedź" msgstr "Szybka odpowiedź"
#: ../../../../js/quick-reply.js:32 ../../../../js/quick-reply.js:33 #: ../../../../js/quick-reply.js:32 ../../../../js/quick-reply.js:33
#: ../../../../js/quick-reply-old.js:33 #: ../../../../js/quick-reply-old.js:33 ../../../../js/quick-reply-old.js:35
#, python-brace-format #, python-brace-format
msgid "Posting mode: Replying to <small>&gt;&gt;{0}</small>" msgid "Posting mode: Replying to <small>&gt;&gt;{0}</small>"
msgstr "Tryb postowania: Odpowiedź na <small>&gt;&gt;{0}</small>" msgstr "Tryb postowania: Odpowiedź na <small>&gt;&gt;{0}</small>"
#: ../../../../js/quick-reply.js:32 ../../../../js/quick-reply.js:33 #: ../../../../js/quick-reply.js:32 ../../../../js/quick-reply.js:33
#: ../../../../js/quick-reply-old.js:33 #: ../../../../js/quick-reply-old.js:33 ../../../../js/quick-reply-old.js:35
msgid "Return" msgid "Return"
msgstr "Powrót" msgstr "Powrót"
#: ../../../../js/expand.js:20 #: ../../../../js/expand.js:20 ../../../../js/expand.js:22
msgid "Click reply to view." msgid "Click reply to view."
msgstr "Kliknij Odpowiedź aby zobaczyć." msgstr "Kliknij Odpowiedź aby zobaczyć."
#: ../../../../js/expand.js:20 #: ../../../../js/expand.js:20 ../../../../js/expand.js:22
msgid "Click to expand" msgid "Click to expand"
msgstr "Kliknij aby rozwinąć" msgstr "Kliknij aby rozwinąć"
#: ../../../../js/expand.js:41 ../../../../js/expand.js:45 #: ../../../../js/expand.js:41 ../../../../js/expand.js:45
#: ../../../../js/expand.js:43 ../../../../js/expand.js:44 #: ../../../../js/expand.js:43 ../../../../js/expand.js:44
#: ../../../../js/expand.js:46
msgid "Hide expanded replies" msgid "Hide expanded replies"
msgstr "Schowaj rozwinięte odpowiedzi" msgstr "Schowaj rozwinięte odpowiedzi"
#: ../../../../js/local-time.js:40 #: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
#: ../../../../js/local-time.js:30
msgid "Mon" msgid "Mon"
msgstr "pon" msgstr "pon"
#: ../../../../js/local-time.js:40 #: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
#: ../../../../js/local-time.js:30
msgid "Tue" msgid "Tue"
msgstr "wto" msgstr "wto"
#: ../../../../js/local-time.js:40 #: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
#: ../../../../js/local-time.js:30
msgid "Wed" msgid "Wed"
msgstr "śro" msgstr "śro"
#: ../../../../js/local-time.js:40 #: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
#: ../../../../js/local-time.js:30
msgid "Thu" msgid "Thu"
msgstr "czw" msgstr "czw"
#: ../../../../js/local-time.js:40 #: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
#: ../../../../js/local-time.js:30
msgid "Fri" msgid "Fri"
msgstr "pią" msgstr "pią"
#: ../../../../js/local-time.js:40 #: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
#: ../../../../js/local-time.js:30
msgid "Sat" msgid "Sat"
msgstr "sob" msgstr "sob"
#: ../../../../js/local-time.js:40 #: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
#: ../../../../js/local-time.js:30
msgid "Sun" msgid "Sun"
msgstr "nie" msgstr "nie"
@ -83,6 +91,8 @@ msgstr "nie"
#: ../../../../js/toggle-locked-threads.js:54 #: ../../../../js/toggle-locked-threads.js:54
#: ../../../../js/toggle-locked-threads.js:40 #: ../../../../js/toggle-locked-threads.js:40
#: ../../../../js/toggle-locked-threads.js:55 #: ../../../../js/toggle-locked-threads.js:55
#: ../../../../js/toggle-locked-threads.js:41
#: ../../../../js/toggle-locked-threads.js:56
msgid "Show locked threads" msgid "Show locked threads"
msgstr "Pokaż zablokowane tematy" msgstr "Pokaż zablokowane tematy"
@ -90,71 +100,86 @@ msgstr "Pokaż zablokowane tematy"
#: ../../../../js/toggle-locked-threads.js:54 #: ../../../../js/toggle-locked-threads.js:54
#: ../../../../js/toggle-locked-threads.js:40 #: ../../../../js/toggle-locked-threads.js:40
#: ../../../../js/toggle-locked-threads.js:55 #: ../../../../js/toggle-locked-threads.js:55
#: ../../../../js/toggle-locked-threads.js:41
#: ../../../../js/toggle-locked-threads.js:56
msgid "Hide locked threads" msgid "Hide locked threads"
msgstr "Schowaj zablokowane tematy" msgstr "Schowaj zablokowane tematy"
#: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:65 #: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:65
#: ../../../../js/forced-anon.js:69 ../../../../js/forced-anon.js:60 #: ../../../../js/forced-anon.js:69 ../../../../js/forced-anon.js:60
#: ../../../../js/forced-anon.js:66 ../../../../js/forced-anon.js:70 #: ../../../../js/forced-anon.js:66 ../../../../js/forced-anon.js:70
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:67
#: ../../../../js/forced-anon.js:71
msgid "Forced anonymity" msgid "Forced anonymity"
msgstr "Wymuszona anonimowość" msgstr "Wymuszona anonimowość"
#: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:65 #: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:65
#: ../../../../js/forced-anon.js:60 ../../../../js/forced-anon.js:66 #: ../../../../js/forced-anon.js:60 ../../../../js/forced-anon.js:66
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:67
msgid "enabled" msgid "enabled"
msgstr "włączona" msgstr "włączona"
#: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:69 #: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:69
#: ../../../../js/forced-anon.js:60 ../../../../js/forced-anon.js:70 #: ../../../../js/forced-anon.js:60 ../../../../js/forced-anon.js:70
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:71
msgid "disabled" msgid "disabled"
msgstr "wyłączona" msgstr "wyłączona"
#: ../../../../js/quick-post-controls.js:27 #: ../../../../js/quick-post-controls.js:27
#: ../../../../js/quick-post-controls.js:29
msgid "Password" msgid "Password"
msgstr "Hasło" msgstr "Hasło"
#: ../../../../js/quick-post-controls.js:29 #: ../../../../js/quick-post-controls.js:29
#: ../../../../js/quick-post-controls.js:31
msgid "Delete file only" msgid "Delete file only"
msgstr "Usuń tylko plik" msgstr "Usuń tylko plik"
#: ../../../../js/quick-post-controls.js:30 ../../../../js/hide-images.js:50 #: ../../../../js/quick-post-controls.js:30 ../../../../js/hide-images.js:50
#: ../../../../js/upload-selection.js:51 #: ../../../../js/upload-selection.js:51 ../../../../js/hide-images.js:51
#: ../../../../js/quick-post-controls.js:32
#: ../../../../js/upload-selection.js:61
msgid "File" msgid "File"
msgstr "Plik" msgstr "Plik"
#: ../../../../js/quick-post-controls.js:31 #: ../../../../js/quick-post-controls.js:31
#: ../../../../js/quick-post-controls.js:33
msgid "Delete" msgid "Delete"
msgstr "Usuń" msgstr "Usuń"
#: ../../../../js/quick-post-controls.js:35 #: ../../../../js/quick-post-controls.js:35
#: ../../../../js/quick-post-controls.js:37
msgid "Reason" msgid "Reason"
msgstr "Powód" msgstr "Powód"
#: ../../../../js/quick-post-controls.js:37 #: ../../../../js/quick-post-controls.js:37
#: ../../../../js/quick-post-controls.js:39
msgid "Report" msgid "Report"
msgstr "Zgłoszenie" msgstr "Zgłoszenie"
#: ../../../../js/hide-images.js:50 #: ../../../../js/hide-images.js:50 ../../../../js/hide-images.js:51
msgid "hide" msgid "hide"
msgstr "ukryj" msgstr "ukryj"
#: ../../../../js/hide-images.js:56 #: ../../../../js/hide-images.js:56 ../../../../js/hide-images.js:57
msgid "show" msgid "show"
msgstr "pokaż" msgstr "pokaż"
#: ../../../../js/toggle-images.js:41 #: ../../../../js/toggle-images.js:41 ../../../../js/toggle-images.js:42
msgid "hidden" msgid "hidden"
msgstr "ukryte" msgstr "ukryte"
#: ../../../../js/toggle-images.js:57 ../../../../js/toggle-images.js:70 #: ../../../../js/toggle-images.js:57 ../../../../js/toggle-images.js:70
#: ../../../../js/toggle-images.js:58 ../../../../js/toggle-images.js:71
msgid "Show images" msgid "Show images"
msgstr "Pokaż obrazki" msgstr "Pokaż obrazki"
#: ../../../../js/toggle-images.js:57 ../../../../js/toggle-images.js:70 #: ../../../../js/toggle-images.js:57 ../../../../js/toggle-images.js:70
#: ../../../../js/toggle-images.js:58 ../../../../js/toggle-images.js:71
msgid "Hide images" msgid "Hide images"
msgstr "Ukryj obrazki" msgstr "Ukryj obrazki"
#: ../../../../js/style-select.js:40 #: ../../../../js/style-select.js:40 ../../../../js/style-select.js:41
msgid "Style: " msgid "Style: "
msgstr "Styl: " msgstr "Styl: "
@ -191,23 +216,23 @@ msgstr "Nie ma więcej wątków do wyświetlenia"
msgid "Loading..." msgid "Loading..."
msgstr "Ładowanie..." msgstr "Ładowanie..."
#: ../../../../js/upload-selection.js:32 #: ../../../../js/upload-selection.js:32 ../../../../js/upload-selection.js:45
msgid "URL" msgid "URL"
msgstr "URL" msgstr "URL"
#: ../../../../js/upload-selection.js:50 #: ../../../../js/upload-selection.js:50 ../../../../js/upload-selection.js:60
msgid "Select" msgid "Select"
msgstr "Wybierz" msgstr "Wybierz"
#: ../../../../js/upload-selection.js:53 #: ../../../../js/upload-selection.js:53 ../../../../js/upload-selection.js:63
msgid "Remote" msgid "Remote"
msgstr "Zdalny" msgstr "Zdalny"
#: ../../../../js/upload-selection.js:56 #: ../../../../js/upload-selection.js:56 ../../../../js/upload-selection.js:66
msgid "Embed" msgid "Embed"
msgstr "Osadź" msgstr "Osadź"
#: ../../../../js/upload-selection.js:59 #: ../../../../js/upload-selection.js:59 ../../../../js/upload-selection.js:69
msgid "Oekaki" msgid "Oekaki"
msgstr "Oekaki" msgstr "Oekaki"
@ -260,16 +285,19 @@ msgid "Enter font or leave empty"
msgstr "Podaj czcionkę, bądź pozostaw puste" msgstr "Podaj czcionkę, bądź pozostaw puste"
#: ../../../../js/catalog-link.js:21 ../../../../js/catalog-link.js:32 #: ../../../../js/catalog-link.js:21 ../../../../js/catalog-link.js:32
#: ../../../../js/catalog-link.js:40 #: ../../../../js/catalog-link.js:40 ../../../../js/catalog-link.js:33
#: ../../../../js/catalog-link.js:44 ../../../../js/catalog-link.js:52
msgid "Catalog" msgid "Catalog"
msgstr "Katalog" msgstr "Katalog"
#: ../../../../js/expand-all-images.js:20 #: ../../../../js/expand-all-images.js:20
#: ../../../../js/expand-all-images.js:21 #: ../../../../js/expand-all-images.js:21
#: ../../../../js/expand-all-images.js:22
msgid "Expand all images" msgid "Expand all images"
msgstr "Rozwiń wszystkie obrazki" msgstr "Rozwiń wszystkie obrazki"
#: ../../../../js/download-original.js:32 #: ../../../../js/download-original.js:32
#: ../../../../js/download-original.js:33
msgid "Save as original filename" msgid "Save as original filename"
msgstr "Zapisz z oryginalną nazwą pliku" msgstr "Zapisz z oryginalną nazwą pliku"
@ -289,62 +317,221 @@ msgstr "Coś poszło źle... wystąpił nieznany błąd!"
msgid "Working..." msgid "Working..."
msgstr "Przetwarzanie..." msgstr "Przetwarzanie..."
#: ../../../../js/ajax.js:42 #: ../../../../js/ajax.js:42 ../../../../js/ajax.js:45
msgid "Posting... (#%)" msgid "Posting... (#%)"
msgstr "Postowanie... (#%)" msgstr "Postowanie... (#%)"
#: ../../../../js/ajax.js:104 #: ../../../../js/ajax.js:104 ../../../../js/ajax.js:109
msgid "Posted..." msgid "Posted..."
msgstr "Zapostowano..." msgstr "Zapostowano..."
#: ../../../../js/ajax.js:106 #: ../../../../js/ajax.js:106 ../../../../js/ajax.js:111
msgid "An unknown error occured when posting!" msgid "An unknown error occured when posting!"
msgstr "Wystąpił nieznany błąd podczas postowania!" msgstr "Wystąpił nieznany błąd podczas postowania!"
#: ../../../../js/ajax.js:130 #: ../../../../js/ajax.js:130 ../../../../js/ajax.js:135
msgid "Posting..." msgid "Posting..."
msgstr "Postowanie..." msgstr "Postowanie..."
#: ../../../../js/quick-reply.js:223 #: ../../../../js/quick-reply.js:223 ../../../../js/quick-reply.js:224
msgid "Upload URL" msgid "Upload URL"
msgstr "Wyślij URL" msgstr "Wyślij URL"
#: ../../../../js/quick-reply.js:266 #: ../../../../js/quick-reply.js:266 ../../../../js/quick-reply.js:267
msgid "Spoiler Image" msgid "Spoiler Image"
msgstr "Schowaj obrazek" msgstr "Schowaj obrazek"
#: ../../../../js/quick-reply.js:277 #: ../../../../js/quick-reply.js:277 ../../../../js/quick-reply.js:278
msgid "Comment" msgid "Comment"
msgstr "Komentarz" msgstr "Komentarz"
#: ../../../../js/quick-reply.js:285 ../../../../js/quick-reply.js:406 #: ../../../../js/quick-reply.js:285 ../../../../js/quick-reply.js:406
#: ../../../../js/quick-reply.js:286 ../../../../js/quick-reply.js:407
msgid "Quick Reply" msgid "Quick Reply"
msgstr "Szybka odpowiedź" msgstr "Szybka odpowiedź"
#: ../../../../js/watch.js:249 ../../../../js/watch.js:250 #: ../../../../js/watch.js:249 ../../../../js/watch.js:250
#: ../../../../js/watch.js:288 ../../../../js/watch.js:289
#: ../../../../js/watch.js:330 ../../../../js/watch.js:331
msgid "Stop watching this thread" msgid "Stop watching this thread"
msgstr "Przestań obserwować ten wątek" msgstr "Przestań obserwować ten wątek"
#: ../../../../js/watch.js:249 ../../../../js/watch.js:250 #: ../../../../js/watch.js:249 ../../../../js/watch.js:250
#: ../../../../js/watch.js:288 ../../../../js/watch.js:289
#: ../../../../js/watch.js:330 ../../../../js/watch.js:331
msgid "Watch this thread" msgid "Watch this thread"
msgstr "Obserwuj ten wątek" msgstr "Obserwuj ten wątek"
#: ../../../../js/watch.js:260 ../../../../js/watch.js:261 #: ../../../../js/watch.js:260 ../../../../js/watch.js:261
#: ../../../../js/watch.js:269 #: ../../../../js/watch.js:269 ../../../../js/watch.js:299
#: ../../../../js/watch.js:300 ../../../../js/watch.js:308
#: ../../../../js/watch.js:341 ../../../../js/watch.js:342
#: ../../../../js/watch.js:350
msgid "Unpin this board" msgid "Unpin this board"
msgstr "Odepnij ten board" msgstr "Odepnij ten board"
#: ../../../../js/watch.js:260 ../../../../js/watch.js:261 #: ../../../../js/watch.js:260 ../../../../js/watch.js:261
#: ../../../../js/watch.js:269 #: ../../../../js/watch.js:269 ../../../../js/watch.js:299
#: ../../../../js/watch.js:300 ../../../../js/watch.js:308
#: ../../../../js/watch.js:341 ../../../../js/watch.js:342
#: ../../../../js/watch.js:350
msgid "Pin this board" msgid "Pin this board"
msgstr "Przypnij ten board" msgstr "Przypnij ten board"
#: ../../../../js/watch.js:262 ../../../../js/watch.js:267 #: ../../../../js/watch.js:262 ../../../../js/watch.js:267
#: ../../../../js/watch.js:268 #: ../../../../js/watch.js:268 ../../../../js/watch.js:301
#: ../../../../js/watch.js:306 ../../../../js/watch.js:307
#: ../../../../js/watch.js:343 ../../../../js/watch.js:348
#: ../../../../js/watch.js:349
msgid "Stop watching this board" msgid "Stop watching this board"
msgstr "Przestań oberwować ten board" msgstr "Przestań oberwować ten board"
#: ../../../../js/watch.js:262 ../../../../js/watch.js:267 #: ../../../../js/watch.js:262 ../../../../js/watch.js:267
#: ../../../../js/watch.js:268 #: ../../../../js/watch.js:268 ../../../../js/watch.js:301
#: ../../../../js/watch.js:306 ../../../../js/watch.js:307
#: ../../../../js/watch.js:343 ../../../../js/watch.js:348
#: ../../../../js/watch.js:349
msgid "Watch this board" msgid "Watch this board"
msgstr "Obserwuj ten board" msgstr "Obserwuj ten board"
#: ../../../../js/wpaint.js:113
msgid "Click on any image on this site to load it into oekaki applet"
msgstr ""
"Kliknij w jakikolwiek obrazek na tej stronie aby załadować go do apletu "
"oekaki"
#: ../../../../js/local-time.js:29
msgid "Sunday"
msgstr "Niedziela"
#: ../../../../js/local-time.js:29
msgid "Monday"
msgstr "Poniedziałek"
#: ../../../../js/local-time.js:29
msgid "Tuesday"
msgstr "Wtorek"
#: ../../../../js/local-time.js:29
msgid "Wednesday"
msgstr "Środa"
#: ../../../../js/local-time.js:29
msgid "Thursday"
msgstr "Czwartek"
#: ../../../../js/local-time.js:29
msgid "Friday"
msgstr "Piątek"
#: ../../../../js/local-time.js:29
msgid "Saturday"
msgstr "Sobota"
#: ../../../../js/local-time.js:31
msgid "January"
msgstr "stycznia"
#: ../../../../js/local-time.js:31
msgid "February"
msgstr "lutego"
#: ../../../../js/local-time.js:31
msgid "March"
msgstr "marca"
#: ../../../../js/local-time.js:31
msgid "April"
msgstr "kwietnia"
#: ../../../../js/local-time.js:31 ../../../../js/local-time.js:32
msgid "May"
msgstr "maj"
#: ../../../../js/local-time.js:31
msgid "June"
msgstr "czerwca"
#: ../../../../js/local-time.js:31
msgid "July"
msgstr "lipca"
#: ../../../../js/local-time.js:31
msgid "August"
msgstr "sierpnia"
#: ../../../../js/local-time.js:31
msgid "September"
msgstr "września"
#: ../../../../js/local-time.js:31
msgid "October"
msgstr "października"
#: ../../../../js/local-time.js:31
msgid "November"
msgstr "listopada"
#: ../../../../js/local-time.js:31
msgid "December"
msgstr "grudnia"
#: ../../../../js/local-time.js:32
msgid "Jan"
msgstr "sty"
#: ../../../../js/local-time.js:32
msgid "Feb"
msgstr "lut"
#: ../../../../js/local-time.js:32
msgid "Mar"
msgstr "mar"
#: ../../../../js/local-time.js:32
msgid "Apr"
msgstr "kwi"
#: ../../../../js/local-time.js:32
msgid "Jun"
msgstr "cze"
#: ../../../../js/local-time.js:32
msgid "Jul"
msgstr "lip"
#: ../../../../js/local-time.js:32
msgid "Aug"
msgstr "sie"
#: ../../../../js/local-time.js:32
msgid "Sep"
msgstr "wrz"
#: ../../../../js/local-time.js:32
msgid "Oct"
msgstr "paź"
#: ../../../../js/local-time.js:32
msgid "Nov"
msgstr "lis"
#: ../../../../js/local-time.js:32
msgid "Dec"
msgstr "gru"
#: ../../../../js/local-time.js:33
msgid "AM"
msgstr "AM"
#: ../../../../js/local-time.js:34
msgid "PM"
msgstr "PM"
#: ../../../../js/local-time.js:35
msgid "am"
msgstr "am"
#: ../../../../js/local-time.js:36
msgid "pm"
msgstr "pm"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
l10n = {"Show locked threads":"Zobrazi\u0165 zamknut\u00e9 vl\u00e1kna","Hide locked threads":"Skry\u0165 zamknut\u00e9 vl\u00e1kna","File":"S\u00fabor","hide":"skry\u0165","show":"uk\u00e1za\u0165","Stop watching this thread":"Zastavi\u0165 sledovanie tohto vl\u00e1kna","Watch this thread":"Sledova\u0165 toto vl\u00e1kno","Unpin this board":"Odopn\u00fa\u0165 t\u00fato dosku","Pin this board":"Pripn\u00fa\u0165 t\u00fato dosku","Stop watching this board":"Zastavi\u0165 sledovanie tejto dosky","Watch this board":"Sledova\u0165 t\u00fato dosku","Upload URL":"Adresa s\u00faboru","Spoiler Image":"Skryt\u00fd obr\u00e1zok","Comment":"Koment\u00e1r","Quick Reply":"R\u00fdchla odpove\u010f","Style: ":"\u0160t\u00fdl:","Sun":"Ne","Mon":"Po","Tue":"Ut","Wed":"St","Thu":"\u0160t","Fri":"Pi","Sat":"So","Forced anonymity":"Vyn\u00faten\u00e1 anonymita","enabled":"zapnut\u00e1","disabled":"vypnut\u00e1","Submit":"Odosla\u0165","Quick reply":"R\u00fdchla odpove\u010f","Posting mode: Replying to <small>&gt;&gt;{0}<\/small>":"Re\u017eim prispievania: Odpove\u010f na <small>&gt;&gt;{0}<\/small>","Return":"N\u00e1vrat","Click reply to view.":"Klikni na Odpove\u010f pre ich zobrazenie.","Click to expand":"Klikni sem pre zobrazenie","Hide expanded replies":"Skry\u0165 zobrazen\u00e9 odpovede","Reported post(s).":"Pr\u00edspevok nahl\u00e1sen\u00fd.","An unknown error occured!":"Nastala nezn\u00e1ma chyba!","Something went wrong... An unknown error occured!":"Stalo sa nie\u010do zl\u00e9... Nastala nezn\u00e1ma chyba!","Working...":"Pracujem...","Posting... (#%)":"Odosielam... (#%)","Posted...":"Odoslan\u00e9...","An unknown error occured when posting!":"Pri odosielan\u00ed nastala nezn\u00e1ma chyba!","Posting...":"Odosielam...","Password":"Heslo","Delete file only":"Odstr\u00e1ni\u0165 iba s\u00fabor","Delete":"Odstr\u00e1ni\u0165","Reason":"D\u00f4vod","Report":"Nahl\u00e1si\u0165","Catalog":"Katal\u00f3g","URL":"Adresa","Select":"Vybra\u0165","Remote":"Vzdialen\u00fd","Embed":"Vlo\u017ei\u0165","Oekaki":"Oekaki","hidden":"skryt\u00fd","Show images":"Zobrazi\u0165 obr\u00e1zky","Hide images":"Skry\u0165 obr\u00e1zky","Expand all images":"Otvori\u0165 v\u0161etky obr\u00e1zky","Save as original filename":"Ulo\u017ei\u0165 s p\u00f4vodn\u00fdm n\u00e1zvom","(hide threads from this board)":"(skry\u0165 vl\u00e1kna z tejto dosky)","(show threads from this board)":"(zobrazi\u0165 vl\u00e1kna z tejto dosky)","No more threads to display":"\u017diadne \u010fal\u0161ie vl\u00e1kna na zobrazenie","Loading...":"Na\u010d\u00edtanie...","Hello!":"Ahoj!","{0} users":"{0} u\u017e\u00edvate\u013eov","Sunday":"Nede\u013ea","Monday":"Pondelok","Tuesday":"Utorok","Wednesday":"Streda","Thursday":"\u0160tvrtok","Friday":"Piatok","Saturday":"Sobota","January":"Janu\u00e1r","February":"Febru\u00e1r","March":"Marec","April":"Apr\u00edl","May":"M\u00e1j","June":"J\u00fan","July":"J\u00fal","August":"August","September":"September","October":"Okt\u00f3ber","November":"November","December":"December","Jan":"Jan","Feb":"Feb","Mar":"Mar","Apr":"Apr","Jun":"J\u00fan","Jul":"J\u00fal","Aug":"Aug","Sep":"Sep","Oct":"Okt","Nov":"Nov","Dec":"Dec","AM":"Doobeda","PM":"Poobede","am":"doobeda","pm":"poobede"};

View File

@ -0,0 +1,431 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-23 18:52+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: dubcheck <admin@alokal.eu>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: sk_SK\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../../../../js/toggle-locked-threads.js:41
#: ../../../../js/toggle-locked-threads.js:56
msgid "Show locked threads"
msgstr "Zobraziť zamknuté vlákna"
#: ../../../../js/toggle-locked-threads.js:41
#: ../../../../js/toggle-locked-threads.js:56
msgid "Hide locked threads"
msgstr "Skryť zamknuté vlákna"
#: ../../../../js/hide-images.js:51 ../../../../js/quick-post-controls.js:32
#: ../../../../js/upload-selection.js:61
msgid "File"
msgstr "Súbor"
#: ../../../../js/hide-images.js:51
msgid "hide"
msgstr "skryť"
#: ../../../../js/hide-images.js:57
msgid "show"
msgstr "ukázať"
#: ../../../../js/watch.js:330 ../../../../js/watch.js:331
msgid "Stop watching this thread"
msgstr "Zastaviť sledovanie tohto vlákna"
#: ../../../../js/watch.js:330 ../../../../js/watch.js:331
msgid "Watch this thread"
msgstr "Sledovať toto vlákno"
#: ../../../../js/watch.js:341 ../../../../js/watch.js:342
#: ../../../../js/watch.js:350
msgid "Unpin this board"
msgstr "Odopnúť túto dosku"
#: ../../../../js/watch.js:341 ../../../../js/watch.js:342
#: ../../../../js/watch.js:350
msgid "Pin this board"
msgstr "Pripnúť túto dosku"
#: ../../../../js/watch.js:343 ../../../../js/watch.js:348
#: ../../../../js/watch.js:349
msgid "Stop watching this board"
msgstr "Zastaviť sledovanie tejto dosky"
#: ../../../../js/watch.js:343 ../../../../js/watch.js:348
#: ../../../../js/watch.js:349
msgid "Watch this board"
msgstr "Sledovať túto dosku"
#: ../../../../js/quick-reply.js:224
msgid "Upload URL"
msgstr "Adresa súboru"
#: ../../../../js/quick-reply.js:267
msgid "Spoiler Image"
msgstr "Skrytý obrázok"
#: ../../../../js/quick-reply.js:278
msgid "Comment"
msgstr "Komentár"
#: ../../../../js/quick-reply.js:286 ../../../../js/quick-reply.js:407
msgid "Quick Reply"
msgstr "Rýchla odpoveď"
#: ../../../../js/style-select.js:41
msgid "Style: "
msgstr "Štýl:"
#: ../../../../js/local-time.js:41 ../../../../js/local-time.js:30
#: ../../../../js/local-time.js:40
msgid "Sun"
msgstr "Ne"
#: ../../../../js/local-time.js:41 ../../../../js/local-time.js:30
#: ../../../../js/local-time.js:40
msgid "Mon"
msgstr "Po"
#: ../../../../js/local-time.js:41 ../../../../js/local-time.js:30
#: ../../../../js/local-time.js:40
msgid "Tue"
msgstr "Ut"
#: ../../../../js/local-time.js:41 ../../../../js/local-time.js:30
#: ../../../../js/local-time.js:40
msgid "Wed"
msgstr "St"
#: ../../../../js/local-time.js:41 ../../../../js/local-time.js:30
#: ../../../../js/local-time.js:40
msgid "Thu"
msgstr "Št"
#: ../../../../js/local-time.js:41 ../../../../js/local-time.js:30
#: ../../../../js/local-time.js:40
msgid "Fri"
msgstr "Pi"
#: ../../../../js/local-time.js:41 ../../../../js/local-time.js:30
#: ../../../../js/local-time.js:40
msgid "Sat"
msgstr "So"
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:67
#: ../../../../js/forced-anon.js:71
msgid "Forced anonymity"
msgstr "Vynútená anonymita"
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:67
msgid "enabled"
msgstr "zapnutá"
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:71
msgid "disabled"
msgstr "vypnutá"
#: ../../../../js/quick-reply-old.js:23
msgid "Submit"
msgstr "Odoslať"
#: ../../../../js/quick-reply-old.js:33
msgid "Quick reply"
msgstr "Rýchla odpoveď"
#: ../../../../js/quick-reply-old.js:35
#, python-brace-format
msgid "Posting mode: Replying to <small>&gt;&gt;{0}</small>"
msgstr "Režim prispievania: Odpoveď na <small>&gt;&gt;{0}</small>"
#: ../../../../js/quick-reply-old.js:35
msgid "Return"
msgstr "Návrat"
#: ../../../../js/expand.js:22
msgid "Click reply to view."
msgstr "Klikni na Odpoveď pre ich zobrazenie."
#: ../../../../js/expand.js:22
msgid "Click to expand"
msgstr "Klikni sem pre zobrazenie"
#: ../../../../js/expand.js:46
msgid "Hide expanded replies"
msgstr "Skryť zobrazené odpovede"
#: ../../../../js/ajax-post-controls.js:43
msgid "Reported post(s)."
msgstr "Príspevok nahlásený."
#: ../../../../js/ajax-post-controls.js:53
msgid "An unknown error occured!"
msgstr "Nastala neznáma chyba!"
#: ../../../../js/ajax-post-controls.js:60
msgid "Something went wrong... An unknown error occured!"
msgstr "Stalo sa niečo zlé... Nastala neznáma chyba!"
#: ../../../../js/ajax-post-controls.js:68
msgid "Working..."
msgstr "Pracujem..."
#: ../../../../js/ajax.js:45
msgid "Posting... (#%)"
msgstr "Odosielam... (#%)"
#: ../../../../js/ajax.js:109
msgid "Posted..."
msgstr "Odoslané..."
#: ../../../../js/ajax.js:111
msgid "An unknown error occured when posting!"
msgstr "Pri odosielaní nastala neznáma chyba!"
#: ../../../../js/ajax.js:135
msgid "Posting..."
msgstr "Odosielam..."
#: ../../../../js/wpaint.js:113
msgid "Click on any image on this site to load it into oekaki applet"
msgstr ""
"Klikni na akýkoľvek obrázok na tejto stránke pre jeho načítanie do Oekaki"
#: ../../../../js/quick-post-controls.js:29
msgid "Password"
msgstr "Heslo"
#: ../../../../js/quick-post-controls.js:31
msgid "Delete file only"
msgstr "Odstrániť iba súbor"
#: ../../../../js/quick-post-controls.js:33
msgid "Delete"
msgstr "Odstrániť"
#: ../../../../js/quick-post-controls.js:37
msgid "Reason"
msgstr "Dôvod"
#: ../../../../js/quick-post-controls.js:39
msgid "Report"
msgstr "Nahlásiť"
#: ../../../../js/catalog-link.js:33 ../../../../js/catalog-link.js:44
#: ../../../../js/catalog-link.js:52
msgid "Catalog"
msgstr "Katalóg"
#: ../../../../js/upload-selection.js:45
msgid "URL"
msgstr "Adresa"
#: ../../../../js/upload-selection.js:60
msgid "Select"
msgstr "Vybrať"
#: ../../../../js/upload-selection.js:63
msgid "Remote"
msgstr "Vzdialený"
#: ../../../../js/upload-selection.js:66
msgid "Embed"
msgstr "Vložiť"
#: ../../../../js/upload-selection.js:69
msgid "Oekaki"
msgstr "Oekaki"
#: ../../../../js/toggle-images.js:42
msgid "hidden"
msgstr "skrytý"
#: ../../../../js/toggle-images.js:58 ../../../../js/toggle-images.js:71
msgid "Show images"
msgstr "Zobraziť obrázky"
#: ../../../../js/toggle-images.js:58 ../../../../js/toggle-images.js:71
msgid "Hide images"
msgstr "Skryť obrázky"
#: ../../../../js/expand-all-images.js:22
msgid "Expand all images"
msgstr "Otvoriť všetky obrázky"
#: ../../../../js/download-original.js:33
msgid "Save as original filename"
msgstr "Uložiť s pôvodným názvom"
#: ../../../../templates/themes/ukko/ukko.js:29
#: ../../../../templates/themes/ukko/ukko.js:40
msgid "(hide threads from this board)"
msgstr "(skryť vlákna z tejto dosky)"
#: ../../../../templates/themes/ukko/ukko.js:33
#: ../../../../templates/themes/ukko/ukko.js:45
msgid "(show threads from this board)"
msgstr "(zobraziť vlákna z tejto dosky)"
#: ../../../../templates/themes/ukko/ukko.js:58
msgid "No more threads to display"
msgstr "Žiadne ďalšie vlákna na zobrazenie"
#: ../../../../templates/themes/ukko/ukko.js:80
msgid "Loading..."
msgstr "Načítanie..."
#: ../../../../templates/main.js:6
msgid "Hello!"
msgstr "Ahoj!"
#: ../../../../templates/main.js:18
#, python-brace-format
msgid "{0} users"
msgstr "{0} užívateľov"
#: ../../../../js/local-time.js:29
msgid "Sunday"
msgstr "Nedeľa"
#: ../../../../js/local-time.js:29
msgid "Monday"
msgstr "Pondelok"
#: ../../../../js/local-time.js:29
msgid "Tuesday"
msgstr "Utorok"
#: ../../../../js/local-time.js:29
msgid "Wednesday"
msgstr "Streda"
#: ../../../../js/local-time.js:29
msgid "Thursday"
msgstr "Štvrtok"
#: ../../../../js/local-time.js:29
msgid "Friday"
msgstr "Piatok"
#: ../../../../js/local-time.js:29
msgid "Saturday"
msgstr "Sobota"
#: ../../../../js/local-time.js:31
msgid "January"
msgstr "Január"
#: ../../../../js/local-time.js:31
msgid "February"
msgstr "Február"
#: ../../../../js/local-time.js:31
msgid "March"
msgstr "Marec"
#: ../../../../js/local-time.js:31
msgid "April"
msgstr "Apríl"
#: ../../../../js/local-time.js:31 ../../../../js/local-time.js:32
msgid "May"
msgstr "Máj"
#: ../../../../js/local-time.js:31
msgid "June"
msgstr "Jún"
#: ../../../../js/local-time.js:31
msgid "July"
msgstr "Júl"
#: ../../../../js/local-time.js:31
msgid "August"
msgstr "August"
#: ../../../../js/local-time.js:31
msgid "September"
msgstr "September"
#: ../../../../js/local-time.js:31
msgid "October"
msgstr "Október"
#: ../../../../js/local-time.js:31
msgid "November"
msgstr "November"
#: ../../../../js/local-time.js:31
msgid "December"
msgstr "December"
#: ../../../../js/local-time.js:32
msgid "Jan"
msgstr "Jan"
#: ../../../../js/local-time.js:32
msgid "Feb"
msgstr "Feb"
#: ../../../../js/local-time.js:32
msgid "Mar"
msgstr "Mar"
#: ../../../../js/local-time.js:32
msgid "Apr"
msgstr "Apr"
#: ../../../../js/local-time.js:32
msgid "Jun"
msgstr "Jún"
#: ../../../../js/local-time.js:32
msgid "Jul"
msgstr "Júl"
#: ../../../../js/local-time.js:32
msgid "Aug"
msgstr "Aug"
#: ../../../../js/local-time.js:32
msgid "Sep"
msgstr "Sep"
#: ../../../../js/local-time.js:32
msgid "Oct"
msgstr "Okt"
#: ../../../../js/local-time.js:32
msgid "Nov"
msgstr "Nov"
#: ../../../../js/local-time.js:32
msgid "Dec"
msgstr "Dec"
#: ../../../../js/local-time.js:33
msgid "AM"
msgstr "Doobeda"
#: ../../../../js/local-time.js:34
msgid "PM"
msgstr "Poobede"
#: ../../../../js/local-time.js:35
msgid "am"
msgstr "doobeda"
#: ../../../../js/local-time.js:36
msgid "pm"
msgstr "poobede"

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
l10n = {"Style: ":"Stil: ","File":"Dosya","hide":"gizle","show":"g\u00f6ster","Show locked threads":"Kilitli konular\u0131 g\u00f6ster","Hide locked threads":"Gizli konular\u0131 kilitle","URL":"URL","Select":"Se\u00e7","Remote":"Uzak","Embed":"G\u00f6m","Oekaki":"Oekaki","hidden":"gizli","Show images":"Resimleri g\u00f6ster","Hide images":"Resimleri gizle","Password":"\u015eifre","Delete file only":"Sadece dosyay\u0131 sil","Delete":"Sil","Reason":"Sebep","Report":"\u015eikayet et","Click reply to view.":"G\u00f6rmek i\u00e7in cevaplaya bas\u0131n.","Click to expand":"Geni\u015fletmek i\u00e7in t\u0131klay\u0131n","Hide expanded replies":"Daralt","Brush size":"F\u0131r\u00e7a b\u00fcy\u00fckl\u00fc\u011f\u00fc","Set text":"Yaz\u0131y\u0131 ayarla","Clear":"Temizle","Save":"Kay\u0131t et","Load":"Y\u00fckle","Toggle eraser":"Silgi","Get color":"Rengi se\u00e7","Fill":"Doldur","Use oekaki instead of file?":"Dosya yerine oekaki kullan","Edit in oekaki":"oekaki'de d\u00fczenle","Enter some text":"Bir yaz\u0131 girin","Enter font or leave empty":"Font girin ya da bo\u015f b\u0131rak\u0131n","Forced anonymity":"Zorunlu anon","enabled":"etkin","disabled":"etkin de\u011fil","Sun":"Paz","Mon":"Pzt","Tue":"Sa","Wed":"\u00c7r\u015f","Thu":"Per","Fri":"Cu","Sat":"Cts","Catalog":"Katalog","Submit":"G\u00f6nder","Quick reply":"\u00c7abuk cevap","Posting mode: Replying to <small>&gt;&gt;{0}<\/small>":"G\u00f6nderme modu: <small>&gt;&gt;{0}<\/small> cevap veriyorsunuz","Return":"Geri d\u00f6n","Expand all images":"B\u00fct\u00fcn resimleri geni\u015flet","Hello!":"Merhaba!","{0} users":"{0} kullan\u0131c\u0131","(hide threads from this board)":"(bu tahtadan konular\u0131 gizle)","(show threads from this board)":"(bu tahtadan konular\u0131 g\u00f6ster)","No more threads to display":"G\u00f6sterecek ba\u015fka konu kalmad\u0131","Loading...":"Y\u00fckleniyor...","Save as original filename":"Dosya ad\u0131yla kaydet","Reported post(s).":"\u015eikayet edilen konu\/konular.","An unknown error occured!":"FATAL \u00d6R\u00d6R","Something went wrong... An unknown error occured!":"Bilemedi\u011fimiz \u00e7ok fena \u015feyler oldu!","Working...":"Yap\u0131yoruz...","Posting... (#%)":"G\u00f6nderiliyor... (#%)","Posted...":"G\u00f6nderildi...","An unknown error occured when posting!":"Hata... \u00e7ok... fena... ","Posting...":"G\u00f6nderiliyor...","Upload URL":"Y\u00fckleme linki","Spoiler Image":"Spoiler","Comment":"Yorum","Quick Reply":"\u00c7abuk Cevaplama","Stop watching this thread":"Bu konuyu takip etmeyi b\u0131rak","Watch this thread":"Bu konuyu takip et","Unpin this board":"Bu tahtan\u0131n i\u011fnesini kald\u0131r","Pin this board":"Bu tahtay\u0131 i\u011fnele","Stop watching this board":"Bu tahtay\u0131 izlemeyi b\u0131rak","Watch this board":"Bu tahtay\u0131 izle","Click on any image on this site to load it into oekaki applet":"Oekaki'ye atmak i\u00e7in website \u00fczerindeki herhangi bir resme t\u0131klay\u0131n"};

View File

@ -0,0 +1,390 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: Tinyboard JS Çevirisi"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-20 20:19+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Tunay Uyar tunayuyar39@gmail.com"
"Language-Team: Türkçe"
"Language: TR"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8"
"Content-Transfer-Encoding: 8bit\n"
#: ../../../../js/style-select.js:40 ../../../../js/style-select.js:41
msgid "Style: "
msgstr "Stil: "
#: ../../../../js/hide-images.js:50 ../../../../js/upload-selection.js:51
#: ../../../../js/quick-post-controls.js:30 ../../../../js/hide-images.js:51
#: ../../../../js/quick-post-controls.js:32
#: ../../../../js/upload-selection.js:61
msgid "File"
msgstr "Dosya"
#: ../../../../js/hide-images.js:50 ../../../../js/hide-images.js:51
msgid "hide"
msgstr "gizle"
#: ../../../../js/hide-images.js:56 ../../../../js/hide-images.js:57
msgid "show"
msgstr "göster"
#: ../../../../js/toggle-locked-threads.js:39
#: ../../../../js/toggle-locked-threads.js:54
#: ../../../../js/toggle-locked-threads.js:40
#: ../../../../js/toggle-locked-threads.js:55
#: ../../../../js/toggle-locked-threads.js:41
#: ../../../../js/toggle-locked-threads.js:56
msgid "Show locked threads"
msgstr "Kilitli konuları göster"
#: ../../../../js/toggle-locked-threads.js:39
#: ../../../../js/toggle-locked-threads.js:54
#: ../../../../js/toggle-locked-threads.js:40
#: ../../../../js/toggle-locked-threads.js:55
#: ../../../../js/toggle-locked-threads.js:41
#: ../../../../js/toggle-locked-threads.js:56
msgid "Hide locked threads"
msgstr "Gizli konuları kilitle"
#: ../../../../js/upload-selection.js:32 ../../../../js/upload-selection.js:45
msgid "URL"
msgstr "URL"
#: ../../../../js/upload-selection.js:50 ../../../../js/upload-selection.js:60
msgid "Select"
msgstr "Seç"
#: ../../../../js/upload-selection.js:53 ../../../../js/upload-selection.js:63
msgid "Remote"
msgstr "Uzak"
#: ../../../../js/upload-selection.js:56 ../../../../js/upload-selection.js:66
msgid "Embed"
msgstr "Göm"
#: ../../../../js/upload-selection.js:59 ../../../../js/upload-selection.js:69
msgid "Oekaki"
msgstr "Oekaki"
#: ../../../../js/toggle-images.js:41 ../../../../js/toggle-images.js:42
msgid "hidden"
msgstr "gizli"
#: ../../../../js/toggle-images.js:57 ../../../../js/toggle-images.js:70
#: ../../../../js/toggle-images.js:58 ../../../../js/toggle-images.js:71
msgid "Show images"
msgstr "Resimleri göster"
#: ../../../../js/toggle-images.js:57 ../../../../js/toggle-images.js:70
#: ../../../../js/toggle-images.js:58 ../../../../js/toggle-images.js:71
msgid "Hide images"
msgstr "Resimleri gizle"
#: ../../../../js/quick-post-controls.js:27
#: ../../../../js/quick-post-controls.js:29
msgid "Password"
msgstr "Şifre"
#: ../../../../js/quick-post-controls.js:29
#: ../../../../js/quick-post-controls.js:31
msgid "Delete file only"
msgstr "Sadece dosyayı sil"
#: ../../../../js/quick-post-controls.js:31
#: ../../../../js/quick-post-controls.js:33
msgid "Delete"
msgstr "Sil"
#: ../../../../js/quick-post-controls.js:35
#: ../../../../js/quick-post-controls.js:37
msgid "Reason"
msgstr "Sebep"
#: ../../../../js/quick-post-controls.js:37
#: ../../../../js/quick-post-controls.js:39
msgid "Report"
msgstr "Şikayet et"
#: ../../../../js/expand.js:20 ../../../../js/expand.js:22
msgid "Click reply to view."
msgstr "Görmek için cevaplaya basın."
#: ../../../../js/expand.js:20 ../../../../js/expand.js:22
msgid "Click to expand"
msgstr "Genişletmek için tıklayın"
#: ../../../../js/expand.js:44 ../../../../js/expand.js:46
msgid "Hide expanded replies"
msgstr "Daralt"
#: ../../../../js/oekaki.js:10
msgid "Brush size"
msgstr "Fırça büyüklüğü"
#: ../../../../js/oekaki.js:10
msgid "Set text"
msgstr "Yazıyı ayarla"
#: ../../../../js/oekaki.js:10
msgid "Clear"
msgstr "Temizle"
#: ../../../../js/oekaki.js:10
msgid "Save"
msgstr "Kayıt et"
#: ../../../../js/oekaki.js:10
msgid "Load"
msgstr "Yükle"
#: ../../../../js/oekaki.js:11
msgid "Toggle eraser"
msgstr "Silgi"
#: ../../../../js/oekaki.js:11
msgid "Get color"
msgstr "Rengi seç"
#: ../../../../js/oekaki.js:11
msgid "Fill"
msgstr "Doldur"
#: ../../../../js/oekaki.js:12
msgid "Use oekaki instead of file?"
msgstr "Dosya yerine oekaki kullan"
#: ../../../../js/oekaki.js:21
msgid "Edit in oekaki"
msgstr "oekaki'de düzenle"
#: ../../../../js/oekaki.js:152
msgid "Enter some text"
msgstr "Bir yazı girin"
#: ../../../../js/oekaki.js:153
msgid "Enter font or leave empty"
msgstr "Font girin ya da boş bırakın"
#: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:65
#: ../../../../js/forced-anon.js:69 ../../../../js/forced-anon.js:60
#: ../../../../js/forced-anon.js:66 ../../../../js/forced-anon.js:70
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:67
#: ../../../../js/forced-anon.js:71
msgid "Forced anonymity"
msgstr "Zorunlu anon"
#: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:65
#: ../../../../js/forced-anon.js:60 ../../../../js/forced-anon.js:66
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:67
msgid "enabled"
msgstr "etkin"
#: ../../../../js/forced-anon.js:59 ../../../../js/forced-anon.js:69
#: ../../../../js/forced-anon.js:60 ../../../../js/forced-anon.js:70
#: ../../../../js/forced-anon.js:61 ../../../../js/forced-anon.js:71
msgid "disabled"
msgstr "etkin değil"
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
msgid "Sun"
msgstr "Paz"
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
msgid "Mon"
msgstr "Pzt"
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
msgid "Tue"
msgstr "Sa"
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
msgid "Wed"
msgstr "Çrş"
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
msgid "Thu"
msgstr "Per"
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
msgid "Fri"
msgstr "Cu"
#: ../../../../js/local-time.js:40 ../../../../js/local-time.js:41
msgid "Sat"
msgstr "Cts"
#: ../../../../js/catalog-link.js:21 ../../../../js/catalog-link.js:32
#: ../../../../js/catalog-link.js:40 ../../../../js/catalog-link.js:33
#: ../../../../js/catalog-link.js:44 ../../../../js/catalog-link.js:52
msgid "Catalog"
msgstr "Katalog"
#: ../../../../js/quick-reply.js:21 ../../../../js/quick-reply-old.js:21
#: ../../../../js/quick-reply-old.js:23
msgid "Submit"
msgstr "Gönder"
#: ../../../../js/quick-reply.js:31 ../../../../js/quick-reply-old.js:31
#: ../../../../js/quick-reply-old.js:33
msgid "Quick reply"
msgstr "Çabuk cevap"
#: ../../../../js/quick-reply.js:33 ../../../../js/quick-reply-old.js:33
#: ../../../../js/quick-reply-old.js:35
#, python-brace-format
msgid "Posting mode: Replying to <small>&gt;&gt;{0}</small>"
msgstr "Gönderme modu: <small>&gt;&gt;{0}</small> cevap veriyorsunuz"
#: ../../../../js/quick-reply.js:33 ../../../../js/quick-reply-old.js:33
#: ../../../../js/quick-reply-old.js:35
msgid "Return"
msgstr "Geri dön"
#: ../../../../js/expand-all-images.js:20
#: ../../../../js/expand-all-images.js:21
#: ../../../../js/expand-all-images.js:22
msgid "Expand all images"
msgstr "Bütün resimleri genişlet"
#: ../../../../templates/main.js:6
msgid "Hello!"
msgstr "Merhaba!"
#: ../../../../templates/main.js:18
#, python-brace-format
msgid "{0} users"
msgstr "{0} kullanıcı"
#: ../../../../templates/themes/ukko/ukko.js:28
#: ../../../../templates/themes/ukko/ukko.js:39
#: ../../../../templates/themes/ukko/ukko.js:29
#: ../../../../templates/themes/ukko/ukko.js:40
msgid "(hide threads from this board)"
msgstr "(bu tahtadan konuları gizle)"
#: ../../../../templates/themes/ukko/ukko.js:32
#: ../../../../templates/themes/ukko/ukko.js:44
#: ../../../../templates/themes/ukko/ukko.js:33
#: ../../../../templates/themes/ukko/ukko.js:45
msgid "(show threads from this board)"
msgstr "(bu tahtadan konuları göster)"
#: ../../../../templates/themes/ukko/ukko.js:57
#: ../../../../templates/themes/ukko/ukko.js:58
msgid "No more threads to display"
msgstr "Gösterecek başka konu kalmadı"
#: ../../../../templates/themes/ukko/ukko.js:79
#: ../../../../templates/themes/ukko/ukko.js:80
msgid "Loading..."
msgstr "Yükleniyor..."
#: ../../../../js/download-original.js:32
#: ../../../../js/download-original.js:33
msgid "Save as original filename"
msgstr "Dosya adıyla kaydet"
#: ../../../../js/ajax-post-controls.js:43
msgid "Reported post(s)."
msgstr "Şikayet edilen konu/konular."
#: ../../../../js/ajax-post-controls.js:53
msgid "An unknown error occured!"
msgstr "FATAL ÖRÖR"
#: ../../../../js/ajax-post-controls.js:60
msgid "Something went wrong... An unknown error occured!"
msgstr "Bilemediğimiz çok fena şeyler oldu!"
#: ../../../../js/ajax-post-controls.js:68
msgid "Working..."
msgstr "Yapıyoruz..."
#: ../../../../js/ajax.js:42 ../../../../js/ajax.js:45
msgid "Posting... (#%)"
msgstr "Gönderiliyor... (#%)"
#: ../../../../js/ajax.js:104 ../../../../js/ajax.js:109
msgid "Posted..."
msgstr "Gönderildi..."
#: ../../../../js/ajax.js:106 ../../../../js/ajax.js:111
msgid "An unknown error occured when posting!"
msgstr "Hata... çok... fena... "
#: ../../../../js/ajax.js:130 ../../../../js/ajax.js:135
msgid "Posting..."
msgstr "Gönderiliyor..."
#: ../../../../js/quick-reply.js:223 ../../../../js/quick-reply.js:224
msgid "Upload URL"
msgstr "Yükleme linki"
#: ../../../../js/quick-reply.js:266 ../../../../js/quick-reply.js:267
msgid "Spoiler Image"
msgstr "Spoiler"
#: ../../../../js/quick-reply.js:277 ../../../../js/quick-reply.js:278
msgid "Comment"
msgstr "Yorum"
#: ../../../../js/quick-reply.js:285 ../../../../js/quick-reply.js:406
#: ../../../../js/quick-reply.js:286 ../../../../js/quick-reply.js:407
msgid "Quick Reply"
msgstr "Çabuk Cevaplama"
#: ../../../../js/watch.js:249 ../../../../js/watch.js:250
#: ../../../../js/watch.js:288 ../../../../js/watch.js:289
#: ../../../../js/watch.js:330 ../../../../js/watch.js:331
msgid "Stop watching this thread"
msgstr "Bu konuyu takip etmeyi bırak"
#: ../../../../js/watch.js:249 ../../../../js/watch.js:250
#: ../../../../js/watch.js:288 ../../../../js/watch.js:289
#: ../../../../js/watch.js:330 ../../../../js/watch.js:331
msgid "Watch this thread"
msgstr "Bu konuyu takip et"
#: ../../../../js/watch.js:260 ../../../../js/watch.js:261
#: ../../../../js/watch.js:269 ../../../../js/watch.js:299
#: ../../../../js/watch.js:300 ../../../../js/watch.js:308
#: ../../../../js/watch.js:341 ../../../../js/watch.js:342
#: ../../../../js/watch.js:350
msgid "Unpin this board"
msgstr "Bu tahtanın iğnesini kaldır"
#: ../../../../js/watch.js:260 ../../../../js/watch.js:261
#: ../../../../js/watch.js:269 ../../../../js/watch.js:299
#: ../../../../js/watch.js:300 ../../../../js/watch.js:308
#: ../../../../js/watch.js:341 ../../../../js/watch.js:342
#: ../../../../js/watch.js:350
msgid "Pin this board"
msgstr "Bu tahtayı iğnele"
#: ../../../../js/watch.js:262 ../../../../js/watch.js:267
#: ../../../../js/watch.js:268 ../../../../js/watch.js:301
#: ../../../../js/watch.js:306 ../../../../js/watch.js:307
#: ../../../../js/watch.js:343 ../../../../js/watch.js:348
#: ../../../../js/watch.js:349
msgid "Stop watching this board"
msgstr "Bu tahtayı izlemeyi bırak"
#: ../../../../js/watch.js:262 ../../../../js/watch.js:267
#: ../../../../js/watch.js:268 ../../../../js/watch.js:301
#: ../../../../js/watch.js:306 ../../../../js/watch.js:307
#: ../../../../js/watch.js:343 ../../../../js/watch.js:348
#: ../../../../js/watch.js:349
msgid "Watch this board"
msgstr "Bu tahtayı izle"
#: ../../../../js/wpaint.js:113
msgid "Click on any image on this site to load it into oekaki applet"
msgstr "Oekaki'ye atmak için website üzerindeki herhangi bir resme tıklayın"

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -739,6 +739,16 @@ function mod_view_thread($boardName, $thread) {
echo $page; echo $page;
} }
function mod_view_thread50($boardName, $thread) {
global $config, $mod;
if (!openBoard($boardName))
error($config['error']['noboard']);
$page = buildThread50($thread, true, $mod);
echo $page;
}
function mod_ip_remove_note($ip, $id) { function mod_ip_remove_note($ip, $id) {
global $config, $mod; global $config, $mod;
@ -1071,6 +1081,104 @@ function mod_bumplock($board, $unbumplock, $post) {
header('Location: ?/' . sprintf($config['board_path'], $board) . $config['file_index'], true, $config['redirect_http']); header('Location: ?/' . sprintf($config['board_path'], $board) . $config['file_index'], true, $config['redirect_http']);
} }
function mod_move_reply($originBoard, $postID) {
global $board, $config, $mod;
if (!openBoard($originBoard))
error($config['error']['noboard']);
if (!hasPermission($config['mod']['move'], $originBoard))
error($config['error']['noaccess']);
$query = prepare(sprintf('SELECT * FROM ``posts_%s`` WHERE `id` = :id', $originBoard));
$query->bindValue(':id', $postID);
$query->execute() or error(db_error($query));
if (!$post = $query->fetch(PDO::FETCH_ASSOC))
error($config['error']['404']);
if (isset($_POST['board'])) {
$targetBoard = $_POST['board'];
if ($_POST['target_thread']) {
$query = prepare(sprintf('SELECT * FROM ``posts_%s`` WHERE `id` = :id', $targetBoard));
$query->bindValue(':id', $_POST['target_thread']);
$query->execute() or error(db_error($query)); // If it fails, thread probably does not exist
$post['op'] = false;
$post['thread'] = $_POST['target_thread'];
}
else {
$post['op'] = true;
}
if ($post['file']) {
$post['has_file'] = true;
$post['width'] = &$post['filewidth'];
$post['height'] = &$post['fileheight'];
$file_src = sprintf($config['board_path'], $board['uri']) . $config['dir']['img'] . $post['file'];
$file_thumb = sprintf($config['board_path'], $board['uri']) . $config['dir']['thumb'] . $post['thumb'];
} else {
$post['has_file'] = false;
}
// allow thread to keep its same traits (stickied, locked, etc.)
$post['mod'] = true;
if (!openBoard($targetBoard))
error($config['error']['noboard']);
// create the new post
$newID = post($post);
if ($post['has_file']) {
// move the image
rename($file_src, sprintf($config['board_path'], $board['uri']) . $config['dir']['img'] . $post['file']);
if ($post['thumb'] != 'spoiler') { //trying to move/copy the spoiler thumb raises an error
rename($file_thumb, sprintf($config['board_path'], $board['uri']) . $config['dir']['thumb'] . $post['thumb']);
}
}
// build index
buildIndex();
// build new thread
buildThread($newID);
// trigger themes
rebuildThemes('post', $targetBoard);
// mod log
modLog("Moved post #${postID} to " . sprintf($config['board_abbreviation'], $targetBoard) . " (#${newID})", $originBoard);
// return to original board
openBoard($originBoard);
// delete original post
deletePost($postID);
buildIndex();
// open target board for redirect
openBoard($targetBoard);
// Find new thread on our target board
$query = prepare(sprintf('SELECT thread FROM ``posts_%s`` WHERE `id` = :id', $targetBoard));
$query->bindValue(':id', $newID);
$query->execute() or error(db_error($query));
$post = $query->fetch(PDO::FETCH_ASSOC);
// redirect
header('Location: ?/' . sprintf($config['board_path'], $board['uri']) . $config['dir']['res'] . sprintf($config['file_page'], $post['thread'] ? $post['thread'] : $newID) . '#' . $newID, true, $config['redirect_http']);
}
else {
$boards = listBoards();
$security_token = make_secure_link_token($originBoard . '/move_reply/' . $postID);
mod_page(_('Move reply'), 'mod/move_reply.html', array('post' => $postID, 'board' => $originBoard, 'boards' => $boards, 'token' => $security_token));
}
}
function mod_move($originBoard, $postID) { function mod_move($originBoard, $postID) {
global $board, $config, $mod, $pdo; global $board, $config, $mod, $pdo;
@ -2148,10 +2256,19 @@ function mod_config($board_config = false) {
if (!$readonly && isset($_POST['code'])) { if (!$readonly && isset($_POST['code'])) {
$code = $_POST['code']; $code = $_POST['code'];
// Save previous instance_config if php_check_syntax fails
$old_code = file_get_contents($config_file);
file_put_contents($config_file, $code); file_put_contents($config_file, $code);
$resp = shell_exec_error('php -l ' . $config_file);
if (preg_match('/No syntax errors detected/', $resp)) {
header('Location: ?/config' . ($board_config ? '/' . $board_config : ''), true, $config['redirect_http']); header('Location: ?/config' . ($board_config ? '/' . $board_config : ''), true, $config['redirect_http']);
return; return;
} }
else {
file_put_contents($config_file, $old_code);
error($config['error']['badsyntax'] . $resp);
}
}
$instance_config = @file_get_contents($config_file); $instance_config = @file_get_contents($config_file);
if ($instance_config === false) { if ($instance_config === false) {

View File

@ -1,7 +1,7 @@
<?php <?php
// Installation/upgrade file // Installation/upgrade file
define('VERSION', 'v0.9.6-dev-22'); define('VERSION', 'v0.9.6-dev-22 + <a href="https://int.vichan.net/devel/">vichan-devel-4.4.97</a>');
require 'inc/functions.php'; require 'inc/functions.php';
@ -237,8 +237,12 @@ if (file_exists($config['has_installed'])) {
query(sprintf("ALTER TABLE `posts_%s` DROP INDEX `thread`", $_board['uri'])) or error(db_error()); query(sprintf("ALTER TABLE `posts_%s` DROP INDEX `thread`", $_board['uri'])) or error(db_error());
} }
case 'v0.9.6-dev-7': case 'v0.9.6-dev-7':
case 'v0.9.6-dev-7 + <a href="https://github.com/vichan-devel/Tinyboard/">vichan-devel-4.0-gold</a>':
query("ALTER TABLE `bans` ADD `seen` BOOLEAN NOT NULL") or error(db_error()); query("ALTER TABLE `bans` ADD `seen` BOOLEAN NOT NULL") or error(db_error());
case 'v0.9.6-dev-8': case 'v0.9.6-dev-8':
case 'v0.9.6-dev-8 + <a href="https://github.com/vichan-devel/Tinyboard/">vichan-devel-4.0.1</a>':
query("CREATE TABLE IF NOT EXISTS `search_queries` ( `ip` varchar(39) NOT NULL, `time` int(11) NOT NULL, `query` text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8;") or error(db_error());
case 'v0.9.6-dev-8 + <a href="https://github.com/vichan-devel/Tinyboard/">vichan-devel-4.0.2</a>':
query("ALTER TABLE `mods` CHANGE `password` `password` CHAR( 64 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'SHA256'") or error(db_error()); query("ALTER TABLE `mods` CHANGE `password` `password` CHAR( 64 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'SHA256'") or error(db_error());
query("ALTER TABLE `mods` ADD `salt` CHAR( 32 ) NOT NULL AFTER `password`") or error(db_error()); query("ALTER TABLE `mods` ADD `salt` CHAR( 32 ) NOT NULL AFTER `password`") or error(db_error());
$query = query("SELECT `id`,`password` FROM `mods`") or error(db_error()); $query = query("SELECT `id`,`password` FROM `mods`") or error(db_error());
@ -258,6 +262,9 @@ if (file_exists($config['has_installed'])) {
} }
} }
case 'v0.9.6-dev-9': case 'v0.9.6-dev-9':
case 'v0.9.6-dev-9 + <a href="https://github.com/vichan-devel/Tinyboard/">vichan-devel-4.0.3</a>':
case 'v0.9.6-dev-9 + <a href="https://github.com/vichan-devel/Tinyboard/">vichan-devel-4.0.4-gold</a>':
case 'v0.9.6-dev-9 + <a href="https://github.com/vichan-devel/Tinyboard/">vichan-devel-4.0.5-gold</a>':
foreach ($boards as &$board) { foreach ($boards as &$board) {
__query(sprintf("ALTER TABLE `posts_%s` __query(sprintf("ALTER TABLE `posts_%s`
CHANGE `subject` `subject` VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, CHANGE `subject` `subject` VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
@ -358,6 +365,10 @@ if (file_exists($config['has_installed'])) {
query("ALTER TABLE `reports` query("ALTER TABLE `reports`
CHANGE `board` `board` VARCHAR( 58 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;") or error(db_error()); CHANGE `board` `board` VARCHAR( 58 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;") or error(db_error());
case 'v0.9.6-dev-11': case 'v0.9.6-dev-11':
case 'v0.9.6-dev-11 + <a href="https://int.vichan.net/devel/">vichan-devel-4.0.6</a>':
case 'v0.9.6-dev-11 + <a href="https://int.vichan.net/devel/">vichan-devel-4.0.7-gold</a>':
case 'v0.9.6-dev-11 + <a href="https://int.vichan.net/devel/">vichan-devel-4.0.8-gold</a>':
case 'v0.9.6-dev-11 + <a href="https://int.vichan.net/devel/">vichan-devel-4.0.9-gold</a>':
foreach ($boards as &$board) { foreach ($boards as &$board) {
__query(sprintf("ALTER TABLE ``posts_%s`` __query(sprintf("ALTER TABLE ``posts_%s``
CHANGE `thumb` `thumb` VARCHAR( 255 ) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, CHANGE `thumb` `thumb` VARCHAR( 255 ) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
@ -365,12 +376,15 @@ if (file_exists($config['has_installed'])) {
$board['uri'])) or error(db_error()); $board['uri'])) or error(db_error());
} }
case 'v0.9.6-dev-12': case 'v0.9.6-dev-12':
case 'v0.9.6-dev-12 + <a href="https://int.vichan.net/devel/">vichan-devel-4.0.10</a>':
case 'v0.9.6-dev-12 + <a href="https://int.vichan.net/devel/">vichan-devel-4.0.11-gold</a>':
foreach ($boards as &$board) { foreach ($boards as &$board) {
query(sprintf("ALTER TABLE ``posts_%s`` ADD INDEX `ip` (`ip`)", $board['uri'])) or error(db_error()); query(sprintf("ALTER TABLE ``posts_%s`` ADD INDEX `ip` (`ip`)", $board['uri'])) or error(db_error());
} }
case 'v0.9.6-dev-13': case 'v0.9.6-dev-13':
query("ALTER TABLE ``antispam`` ADD INDEX `expires` (`expires`)") or error(db_error()); query("ALTER TABLE ``antispam`` ADD INDEX `expires` (`expires`)") or error(db_error());
case 'v0.9.6-dev-14': case 'v0.9.6-dev-14':
case 'v0.9.6-dev-14 + <a href="https://int.vichan.net/devel/">vichan-devel-4.0.12</a>':
foreach ($boards as &$board) { foreach ($boards as &$board) {
query(sprintf("ALTER TABLE ``posts_%s`` query(sprintf("ALTER TABLE ``posts_%s``
DROP INDEX `body`, DROP INDEX `body`,
@ -387,6 +401,7 @@ if (file_exists($config['has_installed'])) {
ADD INDEX `list_threads` (`thread`, `sticky`, `bump`)", $board['uri'])) or error(db_error()); ADD INDEX `list_threads` (`thread`, `sticky`, `bump`)", $board['uri'])) or error(db_error());
} }
case 'v0.9.6-dev-16': case 'v0.9.6-dev-16':
case 'v0.9.6-dev-16 + <a href="https://int.vichan.net/devel/">vichan-devel-4.0.13</a>':
query("ALTER TABLE ``bans`` ADD INDEX `seen` (`seen`)") or error(db_error()); query("ALTER TABLE ``bans`` ADD INDEX `seen` (`seen`)") or error(db_error());
case 'v0.9.6-dev-17': case 'v0.9.6-dev-17':
query("ALTER TABLE ``ip_notes`` query("ALTER TABLE ``ip_notes``
@ -473,6 +488,7 @@ if (file_exists($config['has_installed'])) {
// Replace with new table // Replace with new table
query("RENAME TABLE ``bans_new_temp`` TO ``bans``") or error(db_error()); query("RENAME TABLE ``bans_new_temp`` TO ``bans``") or error(db_error());
case 'v0.9.6-dev-21': case 'v0.9.6-dev-21':
case 'v0.9.6-dev-21 + <a href="https://int.vichan.net/devel/">vichan-devel-4.4.90</a>':
__query("CREATE TABLE IF NOT EXISTS ``ban_appeals`` ( __query("CREATE TABLE IF NOT EXISTS ``ban_appeals`` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ban_id` int(10) unsigned NOT NULL, `ban_id` int(10) unsigned NOT NULL,
@ -482,6 +498,13 @@ if (file_exists($config['has_installed'])) {
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `ban_id` (`ban_id`) KEY `ban_id` (`ban_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ;") or error(db_error()); ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ;") or error(db_error());
case 'v0.9.6-dev-22':
case 'v0.9.6-dev-22 + <a href="https://int.vichan.net/devel/">vichan-devel-4.4.91</a>':
case 'v0.9.6-dev-22 + <a href="https://int.vichan.net/devel/">vichan-devel-4.4.92</a>':
case 'v0.9.6-dev-22 + <a href="https://int.vichan.net/devel/">vichan-devel-4.4.93</a>':
case 'v0.9.6-dev-22 + <a href="https://int.vichan.net/devel/">vichan-devel-4.4.94</a>':
case 'v0.9.6-dev-22 + <a href="https://int.vichan.net/devel/">vichan-devel-4.4.95</a>':
case 'v0.9.6-dev-22 + <a href="https://int.vichan.net/devel/">vichan-devel-4.4.96</a>':
case false: case false:
// Update version number // Update version number
file_write($config['has_installed'], VERSION); file_write($config['has_installed'], VERSION);

View File

@ -236,6 +236,18 @@ CREATE TABLE IF NOT EXISTS `robot` (
-- -------------------------------------------------------- -- --------------------------------------------------------
--
-- Table structure for table `search_queries`
--
CREATE TABLE IF NOT EXISTS `search_queries` (
`ip` varchar(39) NOT NULL,
`time` int(11) NOT NULL,
`query` text NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
-- --
-- Table structure for table `theme_settings` -- Table structure for table `theme_settings`
-- --

View File

@ -32,6 +32,8 @@ $(window).ready(function() {
formData.append('json_response', '1'); formData.append('json_response', '1');
formData.append('post', submit_txt); formData.append('post', submit_txt);
$(document).trigger("ajax_before_post", formData);
var updateProgress = function(e) { var updateProgress = function(e) {
var percentage; var percentage;
if (e.position === undefined) { // Firefox if (e.position === undefined) { // Firefox
@ -85,6 +87,8 @@ $(window).ready(function() {
if($('#' + id).length == 0) { if($('#' + id).length == 0) {
$(this).insertAfter($('div.post:last').next()).after('<br class="clear">'); $(this).insertAfter($('div.post:last').next()).after('<br class="clear">');
$(document).trigger('new_post', this); $(document).trigger('new_post', this);
// watch.js & auto-reload.js retrigger
setTimeout(function() { $(window).trigger("scroll"); }, 100);
} }
}); });

8
js/attention-bar.js Normal file
View File

@ -0,0 +1,8 @@
$(document).ready(function(){
$("#attention_bar").click(function(eO){ $("#attention_bar").css("display","none");
$("#attention_bar_form").css("display","block"); });
$.get(configRoot + "attentionbar.txt", function(data) {
$("#attention_bar").html(data);
$("#attention_bar_input").val($("#attention_bar").text());
});
});

View File

@ -11,10 +11,13 @@
* *
* Usage: * Usage:
* $config['additional_javascript'][] = 'js/jquery.min.js'; * $config['additional_javascript'][] = 'js/jquery.min.js';
* //$config['additional_javascript'][] = 'js/titlebar-notifications.js';
* $config['additional_javascript'][] = 'js/auto-reload.js'; * $config['additional_javascript'][] = 'js/auto-reload.js';
* *
*/ */
auto_reload_enabled = true; // for watch.js to interop
$(document).ready(function(){ $(document).ready(function(){
if($('div.banner').length == 0) if($('div.banner').length == 0)
return; // not index return; // not index
@ -26,12 +29,17 @@ $(document).ready(function(){
var end_of_page = false; var end_of_page = false;
var orig_title = document.title;
var new_posts = 0; var new_posts = 0;
var first_new_post = null; var first_new_post = null;
var update_title = function() {
document.title = (new_posts ? "("+new_posts+") " : "") + orig_title; if (typeof update_title == "undefined") {
}; var update_title = function() { };
}
if (typeof add_title_collector != "undefined")
add_title_collector(function(){
return new_posts;
});
var window_active = true; var window_active = true;
$(window).focus(function() { $(window).focus(function() {
@ -68,6 +76,7 @@ $(document).ready(function(){
recheck_activated(); recheck_activated();
} }
}); });
time_loaded = Date.now(); // interop with watch.js
} }
}); });

View File

@ -15,8 +15,13 @@
function catalog() { function catalog() {
var board = $("input[name='board']"); var board = $("input[name='board']");
if (board) { if (board.length>0) {
if (window.location.href.indexOf("/res/")==-1){ //if we are inside a thread
var catalog_url = 'catalog.html'; var catalog_url = 'catalog.html';
}
else {
var catalog_url = '../catalog.html';
}
var pages = document.getElementsByClassName('pages')[0]; var pages = document.getElementsByClassName('pages')[0];
var bottom = document.getElementsByClassName('boardlist bottom')[0] var bottom = document.getElementsByClassName('boardlist bottom')[0]
var subtitle = document.getElementsByClassName('subtitle')[0]; var subtitle = document.getElementsByClassName('subtitle')[0];
@ -25,7 +30,7 @@ var link = document.createElement('a');
link.href = catalog_url; link.href = catalog_url;
if (pages) { if (pages) {
link.textContent = 'Catalog'; link.textContent = _('Catalog');
link.style.color = '#F10000'; link.style.color = '#F10000';
link.style.padding = '4px'; link.style.padding = '4px';
link.style.paddingLeft = '9px'; link.style.paddingLeft = '9px';
@ -36,7 +41,7 @@ if (pages) {
pages.appendChild(link) pages.appendChild(link)
} }
else { else {
link.textContent = '[Catalog]'; link.textContent = '['+_('Catalog')+']';
link.style.paddingLeft = '10px'; link.style.paddingLeft = '10px';
link.style.textDecoration = "underline"; link.style.textDecoration = "underline";
document.body.insertBefore(link, bottom); document.body.insertBefore(link, bottom);
@ -44,7 +49,7 @@ else {
if (subtitle) { if (subtitle) {
var link2 = document.createElement('a'); var link2 = document.createElement('a');
link2.textContent = 'Catalog'; link2.textContent = _('Catalog');
link2.href = catalog_url; link2.href = catalog_url;
var br = document.createElement('br'); var br = document.createElement('br');
@ -53,4 +58,7 @@ if (subtitle) {
} }
} }
} }
if (active_page == 'thread' || active_page == 'index') {
$(document).ready(catalog); $(document).ready(catalog);
}

88
js/compact-boardlist.js Normal file
View File

@ -0,0 +1,88 @@
/*
* compact-boardlist.js - a compact boardlist implementation making it
* act more like a menubar
* https://github.com/vichan-devel/Tinyboard/blob/master/js/compact-boardlist.js
*
* Released under the MIT license
* Copyright (c) 2014 Marcin Łabanowski <marcin@6irc.net>
*
* Usage:
* $config['boards'] = array(
* "icon_vichan" => array('*'), # would refer to /static/icons/vichan.png
* "Regular" => array('b', 'cp', 'r+oc', 'id', 'waifu'),
* "Topical" => array('sci', "Offsite board name" => '//int.vichan.net/s/'),
* "fa_search" => array("search" => "/search.php") # would refer to a search
* # font-awesome icon
* )
*
* $config['additional_javascript'][] = 'js/jquery.min.js';
* $config['additional_javascript'][] = 'js/mobile-style.js';
* $config['additional_javascript'][] = 'js/compact-boardlist.js';
* //$config['additional_javascript'][] = 'js/watch.js';
*
*/
if (device_type == 'desktop') {
compact_boardlist = true;
do_boardlist = function() {
var categories = [];
var topbl = $('.boardlist:first');
topbl.find('>.sub').each(function() {
var cat = {name: $(this).data('description'), boards: []};
$(this).find('a').each(function() {
var board = {name: $(this).prop('title'), uri: $(this).html(), href: $(this).prop('href') }
cat.boards.push(board);
});
categories.push(cat);
});
topbl.addClass("compact-boardlist")
.html("");
for (var i in categories) {
var item = categories[i];
if (item.name.match(/^icon_/)) {
var icon = item.name.replace(/^icon_/, '')
$("<a class='cb-item cb-icon' href='"+categories[i].boards[0].href+"'><img src='/static/icons/"+icon+".png'></a>")
.appendTo(topbl)
}
else if (item.name.match(/^fa_/)) {
var icon = item.name.replace(/^fa_/, '')
$('<a class="cb-item cb-fa" href="'+categories[i].boards[0].href+'"><i class="fa-'+icon+' fa"></i></a>')
.appendTo(topbl)
}
else {
$("<a class='cb-item cb-cat' href='javascript:void(0)'>"+item.name+"</a>")
.appendTo(topbl)
.mouseenter(function() {
var list = $("<div class='boardlist top cb-menu'></div>")
.css("top", $(this).position().top + 13 + $(this).height())
.css("left", $(this).position().left)
.css("right", "auto")
.appendTo(this);
for (var j in this.item.boards) {
var board = this.item.boards[j];
var tag;
if (board.name) {
tag = $("<a href='"+board.href+"'><span>"+board.name+"</span><span class='cb-uri'>/"+board.uri+"/</span></a>")
}
else {
tag = $("<a href='"+board.href+"'><span>"+board.uri+"</span><span class='cb-uri'><i class='fa fa-globe'></i></span></a>")
}
tag
.addClass("cb-menuitem")
.appendTo(list)
}
})
.mouseleave(function() {
topbl.find(".cb-menu").remove();
})[0].item = item;
}
}
do_boardlist = undefined;
};
}

View File

@ -36,7 +36,7 @@ onready(function(){
$('.postfilename').each(do_original_filename); $('.postfilename').each(do_original_filename);
$(document).bind('new_post', function(e, post) { $(document).on('new_post', function(e, post) {
$(post).find('.postfilename').each(do_original_filename); $(post).find('.postfilename').each(do_original_filename);
}); });
}); });

View File

@ -15,6 +15,7 @@
* *
*/ */
if (active_page == 'ukko' || active_page == 'thread' || active_page == 'index')
onready(function(){ onready(function(){
$('hr:first').before('<div id="expand-all-images" style="text-align:right"><a class="unimportant" href="javascript:void(0)"></a></div>'); $('hr:first').before('<div id="expand-all-images" style="text-align:right"><a class="unimportant" href="javascript:void(0)"></a></div>');
$('div#expand-all-images a') $('div#expand-all-images a')

242
js/expand-video.js Normal file
View File

@ -0,0 +1,242 @@
/* This file is dedicated to the public domain; you may do as you wish with it. */
/* Note: This code expects the global variable configRoot to be set. */
if (typeof _ == 'undefined') {
var _ = function(a) { return a; };
}
function setupVideo(thumb, url) {
if (thumb.videoAlreadySetUp) return;
thumb.videoAlreadySetUp = true;
var video = null;
var videoContainer, videoHide;
var expanded = false;
var hovering = false;
var loop = true;
var loopControls = [document.createElement("span"), document.createElement("span")];
var fileInfo = thumb.parentNode.querySelector(".fileinfo");
var mouseDown = false;
function unexpand() {
if (expanded) {
expanded = false;
if (video.pause) video.pause();
videoContainer.style.display = "none";
thumb.style.display = "inline";
video.style.maxWidth = "inherit";
video.style.maxHeight = "inherit";
}
}
function unhover() {
if (hovering) {
hovering = false;
if (video.pause) video.pause();
videoContainer.style.display = "none";
video.style.maxWidth = "inherit";
video.style.maxHeight = "inherit";
}
}
// Create video element if does not exist yet
function getVideo() {
if (video == null) {
video = document.createElement("video");
video.src = url;
video.loop = loop;
video.innerText = _("Your browser does not support HTML5 video.");
videoHide = document.createElement("img");
videoHide.src = configRoot + "static/collapse.gif";
videoHide.alt = "[ - ]";
videoHide.title = "Collapse video";
videoHide.style.marginLeft = "-15px";
videoHide.style.cssFloat = "left";
videoHide.addEventListener("click", unexpand, false);
videoContainer = document.createElement("div");
videoContainer.style.paddingLeft = "15px";
videoContainer.style.display = "none";
videoContainer.appendChild(videoHide);
videoContainer.appendChild(video);
thumb.parentNode.insertBefore(videoContainer, thumb.nextSibling);
// Dragging to the left collapses the video
video.addEventListener("mousedown", function(e) {
if (e.button == 0) mouseDown = true;
}, false);
video.addEventListener("mouseup", function(e) {
if (e.button == 0) mouseDown = false;
}, false);
video.addEventListener("mouseenter", function(e) {
mouseDown = false;
}, false);
video.addEventListener("mouseout", function(e) {
if (mouseDown && e.clientX - video.getBoundingClientRect().left <= 0) {
unexpand();
}
mouseDown = false;
}, false);
}
}
// Clicking on thumbnail expands video
thumb.addEventListener("click", function(e) {
if (setting("videoexpand") && !e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
getVideo();
expanded = true;
hovering = false;
video.style.position = "static";
video.style.pointerEvents = "inherit";
video.style.display = "inline";
videoHide.style.display = "inline";
videoContainer.style.display = "block";
videoContainer.style.position = "static";
thumb.style.display = "none";
video.muted = (setting("videovolume") == 0);
video.volume = setting("videovolume");
video.controls = true;
if (video.readyState == 0) {
video.addEventListener("loadedmetadata", expand2, false);
} else {
setTimeout(expand2, 0);
}
video.play();
e.preventDefault();
}
}, false);
function expand2() {
video.style.maxWidth = "100%";
video.style.maxHeight = window.innerHeight + "px";
var bottom = video.getBoundingClientRect().bottom;
if (bottom > window.innerHeight) {
window.scrollBy(0, bottom - window.innerHeight);
}
// work around Firefox volume control bug
video.volume = Math.max(setting("videovolume") - 0.001, 0);
video.volume = setting("videovolume");
}
// Hovering over thumbnail displays video
thumb.addEventListener("mouseover", function(e) {
if (setting("videohover")) {
getVideo();
expanded = false;
hovering = true;
var docRight = document.documentElement.getBoundingClientRect().right;
var thumbRight = thumb.querySelector("img, video").getBoundingClientRect().right;
var maxWidth = docRight - thumbRight - 20;
if (maxWidth < 250) maxWidth = 250;
video.style.position = "fixed";
video.style.right = "0px";
video.style.top = "0px";
var docRight = document.documentElement.getBoundingClientRect().right;
var thumbRight = thumb.querySelector("img, video").getBoundingClientRect().right;
video.style.maxWidth = maxWidth + "px";
video.style.maxHeight = "100%";
video.style.pointerEvents = "none";
video.style.display = "inline";
videoHide.style.display = "none";
videoContainer.style.display = "inline";
videoContainer.style.position = "fixed";
video.muted = (setting("videovolume") == 0);
video.volume = setting("videovolume");
video.controls = false;
video.play();
}
}, false);
thumb.addEventListener("mouseout", unhover, false);
// Scroll wheel on thumbnail adjusts default volume
thumb.addEventListener("wheel", function(e) {
if (setting("videohover")) {
var volume = setting("videovolume");
if (e.deltaY > 0) volume -= 0.1;
if (e.deltaY < 0) volume += 0.1;
if (volume < 0) volume = 0;
if (volume > 1) volume = 1;
if (video != null) {
video.muted = (volume == 0);
video.volume = volume;
}
changeSetting("videovolume", volume);
e.preventDefault();
}
}, false);
// [play once] vs [loop] controls
function setupLoopControl(i) {
loopControls[i].addEventListener("click", function(e) {
loop = (i != 0);
thumb.href = thumb.href.replace(/([\?&])loop=\d+/, "$1loop=" + i);
if (video != null) {
video.loop = loop;
if (loop && video.currentTime >= video.duration) {
video.currentTime = 0;
}
}
loopControls[i].style.fontWeight = "bold";
loopControls[1-i].style.fontWeight = "inherit";
}, false);
}
loopControls[0].textContent = _("[play once]");
loopControls[1].textContent = _("[loop]");
loopControls[1].style.fontWeight = "bold";
for (var i = 0; i < 2; i++) {
setupLoopControl(i);
loopControls[i].style.whiteSpace = "nowrap";
fileInfo.appendChild(document.createTextNode(" "));
fileInfo.appendChild(loopControls[i]);
}
}
function setupVideosIn(element) {
var thumbs = element.querySelectorAll("a.file");
for (var i = 0; i < thumbs.length; i++) {
if (/\.webm$/.test(thumbs[i].pathname)) {
setupVideo(thumbs[i], thumbs[i].href);
} else {
var m = thumbs[i].search.match(/\bv=([^&]*)/);
if (m != null) {
var url = decodeURIComponent(m[1]);
if (/\.webm$/.test(url)) setupVideo(thumbs[i], url);
}
}
}
}
onready(function(){
// Insert menu from settings.js
if (typeof settingsMenu != "undefined") document.body.insertBefore(settingsMenu, document.getElementsByTagName("hr")[0]);
// Setup Javascript events for videos in document now
setupVideosIn(document);
// Setup Javascript events for videos added by updater
if (window.MutationObserver) {
var observer = new MutationObserver(function(mutations) {
for (var i = 0; i < mutations.length; i++) {
var additions = mutations[i].addedNodes;
if (additions == null) continue;
for (var j = 0; j < additions.length; j++) {
var node = additions[j];
if (node.nodeType == 1) {
setupVideosIn(node);
}
}
}
});
observer.observe(document.body, {childList: true, subtree: true});
}
});

View File

@ -14,9 +14,8 @@
*/ */
$(document).ready(function(){ $(document).ready(function(){
if($('div.banner').length != 0) if($('span.omitted').length == 0)
return; // not index return; // nothing to expand
$('div.post.op span.omitted').each(function() {
var do_expand = function() { var do_expand = function() {
$(this) $(this)
@ -58,7 +57,7 @@ $(document).ready(function(){
$('div.post.op span.omitted').each(do_expand); $('div.post.op span.omitted').each(do_expand);
$(document).bind("new_post", function(e, post) { $(document).on("new_post", function(e, post) {
if (!$(post).hasClass("reply")) { if (!$(post).hasClass("reply")) {
$(post).find('div.post.op span.omitted').each(do_expand); $(post).find('div.post.op span.omitted').each(do_expand);
} }

View File

@ -12,6 +12,7 @@
* *
*/ */
if (active_page == 'ukko' || active_page == 'thread' || active_page == 'index')
$(document).ready(function() { $(document).ready(function() {
var force_anon = function() { var force_anon = function() {
if($(this).children('a.capcode').length == 0) { if($(this).children('a.capcode').length == 0) {
@ -78,7 +79,7 @@ $(document).ready(function() {
if(forced_anon) if(forced_anon)
enable_fa(); enable_fa();
$(document).bind('new_post', function(e, post) { $(document).on('new_post', function(e, post) {
if(forced_anon) if(forced_anon)
$(post).find('p.intro label').each(force_anon); $(post).find('p.intro label').each(force_anon);
}); });

View File

@ -84,7 +84,7 @@ $(document).ready(function(){
$('div.post > a > img.post-image, div > a > img.post-image').each(handle_images); $('div.post > a > img.post-image, div > a > img.post-image').each(handle_images);
$(document).bind('new_post', function(e, post) { $(document).on('new_post', function(e, post) {
$(post).find('> a > img.post-image').each(handle_images); $(post).find('> a > img.post-image').each(handle_images);
}); });
}); });

View File

@ -4,6 +4,7 @@
* *
* Released under the MIT license * Released under the MIT license
* Copyright (c) 2013 Michael Save <savetheinternet@tinyboard.org> * Copyright (c) 2013 Michael Save <savetheinternet@tinyboard.org>
* Copyright (c) 2013-2014 Marcin Łabanowski <marcin@6irc.net>
* *
* Usage: * Usage:
* $config['additional_javascript'][] = 'js/jquery.min.js'; * $config['additional_javascript'][] = 'js/jquery.min.js';
@ -12,11 +13,9 @@
*/ */
$(document).ready(function(){ $(document).ready(function(){
if($('div.banner').length != 0) if (active_page != "index" && active_page != "ukko")
return; // not index return; // not index
var board = $('form input[name="board"]').val().toString();
if (!localStorage.hiddenthreads) if (!localStorage.hiddenthreads)
localStorage.hiddenthreads = '{}'; localStorage.hiddenthreads = '{}';
@ -37,20 +36,25 @@ $(document).ready(function(){
} }
} }
if (!hidden_data[board]) { var fields_to_hide = 'div.post,div.video-container,video,img,p.fileinfo,a.hide-thread-link,br';
hidden_data[board] = {}; // id : timestamp
}
var do_hide_threads = function() { var do_hide_threads = function() {
var id = $(this).children('p.intro').children('a.post_no:eq(1)').text(); var id = $(this).children('p.intro').children('a.post_no:eq(1)').text();
var thread_container = $(this).parent(); var thread_container = $(this).parent();
var board = thread_container.data("board");
if (!hidden_data[board]) {
hidden_data[board] = {}; // id : timestamp
}
$('<a class="hide-thread-link" style="float:left;margin-right:5px" href="javascript:void(0)">[]</a><span> </span>') $('<a class="hide-thread-link" style="float:left;margin-right:5px" href="javascript:void(0)">[]</a><span> </span>')
.insertBefore(thread_container.find(':not(h2,h2 *):first')) .insertBefore(thread_container.find(':not(h2,h2 *):first'))
.click(function() { .click(function() {
hidden_data[board][id] = Math.round(Date.now() / 1000); hidden_data[board][id] = Math.round(Date.now() / 1000);
store_data(); store_data();
thread_container.find('div.post,div.video-container,img,p.fileinfo,a.hide-thread-link,br').hide(); thread_container.find(fields_to_hide).hide();
var hidden_div = thread_container.find('div.post.op > p.intro').clone(); var hidden_div = thread_container.find('div.post.op > p.intro').clone();
hidden_div.addClass('thread-hidden'); hidden_div.addClass('thread-hidden');
@ -63,7 +67,7 @@ $(document).ready(function(){
.click(function() { .click(function() {
delete hidden_data[board][id]; delete hidden_data[board][id];
store_data(); store_data();
thread_container.find('div.post,div.video-container,img,p.fileinfo,a.hide-thread-link,br').show(); thread_container.find(fields_to_hide).show();
$(this).remove(); $(this).remove();
hidden_div.remove(); hidden_div.remove();
}); });
@ -76,7 +80,7 @@ $(document).ready(function(){
$('div.post.op').each(do_hide_threads); $('div.post.op').each(do_hide_threads);
$(document).bind('new_post', function(e, post) { $(document).on('new_post', function(e, post) {
do_hide_threads.call($(post).find('div.post.op')[0]); do_hide_threads.call($(post).find('div.post.op')[0]);
}); });
}); });

View File

@ -0,0 +1,33 @@
/*
* inline-expanding-filename.js
* Binds image filename link to expanding, to make kusaba x users somewhat more accustomed.
* https://github.com/vichan-devel/Tinyboard/blob/master/js/inline-expanding.js
*
* Released under the MIT license
* Copyright (c) 2012-2013 Marcin Łabanowski <marcin@6irc.net>
*
* Usage:
* $config['additional_javascript'][] = 'js/jquery.min.js';
* $config['additional_javascript'][] = 'js/inline-expanding.js';
* $config['additional_javascript'][] = 'js/inline-expanding-filename.js';
*
*/
onready(function(){
var inline_expanding_filename = function() {
$(this).find(".fileinfo > a").click(function(){
var imagelink = $(this).parent().parent().find('a[target="_blank"]:first');
if(imagelink.length > 0) {
imagelink.click();
return false;
}
});
};
$('div[id^="thread_"]').each(inline_expanding_filename);
// allow to work with auto-reload.js, etc.
$(document).on('new_post', function(e, post) {
inline_expanding_filename.call(post);
});
});

View File

@ -57,11 +57,10 @@ onready(function(){
$('div[id^="thread_"]').each(inline_expand_post); $('div[id^="thread_"]').each(inline_expand_post);
// allow to work with auto-reload.js, etc. // allow to work with auto-reload.js, etc.
$(document).bind('new_post', function(e, post) { $(document).on('new_post', function(e, post) {
inline_expand_post.call(post); inline_expand_post.call(post);
}); });
} else { } else {
inline_expand_post.call(document); inline_expand_post.call(document);
} }
}); });

File diff suppressed because one or more lines are too long

8
js/jquery.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -8,6 +8,7 @@
* *
* Usage: * Usage:
* // $config['additional_javascript'][] = 'js/jquery.min.js'; * // $config['additional_javascript'][] = 'js/jquery.min.js';
* // $config['additional_javascript'][] = 'js/strftime.min.js';
* $config['additional_javascript'][] = 'js/local-time.js'; * $config['additional_javascript'][] = 'js/local-time.js';
* *
*/ */
@ -24,6 +25,27 @@ onready(function(){
return [Math.pow(10, count - num.toString().length), num].join('').substr(1); return [Math.pow(10, count - num.toString().length), num].join('').substr(1);
}; };
var datelocale =
{ days: [_('Sunday'), _('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday')]
, shortDays: [_("Sun"), _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat")]
, months: [_('January'), _('February'), _('March'), _('April'), _('May'), _('June'), _('July'), _('August'), _('September'), _('October'), _('November'), _('December')]
, shortMonths: [_('Jan'), _('Feb'), _('Mar'), _('Apr'), _('May'), _('Jun'), _('Jul'), _('Aug'), _('Sep'), _('Oct'), _('Nov'), _('Dec')]
, AM: _('AM')
, PM: _('PM')
, am: _('am')
, pm: _('pm')
};
var dateformat = (typeof strftime === 'undefined') ? function(t) {
return zeropad(t.getMonth() + 1, 2) + "/" + zeropad(t.getDate(), 2) + "/" + t.getFullYear().toString().substring(2) +
" (" + [_("Sun"), _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun")][t.getDay()] + ") " +
// time
zeropad(t.getHours(), 2) + ":" + zeropad(t.getMinutes(), 2) + ":" + zeropad(t.getSeconds(), 2);
} : function(t) {
// post_date is defined in templates/main.js
return strftime(window.post_date, t, datelocale);
};
var do_localtime = function(elem) { var do_localtime = function(elem) {
var times = elem.getElementsByTagName('time'); var times = elem.getElementsByTagName('time');
@ -35,12 +57,7 @@ onready(function(){
times[i].setAttribute('data-local', 'true'); times[i].setAttribute('data-local', 'true');
times[i].innerHTML = times[i].innerHTML = dateformat(t);
// date
zeropad(t.getMonth() + 1, 2) + "/" + zeropad(t.getDate(), 2) + "/" + t.getFullYear().toString().substring(2) +
" (" + [_("Sun"), _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun")][t.getDay()] + ") " +
// time
zeropad(t.getHours(), 2) + ":" + zeropad(t.getMinutes(), 2) + ":" + zeropad(t.getSeconds(), 2);
}; };
}; };
@ -48,7 +65,7 @@ onready(function(){
if (window.jQuery) { if (window.jQuery) {
// allow to work with auto-reload.js, etc. // allow to work with auto-reload.js, etc.
$(document).bind('new_post', function(e, post) { $(document).on('new_post', function(e, post) {
do_localtime(post); do_localtime(post);
}); });
} }

21
js/mobile-style.js Normal file
View File

@ -0,0 +1,21 @@
/*
* mobile-style.js - adds some responsiveness to Tinyboard
* https://github.com/vichan-devel/Tinyboard/blob/master/js/mobile-style.js
*
* Released under the MIT license
* Copyright (c) 2014 Marcin Łabanowski <marcin@6irc.net>
*
* Usage:
* $config['api']['enabled'] = true;
* $config['additional_javascript'][] = 'js/jquery.min.js';
* $config['additional_javascript'][] = 'js/mobile-style.js';
*/
if(navigator.userAgent.match(/iPhone|iPod|iPad|Android|Opera Mini|Blackberry|PlayBook|Windows Phone|Tablet PC|Windows CE|IEMobile/i)) {
$('html').addClass("mobile-style");
device_type = "mobile";
}
else {
$('html').addClass("desktop-style");
device_type = "desktop";
}

1
js/post-hider.js Symbolic link
View File

@ -0,0 +1 @@
hide-threads.js

View File

@ -19,19 +19,21 @@ onready(function(){
var $link = $(this); var $link = $(this);
var id; var id;
var matches;
if(id = $link.text().match(/^>>(\d+)$/)) { if ($link.is('[data-thread]')) {
id = id[1]; id = $link.attr('data-thread');
} else { }
else if(matches = $link.text().match(/^>>(?:>\/([^\/]+)\/)?(\d+)$/)) {
id = matches[2];
}
else {
return; return;
} }
var board = $(this); var board = $(this);
var i = 0;
while (board.data('board') === undefined) { while (board.data('board') === undefined) {
board = board.parent(); board = board.parent();
i++;
if (i >= 10) return;
} }
var threadid; var threadid;
if ($link.is('[data-thread]')) threadid = 0; if ($link.is('[data-thread]')) threadid = 0;
@ -52,30 +54,37 @@ onready(function(){
hovered_at = {'x': e.pageX, 'y': e.pageY}; hovered_at = {'x': e.pageX, 'y': e.pageY};
var start_hover = function($link) { var start_hover = function($link) {
if($post.is(':visible') && if($.contains($post[0], $link[0])) {
// link links to itself or to op; ignore
}
else if($post.is(':visible') &&
$post.offset().top + $post.height() >= $(window).scrollTop() && $post.offset().top + $post.height() >= $(window).scrollTop() &&
$post.offset().top <= $(window).scrollTop() + $(window).height() $post.offset().top <= $(window).scrollTop() + $(window).height()) {
) {
// post is in view // post is in view
$post.attr('style', 'border-style: none dashed dashed none; background: ' + $post.css('border-right-color')); $post.addClass('highlighted');
} else { } else {
var $newPost = $post.clone(); var $newPost = $post.clone();
$newPost.find('>.reply, >br').remove();
$newPost.find('span.mentioned').remove(); $newPost.find('span.mentioned').remove();
$newPost $newPost
.attr('id', 'post-hover-' + id) .attr('id', 'post-hover-' + id)
.attr('data-board', board)
.addClass('post-hover') .addClass('post-hover')
.css('position', 'absolute')
.css('border-style', 'solid') .css('border-style', 'solid')
.css('box-shadow', '1px 1px 1px #999') .css('box-shadow', '1px 1px 1px #999')
.css('display', 'block') .css('display', 'block')
.css('position', 'absolute')
.css('font-style', 'normal')
.css('z-index', '100') .css('z-index', '100')
.addClass('reply').addClass('post') .addClass('reply').addClass('post')
.insertAfter($link.parent()) .insertAfter($link.parent())
$link.trigger('mousemove'); $link.trigger('mousemove');
} }
}; };
$post = $('div.post#reply_' + id); $post = $('[data-board="' + board + '"] div.post#reply_' + id + ', [data-board="' + board + '"]div#thread_' + id);
if($post.length > 0) { if($post.length > 0) {
start_hover($(this)); start_hover($(this));
} else { } else {
@ -90,15 +99,28 @@ onready(function(){
url: url, url: url,
context: document.body, context: document.body,
success: function(data) { success: function(data) {
var mythreadid = $(data).find('div[id^="thread_"]').attr('id').replace("thread_", "");
if (mythreadid == threadid && parentboard == board) {
$(data).find('div.post.reply').each(function() { $(data).find('div.post.reply').each(function() {
// Not 100% sure that this doesn't break shit: if($('[data-board="' + board + '"] #' + $(this).attr('id')).length == 0) {
$(document).trigger('new_post', this); $('[data-board="' + board + '"]#thread_' + threadid + " .post.reply:first").before($(this).hide().addClass('hidden'));
}
if($('#' + $(this).attr('id')).length == 0)
$('body').prepend($(this).css('display', 'none').addClass('hidden'));
}); });
}
else if ($('[data-board="' + board + '"]#thread_'+mythreadid).length > 0) {
$(data).find('div.post.reply').each(function() {
if($('[data-board="' + board + '"] #' + $(this).attr('id')).length == 0) {
$('[data-board="' + board + '"]#thread_' + mythreadid + " .post.reply:first").before($(this).hide().addClass('hidden'));
}
});
}
else {
$(data).find('div[id^="thread_"]').hide().attr('data-cached', 'yes').prependTo('form[name="postcontrols"]');
}
$post = $('[data-board="' + board + '"] div.post#reply_' + id + ', [data-board="' + board + '"]div#thread_' + id);
$post = $('div.post#reply_' + id);
if(hovering && $post.length > 0) { if(hovering && $post.length > 0) {
start_hover($link); start_hover($link);
} }
@ -110,24 +132,29 @@ onready(function(){
if(!$post) if(!$post)
return; return;
$post.attr('style', ''); $post.removeClass('highlighted');
if($post.hasClass('hidden')) if($post.hasClass('hidden') || $post.data('cached') == 'yes')
$post.css('display', 'none'); $post.css('display', 'none');
$('.post-hover').remove(); $('.post-hover').remove();
}).mousemove(function(e) { }).mousemove(function(e) {
if(!$post) if(!$post)
return; return;
var $hover = $('#post-hover-' + id); var $hover = $('#post-hover-' + id + '[data-board="' + board + '"]');
if($hover.length == 0) if($hover.length == 0)
return; return;
var top = (e.pageY ? e.pageY : hovered_at['y']) - 10; var scrollTop = $(window).scrollTop();
if ($link.is("[data-thread]")) scrollTop = 0;
var epy = e.pageY;
if ($link.is("[data-thread]")) epy -= $(window).scrollTop();
if(e.pageY < $(window).scrollTop() + 15) { var top = (epy ? epy : hovered_at['y']) - 10;
top = $(window).scrollTop();
} else if(e.pageY > $(window).scrollTop() + $(window).height() - $hover.height() - 15) { if(epy < scrollTop + 15) {
top = $(window).scrollTop() + $(window).height() - $hover.height() - 15; top = scrollTop;
} else if(epy > scrollTop + $(window).height() - $hover.height() - 15) {
top = scrollTop + $(window).height() - $hover.height() - 15;
} }
@ -138,7 +165,7 @@ onready(function(){
$('div.body a:not([rel="nofollow"])').each(init_hover); $('div.body a:not([rel="nofollow"])').each(init_hover);
// allow to work with auto-reload.js, etc. // allow to work with auto-reload.js, etc.
$(document).bind('new_post', function(e, post) { $(document).on('new_post', function(e, post) {
$(post).find('div.body a:not([rel="nofollow"])').each(init_hover); $(post).find('div.body a:not([rel="nofollow"])').each(init_hover);
}); });
}); });

View File

@ -83,7 +83,7 @@ $(document).ready(function(){
$('div.post input[type=checkbox].delete').each(init_qpc); $('div.post input[type=checkbox].delete').each(init_qpc);
$(document).bind('new_post', function(e, post) { $(document).on('new_post', function(e, post) {
$(post).find('input[type=checkbox].delete').each(init_qpc); $(post).find('input[type=checkbox].delete').each(init_qpc);
}); });
}); });

View File

@ -14,6 +14,7 @@
* *
*/ */
if (active_page == 'index') {
$(document).ready(function(){ $(document).ready(function(){
if($('div.banner').length != 0) if($('div.banner').length != 0)
return; // not index return; // not index
@ -45,4 +46,4 @@ $(document).ready(function(){
}); });
}); });
}); });
}

View File

@ -36,6 +36,7 @@
display: block;\ display: block;\
padding: 0 0 0 0;\ padding: 0 0 0 0;\
width: 300px;\ width: 300px;\
z-index: 100;\
}\ }\
#quick-reply table {\ #quick-reply table {\
border-collapse: collapse;\ border-collapse: collapse;\
@ -217,13 +218,16 @@
if ($td.find('input[name="file_url"]').length) { if ($td.find('input[name="file_url"]').length) {
$file_url = $td.find('input[name="file_url"]'); $file_url = $td.find('input[name="file_url"]');
if (settings.get('show_remote', false)) {
// Make a new row for it // Make a new row for it
var $newRow = $('<tr><td colspan="2"></td></tr>'); var $newRow = $('<tr><td colspan="2"></td></tr>');
$file_url.clone().attr('placeholder', _('Upload URL')).appendTo($newRow.find('td')); $file_url.clone().attr('placeholder', _('Upload URL')).appendTo($newRow.find('td'));
$file_url.parent().remove();
$newRow.insertBefore(this); $newRow.insertBefore(this);
}
$file_url.parent().remove();
$td.find('label').remove(); $td.find('label').remove();
$td.contents().filter(function() { $td.contents().filter(function() {
@ -237,6 +241,11 @@
} }
} }
// Disable embedding if configured so
if (!settings.get('show_embed', false) && $td.find('input[name="embed"]').length) {
$(this).remove();
}
// Remove oekaki if existent // Remove oekaki if existent
if ($(this).is('#oekaki')) { if ($(this).is('#oekaki')) {
$(this).remove(); $(this).remove();
@ -285,10 +294,10 @@
$origPostForm = $('form[name="post"]:first'); $origPostForm = $('form[name="post"]:first');
// Synchronise body text with original post form // Synchronise body text with original post form
$origPostForm.find('textarea[name="body"]').bind('change input propertychange', function() { $origPostForm.find('textarea[name="body"]').on('change input propertychange', function() {
$postForm.find('textarea[name="body"]').val($(this).val()); $postForm.find('textarea[name="body"]').val($(this).val());
}); });
$postForm.find('textarea[name="body"]').bind('change input propertychange', function() { $postForm.find('textarea[name="body"]').on('change input propertychange', function() {
$origPostForm.find('textarea[name="body"]').val($(this).val()); $origPostForm.find('textarea[name="body"]').val($(this).val());
}); });
$postForm.find('textarea[name="body"]').focus(function() { $postForm.find('textarea[name="body"]').focus(function() {
@ -300,10 +309,10 @@
$(this).attr('id', 'body'); $(this).attr('id', 'body');
}); });
// Synchronise other inputs // Synchronise other inputs
$origPostForm.find('input[type="text"],select').bind('change input propertychange', function() { $origPostForm.find('input[type="text"],select').on('change input propertychange', function() {
$postForm.find('[name="' + $(this).attr('name') + '"]').val($(this).val()); $postForm.find('[name="' + $(this).attr('name') + '"]').val($(this).val());
}); });
$postForm.find('input[type="text"],select').bind('change input propertychange', function() { $postForm.find('input[type="text"],select').on('change input propertychange', function() {
$origPostForm.find('[name="' + $(this).attr('name') + '"]').val($(this).val()); $origPostForm.find('[name="' + $(this).attr('name') + '"]').val($(this).val());
}); });

View File

@ -43,3 +43,11 @@ tb_settings['ajax'] = {
// Always act as if "noko" was typed when posting replies with the ajax script // Always act as if "noko" was typed when posting replies with the ajax script
always_noko_replies: false always_noko_replies: false
}; };
// wpaint.js
tb_settings['wpaint'] = {
// Canvas width
width: 500,
// Canvas height
height: 250
};

View File

@ -48,7 +48,7 @@ onready(function(){
$('div.post.reply').each(showBackLinks); $('div.post.reply').each(showBackLinks);
$(document).bind('new_post', function(e, post) { $(document).on('new_post', function(e, post) {
if ($(post).hasClass("reply")) { if ($(post).hasClass("reply")) {
showBackLinks.call(post); showBackLinks.call(post);
} }

View File

@ -40,7 +40,7 @@ $(document).ready(function(){
$('div.post.reply').each(showOPLinks); $('div.post.reply').each(showOPLinks);
// allow to work with auto-reload.js, etc. // allow to work with auto-reload.js, etc.
$(document).bind('new_post', function(e, post) { $(document).on('new_post', function(e, post) {
$(post).each(showOPLinks); $(post).each(showOPLinks);
}); });
}); });

View File

@ -7,18 +7,28 @@
* Copyright (c) 2013-2014 Marcin Łabanowski <marcin@6irc.net> * Copyright (c) 2013-2014 Marcin Łabanowski <marcin@6irc.net>
* *
* Usage: * Usage:
* $config['additional_javascript'][] = 'js/mobile-style.js';
* $config['additional_javascript'][] = 'js/smartphone-spoiler.js'; * $config['additional_javascript'][] = 'js/smartphone-spoiler.js';
* *
*/ */
onready(function(){ onready(function(){
if(navigator.userAgent.match(/iPhone|iPod|iPad|Android|Opera Mini|Blackberry|PlayBook|Windows Phone|Tablet PC|Windows CE|IEMobile/i)) { if(device_type == 'mobile') {
var spoilers = document.getElementsByClassName('spoiler'); var fix_spoilers = function(where) {
var spoilers = where.getElementsByClassName('spoiler');
for(var i = 0; i < spoilers.length; i++) { for(var i = 0; i < spoilers.length; i++) {
spoilers[i].onmousedown = function() { spoilers[i].onmousedown = function() {
this.style.color = 'white'; this.style.color = 'white';
}; };
} }
};
fix_spoilers(document);
// allow to work with auto-reload.js, etc.
$(document).on('new_post', function(e, post) {
fix_spoilers(post);
});
} }
}); });

8
js/strftime.min.js vendored Normal file
View File

@ -0,0 +1,8 @@
(function(){function i(c,a,b){return g(c,a,b)}function g(c,a,b,j){j=j||{};a&&!n(a)&&(b=a,a=void 0);a=a||new Date;b=b||o;b.formats=b.formats||{};var i=a.getTime(),h=j.timezone,e=typeof h;if(j.utc||e=="number"||e=="string")a=p(a);if(h){if(e=="string")var k=h[0]=="-"?-1:1,q=parseInt(h.slice(1,3),10),r=parseInt(h.slice(3,5),10),h=k*60*q+r;e&&(a=new Date(a.getTime()+h*6E4))}return c.replace(/%([-_0]?.)/g,function(c,e){var d;if(e.length==2){d=e[0];if(d=="-")d="";else if(d=="_")d=" ";else if(d=="0")d="0";
else return c;e=e[1]}switch(e){case "A":return b.days[a.getDay()];case "a":return b.shortDays[a.getDay()];case "B":return b.months[a.getMonth()];case "b":return b.shortMonths[a.getMonth()];case "C":return f(Math.floor(a.getFullYear()/100),d);case "D":return g(b.formats.D||"%m/%d/%y",a,b);case "d":return f(a.getDate(),d);case "e":return a.getDate();case "F":return g(b.formats.F||"%Y-%m-%d",a,b);case "H":return f(a.getHours(),d);case "h":return b.shortMonths[a.getMonth()];case "I":return f(l(a),d);
case "j":return d=new Date(a.getFullYear(),0,1),d=Math.ceil((a.getTime()-d.getTime())/864E5),f(d,3);case "k":return f(a.getHours(),d==null?" ":d);case "L":return f(Math.floor(i%1E3),3);case "l":return f(l(a),d==null?" ":d);case "M":return f(a.getMinutes(),d);case "m":return f(a.getMonth()+1,d);case "n":return"\n";case "o":return String(a.getDate())+s(a.getDate());case "P":return a.getHours()<12?b.am:b.pm;case "p":return a.getHours()<12?b.AM:b.PM;case "R":return g(b.formats.R||"%H:%M",a,b);case "r":return g(b.formats.r||
"%I:%M:%S %p",a,b);case "S":return f(a.getSeconds(),d);case "s":return Math.floor(i/1E3);case "T":return g(b.formats.T||"%H:%M:%S",a,b);case "t":return"\t";case "U":return f(m(a,"sunday"),d);case "u":return d=a.getDay(),d==0?7:d;case "v":return g(b.formats.v||"%e-%b-%Y",a,b);case "W":return f(m(a,"monday"),d);case "w":return a.getDay();case "Y":return a.getFullYear();case "y":return d=String(a.getFullYear()),d.slice(d.length-2);case "Z":return j.utc?"GMT":(d=a.toString().match(/\((\w+)\)/))&&d[1]||
"";case "z":return j.utc?"+0000":(d=typeof h=="number"?h:-a.getTimezoneOffset(),(d<0?"-":"+")+f(Math.abs(d/60))+f(d%60));default:return e}})}function p(c){var a=(c.getTimezoneOffset()||0)*6E4;return new Date(c.getTime()+a)}function n(c){for(var a=0,b=k.length,a=0;a<b;++a)if(typeof c[k[a]]!="function")return!1;return!0}function f(c,a,b){typeof a==="number"&&(b=a,a="0");a==null&&(a="0");b=b||2;c=String(c);if(a)for(;c.length<b;)c=a+c;return c}function l(c){c=c.getHours();c==0?c=12:c>12&&(c-=12);return c}
function s(c){var a=c%10;c%=100;if(c>=11&&c<=13||a===0||a>=4)return"th";switch(a){case 1:return"st";case 2:return"nd";case 3:return"rd"}}function m(c,a){var a=a||"sunday",b=c.getDay();a=="monday"&&(b==0?b=6:b--);var e=new Date(c.getFullYear(),0,1);return Math.floor(((c-e)/864E5+7-b)/7)}var e;e=typeof module!=="undefined"?module.exports=i:function(){return this||(0,eval)("this")}();var o={days:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),shortDays:"Sun Mon Tue Wed Thu Fri Sat".split(" "),
months:"January February March April May June July August September October November December".split(" "),shortMonths:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),AM:"AM",PM:"PM",am:"am",pm:"pm"};e.strftime=i;e.strftimeTZ=i.strftimeTZ=function(c,a,b,e){if((typeof b=="number"||typeof b=="string")&&e==null)e=b,b=void 0;return g(c,a,b,{timezone:e})};e.strftimeUTC=i.strftimeUTC=function(c,a,b){return g(c,a,b,{utc:!0})};e.localizedStrftime=i.localizedStrftime=function(c){return function(a,
b){return g(a,b,c)}};var k=["getTime","getTimezoneOffset","getDay","getDate","getMonth","getFullYear","getYear","getHours","getMinutes","getSeconds"]})();

View File

@ -0,0 +1,32 @@
/*
* titlebar-notifications.js - a library for showing number of new events in titlebar
* https://github.com/vichan-devel/Tinyboard/blob/master/js/titlebar-notifications.js
*
* Released under the MIT license
* Copyright (c) 2014 Marcin Łabanowski <marcin@6irc.net>
*
* Usage:
* $config['additional_javascript'][] = 'js/titlebar-notifications.js';
* //$config['additional_javascript'][] = 'js/auto-reload.js';
* //$config['additional_javascript'][] = 'js/watch.js';
*
*/
var orig_title = document.title;
$(function(){
orig_title = document.title;
});
update_title = function() {
var updates = 0;
for(var i in title_collectors) {
updates += title_collectors[i]();
}
document.title = (updates ? "("+updates+") " : "") + orig_title;
};
var title_collectors = [];
add_title_collector = function(f) {
title_collectors.push(f);
};

View File

@ -76,7 +76,7 @@ $(document).ready(function(){
show_hide_hide_images_buttons(); show_hide_hide_images_buttons();
} }
$(document).bind('new_post', function(e, post) { $(document).on('new_post', function(e, post) {
if (hide_images) { if (hide_images) {
$(post).find('img.post-image').each(hideImage); $(post).find('img.post-image').each(hideImage);
} }

View File

@ -11,6 +11,7 @@
* *
*/ */
if (active_page == 'ukko' || active_page == 'index')
$(document).ready(function(){ $(document).ready(function(){
if($('div.banner').length != 0) if($('div.banner').length != 0)
return; // not index return; // not index
@ -60,7 +61,7 @@ $(document).ready(function(){
hideLockedThread(getThreadFromIcon($(this))); hideLockedThread(getThreadFromIcon($(this)));
}); });
} }
$(document).bind('new_post', function(e, post) { $(document).on('new_post', function(e, post) {
if (hide_locked_threads) { if (hide_locked_threads) {
$(post).find('img.icon[title="Locked"], i.fa-lock.fa').each(function() { $(post).find('img.icon[title="Locked"], i.fa-lock.fa').each(function() {
hideLockedThread(getThreadFromIcon($(this))); hideLockedThread(getThreadFromIcon($(this)));

77
js/upload-selection.js Normal file
View File

@ -0,0 +1,77 @@
/*
* upload-selection.js - makes upload fields in post form more compact
* https://github.com/vichan-devel/Tinyboard/blob/master/js/upload-selection.js
*
* Released under the MIT license
* Copyright (c) 2014 Marcin Łabanowski <marcin@6irc.net>
*
* Usage:
* $config['additional_javascript'][] = 'js/jquery.min.js';
* //$config['additional_javascript'][] = 'js/wpaint.js';
* $config['additional_javascript'][] = 'js/upload-selection.js';
*
*/
$(function(){
var enabled_file = true;
var enabled_url = $("#upload_url").length > 0;
var enabled_embed = $("#upload_embed").length > 0;
var enabled_oekaki = typeof window.oekaki != "undefined";
var disable_all = function() {
$("#upload").hide();
$("#upload_file").hide();
$("#upload_url").hide();
$("#upload_embed").hide();
if (enabled_oekaki) {
if (window.oekaki.initialized) {
window.oekaki.deinit();
}
}
};
enable_file = function() {
disable_all();
$("#upload").show();
$("#upload_file").show();
};
enable_url = function() {
disable_all();
$("#upload").show();
$("#upload_url").show();
$('label[for="file_url"]').html(_("URL"));
};
enable_embed = function() {
disable_all();
$("#upload_embed").show();
};
enable_oekaki = function() {
disable_all();
window.oekaki.init();
};
if (enabled_url || enabled_embed || enabled_oekaki) {
$("<tr><th>"+_("Select")+"</th><td id='upload_selection'></td></tr>").insertBefore("#upload");
var my_html = "<a href='javascript:void(0)' onclick='enable_file(); return false;'>"+_("File")+"</a>";
if (enabled_url) {
my_html += " / <a href='javascript:void(0)' onclick='enable_url(); return false;'>"+_("Remote")+"</a>";
}
if (enabled_embed) {
my_html += " / <a href='javascript:void(0)' onclick='enable_embed(); return false;'>"+_("Embed")+"</a>";
}
if (enabled_oekaki) {
my_html += " / <a href='javascript:void(0)' onclick='enable_oekaki(); return false;'>"+_("Oekaki")+"</a>";
$("#confirm_oekaki_label").hide();
}
$("#upload_selection").html(my_html);
enable_file();
}
});

1
js/wPaint Submodule

@ -0,0 +1 @@
Subproject commit 2c272dffca0f3d7b7163bd82ba15629f54409278

421
js/watch.js Normal file
View File

@ -0,0 +1,421 @@
/*
* watch.js - board watch, thread watch and board pinning
* https://github.com/vichan-devel/Tinyboard/blob/master/js/watch.js
*
* Released under the MIT license
* Copyright (c) 2014 Marcin Łabanowski <marcin@6irc.net>
*
* Usage:
* $config['api']['enabled'] = true;
* $config['additional_javascript'][] = 'js/jquery.min.js';
* $config['additional_javascript'][] = 'js/mobile-style.js';
* //$config['additional_javascript'][] = 'js/titlebar-notifications.js';
* //$config['additional_javascript'][] = 'js/auto-reload.js';
* //$config['additional_javascript'][] = 'js/hide-threads.js';
* //$config['additional_javascript'][] = 'js/compact-boardlist.js';
* $config['additional_javascript'][] = 'js/watch.js';
*
*/
$(function(){
// migrate from old name
if (typeof localStorage.watch == "string") {
localStorage.watch_js = localStorage.watch;
delete localStorage.watch;
}
var window_active = true;
$(window).focus(function() {
window_active = true;
$(window).trigger('scroll');
});
$(window).blur(function() {
window_active = false;
});
var status = {};
time_loaded = Date.now();
var updating_suspended = false;
var storage = function() {
var storage = JSON.parse(localStorage.watch_js !== undefined ? localStorage.watch_js : "{}");
delete storage.undefined; // fix for some bug
return storage;
};
var storage_save = function(s) {
localStorage.watch_js = JSON.stringify(s);
};
var osize = function(o) {
var size = 0;
for (var key in o) {
if (o.hasOwnProperty(key)) size++;
}
return size;
};
var is_pinned = function(boardconfig) {
return boardconfig.pinned || boardconfig.watched || (boardconfig.threads ? osize(boardconfig.threads) : false);
};
var is_boardwatched = function(boardconfig) {
return boardconfig.watched;
};
var is_threadwatched = function(boardconfig, thread) {
return boardconfig && boardconfig.threads && boardconfig.threads[thread];
};
var toggle_pinned = function(board) {
var st = storage();
var bc = st[board] || {};
if (is_pinned(bc)) {
bc.pinned = false;
bc.watched = false;
bc.threads = {};
}
else {
bc.pinned = true;
}
st[board] = bc;
storage_save(st);
return bc.pinned;
};
var toggle_boardwatched = function(board) {
var st = storage();
var bc = st[board] || {};
bc.watched = !is_boardwatched(bc) && Date.now();
st[board] = bc;
storage_save(st);
return bc.watched;
};
var toggle_threadwatched = function(board, thread) {
var st = storage();
var bc = st[board] || {};
if (is_threadwatched(bc, thread)) {
delete bc.threads[thread];
}
else {
bc.threads = bc.threads || {};
bc.threads[thread] = Date.now();
}
st[board] = bc;
storage_save(st);
return is_threadwatched(bc, thread);
};
var construct_watchlist_for = function(board, variant) {
var list = $("<div class='boardlist top cb-menu watch-menu'></div>");
list.attr("data-board", board);
for (var tid in storage()[board].threads) {
var newposts = "(0)";
if (status && status[board] && status[board].threads && status[board].threads[tid]) {
if (status[board].threads[tid] == -404) {
newposts = "<i class='fa fa-ban-circle'></i>";
}
else {
newposts = "("+status[board].threads[tid]+")";
}
}
var tag;
if (variant == 'desktop') {
tag = $("<a href='"+modRoot+board+"/res/"+tid+".html'><span>#"+tid+"</span><span class='cb-uri watch-remove'>"+newposts+"</span>");
tag.find(".watch-remove").mouseenter(function() {
this.oldval = $(this).html();
$(this).css("min-width", $(this).width());
$(this).html("<i class='fa fa-minus'></i>");
})
.mouseleave(function() {
$(this).html(this.oldval);
})
}
else if (variant == 'mobile') {
tag = $("<a href='"+modRoot+board+"/res/"+tid+".html'><span>#"+tid+"</span><span class='cb-uri'>"+newposts+"</span>"
+"<span class='cb-uri watch-remove'><i class='fa fa-minus'></i></span>");
}
tag.attr('data-thread', tid)
.addClass("cb-menuitem")
.appendTo(list)
.find(".watch-remove")
.click(function() {
var b = $(this).parent().parent().attr("data-board");
var t = $(this).parent().attr("data-thread");
toggle_threadwatched(b, t);
$(this).parent().parent().parent().mouseleave();
$(this).parent().remove();
return false;
});
}
return list;
};
var update_pinned = function() {
if (typeof update_title != "undefined") update_title();
var bl = $('.boardlist').first();
$('#watch-pinned, .watch-menu').remove();
var pinned = $('<div id="watch-pinned"></div>').appendTo(bl);
var st = storage();
for (var i in st) {
if (is_pinned(st[i])) {
var link;
if (bl.find('[href*="'+modRoot+i+'/index.html"]:not(.cb-menuitem)').length) link = bl.find('[href*="'+modRoot+i+'/"]').first();
else link = $('<a href="'+modRoot+i+'/" class="cb-item cb-cat">/'+i+'/</a>').appendTo(pinned);
if (link[0].origtitle === undefined) {
link[0].origtitle = link.html();
}
else {
link.html(link[0].origtitle);
}
if (st[i].watched) {
link.css("font-weight", "bold");
if (status && status[i] && status[i].new_threads) {
link.html(link.html() + " (" + status[i].new_threads + ")");
}
}
else if (st[i].threads && osize(st[i].threads)) {
link.css("font-style", "italic");
link.attr("data-board", i);
if (status && status[i] && status[i].threads) {
var new_posts = 0;
for (var tid in status[i].threads) {
if (status[i].threads[tid] > 0) {
new_posts += status[i].threads[tid];
}
}
if (new_posts > 0) {
link.html(link.html() + " (" + new_posts + ")");
}
}
if (device_type == "desktop")
link.off().mouseenter(function() {
updating_suspended = true;
$('.cb-menu').remove();
var board = $(this).attr("data-board");
var wl = construct_watchlist_for(board, "desktop").appendTo($(this))
.css("top", $(this).position().top
+ ($(this).css('padding-top').replace('px', '')|0)
+ ($(this).css('padding-bottom').replace('px', '')|0)
+ $(this).height())
.css("left", $(this).position().left)
.css("right", "auto")
.css("font-style", "normal");
if (typeof init_hover != "undefined")
wl.find("a.cb-menuitem").each(init_hover);
}).mouseleave(function() {
updating_suspended = false;
$('.boardlist .cb-menu').remove();
});
}
}
}
if (device_type == "mobile" && (active_page == 'thread' || active_page == 'index')) {
var board = $('form[name="post"] input[name="board"]').val();
var where = $('div[style="text-align:right"]').first();
$('.watch-menu').remove();
construct_watchlist_for(board, "mobile").css("float", "left").insertBefore(where);
}
};
var fetch_jsons = function() {
if (updating_suspended) return;
if (window_active) check_scroll();
var st = storage();
for (var i in st) {
if (st[i].watched) {
var r = $.getJSON(configRoot+i+"/threads.json", function(j, x, r) {
handle_board_json(r.board, j);
});
r.board = i;
}
else if (st[i].threads) {
for (var j in st[i].threads) {
var r = $.getJSON(configRoot+i+"/res/"+j+".json", function(k, x, r) {
handle_thread_json(r.board, r.thread, k);
}).error(function(r) {
if(r.status == 404) handle_thread_404(r.board, r.thread);
});
r.board = i;
r.thread = j;
}
}
}
};
var handle_board_json = function(board, json) {
var last_thread;
var new_threads = 0;
var hidden_data = {};
if (localStorage.hiddenthreads) {
hidden_data = JSON.parse(localStorage.hiddenthreads);
}
for (var i in json) {
for (var j in json[i].threads) {
var thread = json[i].threads[j];
if (hidden_data[board]) { // hide threads integration
var cont = false;
for (var k in hidden_data[board]) {
if (parseInt(k) == thread.no) {
cont = true;
break;
}
}
if (cont) continue;
}
if (thread.last_modified > storage()[board].watched / 1000) {
last_thread = thread.no;
new_threads++;
}
}
}
status = status || {};
status[board] = status[board] || {};
status[board].last_thread = last_thread;
status[board].new_threads = new_threads;
update_pinned();
};
var handle_thread_json = function(board, threadid, json) {
for (var i in json.posts) {
var post = json.posts[i];
var new_posts = 0;
if (post.time > storage()[board].threads[threadid] / 1000) {
new_posts++;
}
status = status || {};
status[board] = status[board] || {};
status[board].threads = status[board].threads || {};
status[board].threads[threadid] = new_posts;
update_pinned();
}
};
var handle_thread_404 = function(board, threadid) {
status = status || {};
status[board] = status[board] || {};
status[board].threads = status[board].threads || {};
status[board].threads[threadid] = -404; //notify 404
update_pinned();
};
if (active_page == "thread") {
var board = $('form[name="post"] input[name="board"]').val();
var thread = $('form[name="post"] input[name="thread"]').val();
var boardconfig = storage()[board] || {};
$('hr:first').before('<div id="watch-thread" style="text-align:right"><a class="unimportant" href="javascript:void(0)">-</a></div>');
$('#watch-thread a').html(is_threadwatched(boardconfig, thread) ? _("Stop watching this thread") : _("Watch this thread")).click(function() {
$(this).html(toggle_threadwatched(board, thread) ? _("Stop watching this thread") : _("Watch this thread"));
update_pinned();
});
}
if (active_page == "index") {
var board = $('form[name="post"] input[name="board"]').val();
var boardconfig = storage()[board] || {};
$('hr:first').before('<div id="watch-pin" style="text-align:right"><a class="unimportant" href="javascript:void(0)">-</a></div>');
$('#watch-pin a').html(is_pinned(boardconfig) ? _("Unpin this board") : _("Pin this board")).click(function() {
$(this).html(toggle_pinned(board) ? _("Unpin this board") : _("Pin this board"));
$('#watch-board a').html(is_boardwatched(boardconfig) ? _("Stop watching this board") : _("Watch this board"));
update_pinned();
});
$('hr:first').before('<div id="watch-board" style="text-align:right"><a class="unimportant" href="javascript:void(0)">-</a></div>');
$('#watch-board a').html(is_boardwatched(boardconfig) ? _("Stop watching this board") : _("Watch this board")).click(function() {
$(this).html(toggle_boardwatched(board) ? _("Stop watching this board") : _("Watch this board"));
$('#watch-pin a').html(is_pinned(boardconfig) ? _("Unpin this board") : _("Pin this board"));
update_pinned();
});
}
var check_post = function(frame, post) {
return post.length && $(frame).scrollTop() + $(frame).height() >=
post.position().top + post.height();
}
var check_scroll = function() {
if (!status) return;
var refresh = false;
for(var bid in status) {
if (((status[bid].new_threads && (active_page == "ukko" || active_page == "index")) || status[bid].new_threads == 1)
&& check_post(this, $('[data-board="'+bid+'"]#thread_'+status[bid].last_thread))) {
var st = storage()
st[bid].watched = time_loaded;
storage_save(st);
refresh = true;
}
if (!status[bid].threads) continue;
for (var tid in status[bid].threads) {
if(status[bid].threads[tid] && check_post(this, $('[data-board="'+bid+'"]#thread_'+tid))) {
var st = storage();
st[bid].threads[tid] = time_loaded;
storage_save(st);
refresh = true;
}
}
}
return refresh;
};
$(window).scroll(function() {
var refresh = check_scroll();
if (refresh) {
fetch_jsons();
refresh = false;
}
});
if (typeof add_title_collector != "undefined")
add_title_collector(function() {
if (!status) return 0;
var sum = 0;
for (var bid in status) {
if (status[bid].new_threads) {
sum += status[bid].new_threads;
if (!status[bid].threads) continue;
for (var tid in status[bid].threads) {
if (status[bid].threads[tid] > 0) {
if (auto_reload_enabled && active_page == "thread") {
var board = $('form[name="post"] input[name="board"]').val();
var thread = $('form[name="post"] input[name="thread"]').val();
if (board == bid && thread == tid) continue;
}
sum += status[bid].threads[tid];
}
}
}
}
return sum;
});
update_pinned();
fetch_jsons();
setInterval(fetch_jsons, 10000);
});

87
js/webm-settings.js Normal file
View File

@ -0,0 +1,87 @@
/* This file is dedicated to the public domain; you may do as you wish with it. */
if (typeof _ == 'undefined') {
var _ = function(a) { return a; };
}
// Default settings
var defaultSettings = {
"videoexpand": true,
"videohover": false,
"videovolume": 1.0
};
// Non-persistent settings for when localStorage is absent/disabled
var tempSettings = {};
// Scripts obtain settings by calling this function
function setting(name) {
if (localStorage) {
if (localStorage[name] === undefined) return defaultSettings[name];
return JSON.parse(localStorage[name]);
} else {
if (tempSettings[name] === undefined) return defaultSettings[name];
return tempSettings[name];
}
}
// Settings should be changed with this function
function changeSetting(name, value) {
if (localStorage) {
localStorage[name] = JSON.stringify(value);
} else {
tempSettings[name] = value;
}
}
// Create settings menu
var settingsMenu = document.createElement("div");
settingsMenu.style.textAlign = "right";
settingsMenu.style.background = "inherit";
settingsMenu.innerHTML = '<a class="unimportant" href="javascript:void(0)"><span>'+_('WebM Settings')+'</span></a>'
+ '<div style="display: none; text-align: left; position: absolute; right: 1em; margin-left: -999em; margin-top: -1px; padding-top: 1px; background: inherit;">'
+ '<label><input type="checkbox" name="videoexpand">'+_('Expand videos inline')+'</label><br>'
+ '<label><input type="checkbox" name="videohover">'+_('Play videos on hover')+'</label><br>'
+ '<label><input type="range" name="videovolume" min="0" max="1" step="0.01" style="width: 4em; height: 1ex; vertical-align: middle; margin: 0px;">'+_('Default volume')+'</label><br>'
+ '</div>';
function refreshSettings() {
var settingsItems = settingsMenu.getElementsByTagName("input");
for (var i = 0; i < settingsItems.length; i++) {
var control = settingsItems[i];
if (control.type == "checkbox") {
control.checked = setting(control.name);
} else if (control.type == "range") {
control.value = setting(control.name);
}
}
}
function setupControl(control) {
if (control.addEventListener) control.addEventListener("change", function(e) {
if (control.type == "checkbox") {
changeSetting(control.name, control.checked);
} else if (control.type == "range") {
changeSetting(control.name, control.value);
}
}, false);
}
refreshSettings();
var settingsItems = settingsMenu.getElementsByTagName("input");
for (var i = 0; i < settingsItems.length; i++) {
setupControl(settingsItems[i]);
}
if (settingsMenu.addEventListener) {
settingsMenu.addEventListener("mouseover", function(e) {
refreshSettings();
settingsMenu.getElementsByTagName("span")[0].style.fontWeight = "bold";
settingsMenu.getElementsByTagName("div")[0].style.display = "block";
}, false);
settingsMenu.addEventListener("mouseout", function(e) {
settingsMenu.getElementsByTagName("span")[0].style.fontWeight = "normal";
settingsMenu.getElementsByTagName("div")[0].style.display = "none";
}, false);
}

28
js/webm/playersettings.js Normal file
View File

@ -0,0 +1,28 @@
/* This file is dedicated to the public domain; you may do as you wish with it. */
if (window.addEventListener) window.addEventListener("load", function(e) {
document.getElementById("playerheader").appendChild(settingsMenu);
var video = document.getElementsByTagName("video")[0];
var loopLinks = [document.getElementById("loop0"), document.getElementById("loop1")];
function setupLoopLink(i) {
loopLinks[i].addEventListener("click", function(e) {
if (!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
video.loop = (i != 0);
if (i != 0 && video.currentTime >= video.duration) {
video.currentTime = 0;
}
loopLinks[i].style.fontWeight = "bold";
loopLinks[1-i].style.fontWeight = "inherit";
e.preventDefault();
}
}, false);
}
for (var i = 0; i < 2; i++) {
setupLoopLink(i);
}
video.muted = (setting("videovolume") == 0);
video.volume = setting("videovolume");
video.play();
}, false);

134
js/wpaint.js Normal file
View File

@ -0,0 +1,134 @@
/*
* wpaint.js - wPaint integration javascript
* https://github.com/vichan-devel/Tinyboard/blob/master/js/wpaint.js
*
* Released under the MIT license
* Copyright (c) 2014 Marcin Łabanowski <marcin@6irc.net>
*
* Contains parts of old oekaki code:
* Copyright (c) 2013 copypaste <wizardchan@hush.com>
* Copyright (c) 2013-2014 Marcin Łabanowski <marcin@6irc.net>
*
* Usage:
* $config['additional_javascript'][] = 'js/jquery.min.js';
* $config['additional_javascript'][] = 'js/jquery-ui.custom.min.js';
* $config['additional_javascript'][] = 'js/ajax.js';
* $config['additional_javascript'][] = 'js/wPaint/lib/wColorPicker.min.js';
* $config['additional_javascript'][] = 'js/wPaint/wPaint.min.js';
* $config['additional_javascript'][] = 'js/wPaint/plugins/main/wPaint.menu.main.min.js';
* $config['additional_javascript'][] = 'js/wPaint/plugins/text/wPaint.menu.text.min.js';
* $config['additional_javascript'][] = 'js/wPaint/plugins/shapes/wPaint.menu.main.shapes.min.js';
* $config['additional_javascript'][] = 'js/wPaint/plugins/file/wPaint.menu.main.file.min.js';
* $config['additional_javascript'][] = 'js/wpaint.js';
* $config['additional_javascript'][] = 'js/upload-selection.js';
*
*/
window.oekaki = (function(){
"use strict";
var oekaki = {};
oekaki.settings = new script_settings('wpaint');
oekaki.height = oekaki.settings.get("height", 250);
oekaki.width = oekaki.settings.get("width", 500);
function dataURItoBlob(dataURI) {
var binary = atob(dataURI.split(',')[1]);
var array = new Array(binary.length);
for(var i = 0; i < binary.length; i++) {
array[i] = binary.charCodeAt(i);
}
return new Blob([new Uint8Array(array)], {type: 'image/jpeg'});
}
oekaki.do_css = function() {
}
oekaki.init = function() {
var oekaki_form = '<tr id="oekaki"><th>Oekaki</th><td><div id="wpaintctr"><div id="wpaintdiv"></div></div></td></tr>';
// Add oekaki after the file input
$('form[name="post"]:not(#quick-reply) input[type="file"]').parent().parent().after(oekaki_form);
$('<link class="wpaintcss" rel="stylesheet" href="'+configRoot+'js/wPaint/wPaint.min.css" />').appendTo($("head"));
$('<link class="wpaintcss" rel="stylesheet" href="'+configRoot+'js/wPaint/lib/wColorPicker.min.css" />').appendTo($("head"));
$('<link class="wpaintcss" rel="stylesheet" href="'+configRoot+'stylesheets/jquery-ui/core.css" />').appendTo($("head"));
$('<link class="wpaintcss" rel="stylesheet" href="'+configRoot+'stylesheets/jquery-ui/resizable.css" />').appendTo($("head"));
$('<link class="wpaintcss" rel="stylesheet" href="'+configRoot+'stylesheets/jquery-ui/theme.css" />').appendTo($("head"));
var initcount = 0;
$('.wpaintcss').one('load', function() {
initcount++;
if (initcount == 5) {
$.extend($.fn.wPaint.defaults, {
mode: 'pencil', // set mode
lineWidth: '1', // starting line width
fillStyle: '#FFFFFF', // starting fill style
strokeStyle: '#000000', // start stroke style
});
delete $.fn.wPaint.menus.main.items.save;
$('#wpaintdiv').wPaint({
path: configRoot+'js/wPaint/',
menuOffsetTop: -46,
bg: "#ffffff",
loadImgFg: oekaki.load_img,
loadImgBg: oekaki.load_img
});
$("#wpaintctr").resizable({
stop: function(event,ui) {
$("#wpaintdiv").wPaint("resize");
},
alsoResize: "#wpaintdiv, #wpaintdiv canvas",
});
$('#wpaintctr .ui-resizable-se').css({'height':'12px', 'width':'12px'});
}
});
$("#wpaintdiv").width(oekaki.width).height(oekaki.height).css("position", "relative");
$("#wpaintctr").width(oekaki.width+5).height(oekaki.height+5).css("padding-top", 48).css("position", "relative");
$(document).on("ajax_before_post.wpaint", function(e, postData) {
var blob = $('#wpaintdiv').wPaint("image");
blob = dataURItoBlob(blob);
postData.append("file", blob, "Oekaki.png");
});
$(window).on('stylesheet', function() {
oekaki.do_css();
if ($('link#stylesheet').attr('href')) {
$('link#stylesheet')[0].onload = oekaki.do_css;
}
});
oekaki.initialized = true;
};
oekaki.load_img = function() {
alert(_("Click on any image on this site to load it into oekaki applet"));
$('img').one('click.loadimg', function(e) {
$('img').off('click.loadimg');
e.stopImmediatePropagation();
e.preventDefault();
var url = $(this).prop('src');
$('#wpaintdiv').wPaint('setBg', url);
return false;
});
};
oekaki.deinit = function() {
$('#oekaki, .wpaintcss').remove();
$(document).off("ajax_before_post.wpaint");
oekaki.initialized = false;
};
oekaki.initialized = false;
return oekaki;
})();

View File

@ -16,8 +16,7 @@
* $config['embedding'] = array(); * $config['embedding'] = array();
* $config['embedding'][0] = array( * $config['embedding'][0] = array(
* '/^https?:\/\/(\w+\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9\-_]{10,11})(&.+)?$/i', * '/^https?:\/\/(\w+\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9\-_]{10,11})(&.+)?$/i',
* '<div class="video-container" data-video="$2"><a href="$0" target="_blank" class="file"><img style="width:360px;height:270px;" src="//img.youtube.com/vi/$2/0.jpg" class="post-image"/></a></div>' * $config['youtube_js_html']);
);
* $config['additional_javascript'][] = 'js/jquery.min.js'; * $config['additional_javascript'][] = 'js/jquery.min.js';
* $config['additional_javascript'][] = 'js/youtube.js'; * $config['additional_javascript'][] = 'js/youtube.js';
* *
@ -29,7 +28,9 @@ onready(function(){
$('div.video-container a', tag).click(function() { $('div.video-container a', tag).click(function() {
var videoID = $(this.parentNode).data('video'); var videoID = $(this.parentNode).data('video');
$(this.parentNode).html('<iframe style="float:left;margin: 10px 20px" type="text/html" width="360" height="270" src="//www.youtube.com/embed/' + videoID + '?autoplay=1" frameborder="0"/>'); $(this.parentNode).html('<iframe style="float:left;margin: 10px 20px" type="text/html" '+
'width="360" height="270" src="//www.youtube.com/embed/' + videoID +
'?autoplay=1&html5=1" allowfullscreen frameborder="0"/>');
return false; return false;
}); });
@ -37,7 +38,7 @@ onready(function(){
do_embed_yt(document); do_embed_yt(document);
// allow to work with auto-reload.js, etc. // allow to work with auto-reload.js, etc.
$(document).bind('new_post', function(e, post) { $(document).on('new_post', function(e, post) {
do_embed_yt(post); do_embed_yt(post);
}); });
}); });

View File

@ -1,7 +1,7 @@
<?php <?php
/* /*
* Copyright (c) 2010-2013 Tinyboard Development Group * Copyright (c) 2010-2014 Tinyboard Development Group
*/ */
require 'inc/functions.php'; require 'inc/functions.php';
@ -72,6 +72,7 @@ $pages = array(
'/(\%b)/ban(&delete)?/(\d+)' => 'secure_POST ban_post', // ban poster '/(\%b)/ban(&delete)?/(\d+)' => 'secure_POST ban_post', // ban poster
'/(\%b)/move/(\d+)' => 'secure_POST move', // move thread '/(\%b)/move/(\d+)' => 'secure_POST move', // move thread
'/(\%b)/move_reply/(\d+)' => 'secure_POST move_reply', // move reply
'/(\%b)/edit(_raw)?/(\d+)' => 'secure_POST edit_post', // edit post '/(\%b)/edit(_raw)?/(\d+)' => 'secure_POST edit_post', // edit post
'/(\%b)/delete/(\d+)' => 'secure delete', // delete post '/(\%b)/delete/(\d+)' => 'secure delete', // delete post
'/(\%b)/deletefile/(\d+)' => 'secure deletefile', // delete file from post '/(\%b)/deletefile/(\d+)' => 'secure deletefile', // delete file from post
@ -99,6 +100,8 @@ $pages = array(
'/(\%b)/' => 'view_board', '/(\%b)/' => 'view_board',
'/(\%b)/' . preg_quote($config['file_index'], '!') => 'view_board', '/(\%b)/' . preg_quote($config['file_index'], '!') => 'view_board',
'/(\%b)/' . str_replace('%d', '(\d+)', preg_quote($config['file_page'], '!')) => 'view_board', '/(\%b)/' . str_replace('%d', '(\d+)', preg_quote($config['file_page'], '!')) => 'view_board',
'/(\%b)/' . preg_quote($config['dir']['res'], '!') .
str_replace('%d', '(\d+)', preg_quote($config['file_page50'], '!')) => 'view_thread50',
'/(\%b)/' . preg_quote($config['dir']['res'], '!') . '/(\%b)/' . preg_quote($config['dir']['res'], '!') .
str_replace('%d', '(\d+)', preg_quote($config['file_page'], '!')) => 'view_thread', str_replace('%d', '(\d+)', preg_quote($config['file_page'], '!')) => 'view_thread',
); );

25
player.php Normal file
View File

@ -0,0 +1,25 @@
<?php
/* This file is dedicated to the public domain; you may do as you wish with it. */
$params = '?v=' . urlencode($_GET['v']) . '&amp;t=' . urlencode($_GET['t']);
$loop = ($_GET['loop'] != "0");
?><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title><?php echo htmlspecialchars($_GET['t']); ?></title>
<link rel="stylesheet" href="stylesheets/webm/playerstyle.css">
<script src="js/webm-settings.js"></script>
<script src="js/webm/playersettings.js"></script>
</head>
<body>
<div id="playerheader">
<a id="loop0" href="<?php echo $params; ?>&amp;loop=0"<?php if (!$loop) echo ' style="font-weight: bold"'; ?>>[play once]</a>
<a id="loop1" href="<?php echo $params; ?>&amp;loop=1"<?php if ($loop) echo ' style="font-weight: bold"'; ?>>[loop]</a>
</div>
<div id="playercontent">
<video controls<?php if ($loop) echo ' loop'; ?> src="<?php echo htmlspecialchars($_GET['v']); ?>">
Your browser does not support HTML5 video. <a href="<?php echo htmlspecialchars($_GET['v']); ?>">[Download]</a>
</video>
</div>
</body>
</html>

View File

@ -1,9 +1,8 @@
<?php <?php
/* /*
* Copyright (c) 2010-2013 Tinyboard Development Group * Copyright (c) 2010-2014 Tinyboard Development Group
*/ */
//
require 'inc/functions.php'; require 'inc/functions.php';
require 'inc/anti-bot.php'; require 'inc/anti-bot.php';
@ -181,7 +180,7 @@ if (isset($_POST['delete'])) {
// Check the referrer // Check the referrer
if ($config['referer_match'] !== false && if ($config['referer_match'] !== false &&
(!isset($_SERVER['HTTP_REFERER']) || !preg_match($config['referer_match'], urldecode($_SERVER['HTTP_REFERER'])))) (!isset($_SERVER['HTTP_REFERER']) || !preg_match($config['referer_match'], rawurldecode($_SERVER['HTTP_REFERER']))))
error($config['error']['referer']); error($config['error']['referer']);
checkDNSBL(); checkDNSBL();
@ -401,10 +400,14 @@ if (isset($_POST['delete'])) {
$post['name'] = $trip[0]; $post['name'] = $trip[0];
$post['trip'] = isset($trip[1]) ? $trip[1] : ''; $post['trip'] = isset($trip[1]) ? $trip[1] : '';
$noko = false;
if (strtolower($post['email']) == 'noko') { if (strtolower($post['email']) == 'noko') {
$noko = true; $noko = true;
$post['email'] = ''; $post['email'] = '';
} else $noko = false; } elseif (strtolower($post['email']) == 'nonoko'){
$noko = false;
$post['email'] = '';
} else $noko = $config['always_noko'];
if ($post['has_file']) { if ($post['has_file']) {
$post['extension'] = strtolower(mb_substr($post['filename'], mb_strrpos($post['filename'], '.') + 1)); $post['extension'] = strtolower(mb_substr($post['filename'], mb_strrpos($post['filename'], '.') + 1));
@ -445,13 +448,25 @@ if (isset($_POST['delete'])) {
} }
if ($config['country_flags']) { if ($config['country_flags']) {
if (!geoip_db_avail(GEOIP_COUNTRY_EDITION)) { require 'inc/lib/geoip/geoip.inc';
error('GeoIP not available: ' . geoip_db_filename(GEOIP_COUNTRY_EDITION)); $gi=geoip\geoip_open('inc/lib/geoip/GeoIPv6.dat', GEOIP_STANDARD);
function ipv4to6($ip) {
if (strpos($ip, ':') !== false) {
if (strpos($ip, '.') > 0)
$ip = substr($ip, strrpos($ip, ':')+1);
else return $ip; //native ipv6
} }
if ($country_code = @geoip_country_code_by_name($_SERVER['REMOTE_ADDR'])) { $iparr = array_pad(explode('.', $ip), 4, 0);
$part7 = base_convert(($iparr[0] * 256) + $iparr[1], 10, 16);
$part8 = base_convert(($iparr[2] * 256) + $iparr[3], 10, 16);
return '::ffff:'.$part7.':'.$part8;
}
if ($country_code = geoip\geoip_country_code_by_addr_v6($gi, ipv4to6($_SERVER['REMOTE_ADDR']))) {
if (!in_array(strtolower($country_code), array('eu', 'ap', 'o1', 'a1', 'a2'))) if (!in_array(strtolower($country_code), array('eu', 'ap', 'o1', 'a1', 'a2')))
$post['body'] .= "\n<tinyboard flag>".strtolower($country_code)."</tinyboard>". $post['body'] .= "\n<tinyboard flag>".strtolower($country_code)."</tinyboard>".
"\n<tinyboard flag alt>" . @geoip_country_name_by_name($_SERVER['REMOTE_ADDR']) . "</tinyboard>"; "\n<tinyboard flag alt>".geoip\geoip_country_name_by_addr_v6($gi, ipv4to6($_SERVER['REMOTE_ADDR']))."</tinyboard>";
} }
} }
@ -736,9 +751,23 @@ if (isset($_POST['delete'])) {
$root = $post['mod'] ? $config['root'] . $config['file_mod'] . '?/' : $config['root']; $root = $post['mod'] ? $config['root'] . $config['file_mod'] . '?/' : $config['root'];
if ($config['always_noko'] || $noko) { if ($noko) {
$redirect = $root . $board['dir'] . $config['dir']['res'] . $redirect = $root . $board['dir'] . $config['dir']['res'] .
sprintf($config['file_page'], $post['op'] ? $id:$post['thread']) . (!$post['op'] ? '#' . $id : ''); sprintf($config['file_page'], $post['op'] ? $id:$post['thread']) . (!$post['op'] ? '#' . $id : '');
if (!$post['op'] && isset($_SERVER['HTTP_REFERER'])) {
$regex = array(
'board' => str_replace('%s', '(\w{1,8})', preg_quote($config['board_path'], '/')),
'page' => str_replace('%d', '(\d+)', preg_quote($config['file_page'], '/')),
'page50' => str_replace('%d', '(\d+)', preg_quote($config['file_page50'], '/')),
'res' => preg_quote($config['dir']['res'], '/'),
);
if (preg_match('/\/' . $regex['board'] . $regex['res'] . $regex['page50'] . '([?&].*)?$/', $_SERVER['HTTP_REFERER'])) {
$redirect = $root . $board['dir'] . $config['dir']['res'] .
sprintf($config['file_page50'], $post['op'] ? $id:$post['thread']) . (!$post['op'] ? '#' . $id : '');
}
}
} else { } else {
$redirect = $root . $board['dir'] . $config['file_index']; $redirect = $root . $board['dir'] . $config['file_index'];
@ -748,6 +777,8 @@ if (isset($_POST['delete'])) {
_syslog(LOG_INFO, 'New post: /' . $board['dir'] . $config['dir']['res'] . _syslog(LOG_INFO, 'New post: /' . $board['dir'] . $config['dir']['res'] .
sprintf($config['file_page'], $post['op'] ? $id : $post['thread']) . (!$post['op'] ? '#' . $id : '')); sprintf($config['file_page'], $post['op'] ? $id : $post['thread']) . (!$post['op'] ? '#' . $id : ''));
if (!$post['mod']) header('X-Associated-Content: "' . $redirect . '"');
if ($post['op']) if ($post['op'])
rebuildThemes('post-thread', $board['uri']); rebuildThemes('post-thread', $board['uri']);
else else
@ -759,7 +790,7 @@ if (isset($_POST['delete'])) {
header('Content-Type: text/json; charset=utf-8'); header('Content-Type: text/json; charset=utf-8');
echo json_encode(array( echo json_encode(array(
'redirect' => $redirect, 'redirect' => $redirect,
'noko' => $config['always_noko'] || $noko, 'noko' => $noko,
'id' => $id 'id' => $id
)); ));
} }

170
search.php Normal file
View File

@ -0,0 +1,170 @@
<?php
require 'inc/functions.php';
if (!$config['search']['enable']) {
die(_("Post search is disabled"));
}
$queries_per_minutes = $config['search']['queries_per_minutes'];
$queries_per_minutes_all = $config['search']['queries_per_minutes_all'];
$search_limit = $config['search']['search_limit'];
$boards = $config['search']['boards'];
$body = Element('search_form.html', Array('boards' => $boards, 'board' => isset($_GET['board']) ? $_GET['board'] : false, 'search' => isset($_GET['search']) ? str_replace('"', '&quot;', utf8tohtml($_GET['search'])) : false));
if(isset($_GET['search']) && !empty($_GET['search']) && isset($_GET['board']) && in_array($_GET['board'], $boards)) {
$phrase = $_GET['search'];
$_body = '';
$query = prepare("SELECT COUNT(*) FROM ``search_queries`` WHERE `ip` = :ip AND `time` > :time");
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']);
$query->bindValue(':time', time() - ($queries_per_minutes[1] * 60));
$query->execute() or error(db_error($query));
if($query->fetchColumn() > $queries_per_minutes[0])
error(_('Wait a while before searching again, please.'));
$query = prepare("SELECT COUNT(*) FROM ``search_queries`` WHERE `time` > :time");
$query->bindValue(':time', time() - ($queries_per_minutes_all[1] * 60));
$query->execute() or error(db_error($query));
if($query->fetchColumn() > $queries_per_minutes_all[0])
error(_('Wait a while before searching again, please.'));
$query = prepare("INSERT INTO ``search_queries`` VALUES (:ip, :time, :query)");
$query->bindValue(':ip', $_SERVER['REMOTE_ADDR']);
$query->bindValue(':time', time());
$query->bindValue(':query', $phrase);
$query->execute() or error(db_error($query));
_syslog(LOG_NOTICE, 'Searched /' . $_GET['board'] . '/ for "' . $phrase . '"');
// Cleanup search queries table
$query = prepare("DELETE FROM ``search_queries`` WHERE `time` <= :time");
$query->bindValue(':time', time() - ($queries_per_minutes_all[1] * 60));
$query->execute() or error(db_error($query));
openBoard($_GET['board']);
$filters = Array();
function search_filters($m) {
global $filters;
$name = $m[2];
$value = isset($m[4]) ? $m[4] : $m[3];
if(!in_array($name, array('id', 'thread', 'subject', 'name'))) {
// unknown filter
return $m[0];
}
$filters[$name] = $value;
return $m[1];
}
$phrase = trim(preg_replace_callback('/(^|\s)(\w+):("(.*)?"|[^\s]*)/', 'search_filters', $phrase));
if(!preg_match('/[^*^\s]/', $phrase) && empty($filters)) {
_syslog(LOG_WARNING, 'Query too broad.');
$body .= '<p class="unimportant" style="text-align:center">(Query too broad.)</p>';
echo Element('page.html', Array(
'config'=>$config,
'title'=>'Search',
'body'=>$body,
));
exit;
}
// Escape escape character
$phrase = str_replace('!', '!!', $phrase);
// Remove SQL wildcard
$phrase = str_replace('%', '!%', $phrase);
// Use asterisk as wildcard to suit convention
$phrase = str_replace('*', '%', $phrase);
// Remove `, it's used by table prefix magic
$phrase = str_replace('`', '!`', $phrase);
$like = '';
$match = Array();
// Find exact phrases
if(preg_match_all('/"(.+?)"/', $phrase, $m)) {
foreach($m[1] as &$quote) {
$phrase = str_replace("\"{$quote}\"", '', $phrase);
$match[] = $pdo->quote($quote);
}
}
$words = explode(' ', $phrase);
foreach($words as &$word) {
if(empty($word))
continue;
$match[] = $pdo->quote($word);
}
$like = '';
foreach($match as &$phrase) {
if(!empty($like))
$like .= ' AND ';
$phrase = preg_replace('/^\'(.+)\'$/', '\'%$1%\'', $phrase);
$like .= '`body` LIKE ' . $phrase . ' ESCAPE \'!\'';
}
foreach($filters as $name => $value) {
if(!empty($like))
$like .= ' AND ';
$like .= '`' . $name . '` = '. $pdo->quote($value);
}
$like = str_replace('%', '%%', $like);
$query = prepare(sprintf("SELECT * FROM ``posts_%s`` WHERE " . $like . " ORDER BY `time` DESC LIMIT :limit", $board['uri']));
$query->bindValue(':limit', $search_limit, PDO::PARAM_INT);
$query->execute() or error(db_error($query));
if($query->rowCount() == $search_limit) {
_syslog(LOG_WARNING, 'Query too broad.');
$body .= '<p class="unimportant" style="text-align:center">('._('Query too broad.').')</p>';
echo Element('page.html', Array(
'config'=>$config,
'title'=>'Search',
'body'=>$body,
));
exit;
}
$temp = '';
while($post = $query->fetch()) {
if(!$post['thread']) {
$po = new Thread($post);
} else {
$po = new Post($post);
}
$temp .= $po->build(true) . '<hr/>';
}
if(!empty($temp))
$_body .= '<fieldset><legend>' .
sprintf(ngettext('%d result in', '%d results in', $query->rowCount()),
$query->rowCount()) . ' <a href="/' .
sprintf($config['board_path'], $board['uri']) . $config['file_index'] .
'">' .
sprintf($config['board_abbreviation'], $board['uri']) . ' - ' . $board['title'] .
'</a></legend>' . $temp . '</fieldset>';
$body .= '<hr/>';
if(!empty($_body))
$body .= $_body;
else
$body .= '<p style="text-align:center" class="unimportant">('._('No results.').')</p>';
}
echo Element('page.html', Array(
'config'=>$config,
'title'=>_('Search'),
'body'=>'' . $body
));

BIN
static/blank.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

BIN
static/collapse.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 B

BIN
static/flags/a1.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

BIN
static/flags/a2.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

BIN
static/flags/ac.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

Some files were not shown because too many files have changed in this diff Show More