Merge remote-tracking branch 'upstream/develop' into 1601-api-statuses-lookup

This commit is contained in:
Michael 2017-03-25 11:25:47 +00:00
commit 4665cda00e
73 changed files with 9863 additions and 9437 deletions

117
boot.php
View file

@ -32,7 +32,6 @@ require_once('include/cache.php');
require_once('library/Mobile_Detect/Mobile_Detect.php');
require_once('include/features.php');
require_once('include/identity.php');
require_once('include/pidfile.php');
require_once('update.php');
require_once('include/dbstructure.php');
@ -40,7 +39,7 @@ define ( 'FRIENDICA_PLATFORM', 'Friendica');
define ( 'FRIENDICA_CODENAME', 'Asparagus');
define ( 'FRIENDICA_VERSION', '3.5.2-dev' );
define ( 'DFRN_PROTOCOL_VERSION', '2.23' );
define ( 'DB_UPDATE_VERSION', 1215 );
define ( 'DB_UPDATE_VERSION', 1216 );
/**
* @brief Constant with a HTML line break.
@ -442,10 +441,17 @@ define('SR_SCOPE_ALL', 'all');
define('SR_SCOPE_TAGS', 'tags');
/* @}*/
// Normally this constant is defined - but not if "pcntl" isn't installed
if (!defined("SIGTERM"))
define("SIGTERM", 15);
/**
* Lowest possible date time value
*/
define ('NULL_DATE', '0001-01-01 00:00:00');
// Normally this constant is defined - but not if "pcntl" isn't installed
if (!defined("SIGTERM")) {
define("SIGTERM", 15);
}
/**
*
* Reverse the effect of magic_quotes_gpc if it is enabled.
@ -1346,60 +1352,25 @@ class App {
return false;
}
/**
* @brief Checks if the process is already running
*
* @param string $taskname The name of the task that will be used for the name of the lockfile
* @param string $task The path and name of the php script
* @param int $timeout The timeout after which a task should be killed
*
* @return bool Is the process running?
*/
function is_already_running($taskname, $task = "", $timeout = 540) {
$lockpath = get_lockpath();
if ($lockpath != '') {
$pidfile = new pidfile($lockpath, $taskname);
if ($pidfile->is_already_running()) {
logger("Already running");
if ($pidfile->running_time() > $timeout) {
$pidfile->kill();
logger("killed stale process");
// Calling a new instance
if ($task != "")
proc_run(PRIORITY_MEDIUM, $task);
}
return true;
}
}
return false;
}
function proc_run($args) {
if (!function_exists("proc_open")) {
return;
}
// Add the php path if it is a php call
if (count($args) && ($args[0] === 'php' OR !is_string($args[0]))) {
// If the last worker fork was less than 10 seconds before then don't fork another one.
// This should prevent the forking of masses of workers.
if (get_config("system", "worker")) {
$cachekey = "app:proc_run:started";
$result = Cache::get($cachekey);
if (!is_null($result)) {
if ((time() - $result) < 10) {
return;
}
}
// Set the timestamp of the last proc_run
Cache::set($cachekey, time(), CACHE_MINUTE);
// If the last worker fork was less than 10 seconds before then don't fork another one.
// This should prevent the forking of masses of workers.
$cachekey = "app:proc_run:started";
$result = Cache::get($cachekey);
if (!is_null($result)) {
if ((time() - $result) < 10) {
return;
}
$args[0] = ((x($this->config,'php_path')) && (strlen($this->config['php_path'])) ? $this->config['php_path'] : 'php');
}
// Set the timestamp of the last proc_run
Cache::set($cachekey, time(), CACHE_MINUTE);
array_unshift($args, ((x($this->config,'php_path')) && (strlen($this->config['php_path'])) ? $this->config['php_path'] : 'php'));
// add baseurl to args. cli scripts can't construct it
$args[] = $this->get_baseurl();
@ -1976,10 +1947,9 @@ function get_max_import_size() {
* @brief Wrap calls to proc_close(proc_open()) and call hook
* so plugins can take part in process :)
*
* @param (string|integer|array) $cmd program to run, priority or parameter array
* @param (integer|array) priority or parameter array, $cmd atrings are deprecated and are ignored
*
* next args are passed as $cmd command line
* e.g.: proc_run("ls","-la","/tmp");
* or: proc_run(PRIORITY_HIGH, "include/notifier.php", "drop", $drop_id);
* or: proc_run(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), "include/create_shadowentry.php", $post_id);
*
@ -2024,11 +1994,6 @@ function proc_run($cmd){
if (!$arr['run_cmd'] OR !count($args))
return;
if (!get_config("system", "worker") OR (is_string($run_parameter) AND ($run_parameter != 'php'))) {
$a->proc_run($args);
return;
}
$priority = PRIORITY_MEDIUM;
$dont_fork = get_config("system", "worker_dont_fork");
@ -2063,7 +2028,7 @@ function proc_run($cmd){
}
// Checking number of workers
$workers = q("SELECT COUNT(*) AS `workers` FROM `workerqueue` WHERE `executed` != '0000-00-00 00:00:00'");
$workers = q("SELECT COUNT(*) AS `workers` FROM `workerqueue` WHERE `executed` > '%s'", dbesc(NULL_DATE));
// Get number of allowed number of worker threads
$queues = intval(get_config("system", "worker_queues"));
@ -2076,7 +2041,7 @@ function proc_run($cmd){
return;
// Now call the poller to execute the jobs that we just added to the queue
$args = array("php", "include/poller.php", "no_cron");
$args = array("include/poller.php", "no_cron");
$a->proc_run($args);
}
@ -2410,38 +2375,6 @@ function get_itemcachepath() {
return "";
}
function get_lockpath() {
$lockpath = get_config('system','lockpath');
if (($lockpath != "") AND App::directory_usable($lockpath)) {
// We have a lock path and it is usable
return $lockpath;
}
// We don't have a working preconfigured lock path, so we take the temp path.
$temppath = get_temppath();
if ($temppath != "") {
// To avoid any interferences with other systems we create our own directory
$lockpath = $temppath."/lock";
if (!is_dir($lockpath)) {
mkdir($lockpath);
}
if (App::directory_usable($lockpath)) {
// The new path is usable, we are happy
set_config("system", "lockpath", $lockpath);
return $lockpath;
} else {
// We can't create a subdirectory, strange.
// But the directory seems to work, so we use it but don't store it.
return $temppath;
}
}
// Reaching this point means that the operating system is configured badly.
return "";
}
/**
* @brief Returns the path where spool files are stored
*

View file

@ -1,5 +1,5 @@
-- ------------------------------------------
-- Friendica 3.5.1-rc (Asparagus)
-- Friendica 3.5.2-dev (Asparagus)
-- DB_UPDATE_VERSION 1215
-- ------------------------------------------
@ -30,8 +30,8 @@ CREATE TABLE IF NOT EXISTS `attach` (
`filetype` varchar(64) NOT NULL DEFAULT '',
`filesize` int(11) NOT NULL DEFAULT 0,
`data` longblob NOT NULL,
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`edited` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`edited` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`allow_cid` mediumtext,
`allow_gid` mediumtext,
`deny_cid` mediumtext,
@ -58,7 +58,7 @@ CREATE TABLE IF NOT EXISTS `cache` (
`k` varbinary(255) NOT NULL,
`v` mediumtext,
`expire_mode` int(11) NOT NULL DEFAULT 0,
`updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY(`k`),
INDEX `expire_mode_updated` (`expire_mode`,`updated`)
) DEFAULT CHARSET=utf8mb4;
@ -107,7 +107,7 @@ CREATE TABLE IF NOT EXISTS `config` (
CREATE TABLE IF NOT EXISTS `contact` (
`id` int(11) NOT NULL auto_increment,
`uid` int(11) NOT NULL DEFAULT 0,
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`self` tinyint(1) NOT NULL DEFAULT 0,
`remote_self` tinyint(1) NOT NULL DEFAULT 0,
`rel` tinyint(1) NOT NULL DEFAULT 0,
@ -145,14 +145,14 @@ CREATE TABLE IF NOT EXISTS `contact` (
`usehub` tinyint(1) NOT NULL DEFAULT 0,
`subhub` tinyint(1) NOT NULL DEFAULT 0,
`hub-verify` varchar(255) NOT NULL DEFAULT '',
`last-update` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`success_update` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`failure_update` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`name-date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`uri-date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`avatar-date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`term-date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`last-item` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`last-update` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`success_update` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`failure_update` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`name-date` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`uri-date` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`avatar-date` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`term-date` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`last-item` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`priority` tinyint(3) NOT NULL DEFAULT 0,
`blocked` tinyint(1) NOT NULL DEFAULT 1,
`readonly` tinyint(1) NOT NULL DEFAULT 0,
@ -197,25 +197,13 @@ CREATE TABLE IF NOT EXISTS `conv` (
`recips` text,
`uid` int(11) NOT NULL DEFAULT 0,
`creator` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`subject` text,
PRIMARY KEY(`id`),
INDEX `uid` (`uid`)
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE deliverq
--
CREATE TABLE IF NOT EXISTS `deliverq` (
`id` int(10) unsigned NOT NULL auto_increment,
`cmd` varbinary(32) NOT NULL DEFAULT '',
`item` int(11) NOT NULL DEFAULT 0,
`contact` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY(`id`),
UNIQUE INDEX `cmd_item_contact` (`cmd`,`item`,`contact`)
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE event
--
@ -225,10 +213,10 @@ CREATE TABLE IF NOT EXISTS `event` (
`uid` int(11) NOT NULL DEFAULT 0,
`cid` int(11) NOT NULL DEFAULT 0,
`uri` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`edited` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`start` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`finish` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`edited` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`start` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`finish` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`summary` text,
`desc` text,
`location` text,
@ -264,7 +252,7 @@ CREATE TABLE IF NOT EXISTS `fcontact` (
`network` varchar(32) NOT NULL DEFAULT '',
`alias` varchar(255) NOT NULL DEFAULT '',
`pubkey` text,
`updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY(`id`),
INDEX `addr` (`addr`(32)),
INDEX `url` (`url`)
@ -305,7 +293,7 @@ CREATE TABLE IF NOT EXISTS `fsuggest` (
`request` varchar(255) NOT NULL DEFAULT '',
`photo` varchar(255) NOT NULL DEFAULT '',
`note` text,
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8mb4;
@ -332,10 +320,10 @@ CREATE TABLE IF NOT EXISTS `gcontact` (
`nurl` varchar(255) NOT NULL DEFAULT '',
`photo` varchar(255) NOT NULL DEFAULT '',
`connect` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated` datetime DEFAULT '0000-00-00 00:00:00',
`last_contact` datetime DEFAULT '0000-00-00 00:00:00',
`last_failure` datetime DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`updated` datetime DEFAULT '0001-01-01 00:00:00',
`last_contact` datetime DEFAULT '0001-01-01 00:00:00',
`last_failure` datetime DEFAULT '0001-01-01 00:00:00',
`location` varchar(255) NOT NULL DEFAULT '',
`about` text,
`keywords` text,
@ -369,7 +357,7 @@ CREATE TABLE IF NOT EXISTS `glink` (
`uid` int(11) NOT NULL DEFAULT 0,
`gcid` int(11) NOT NULL DEFAULT 0,
`zcid` int(11) NOT NULL DEFAULT 0,
`updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY(`id`),
UNIQUE INDEX `cid_uid_gcid_zcid` (`cid`,`uid`,`gcid`,`zcid`),
INDEX `gcid` (`gcid`)
@ -417,10 +405,10 @@ CREATE TABLE IF NOT EXISTS `gserver` (
`noscrape` varchar(255) NOT NULL DEFAULT '',
`network` varchar(32) NOT NULL DEFAULT '',
`platform` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`last_poco_query` datetime DEFAULT '0000-00-00 00:00:00',
`last_contact` datetime DEFAULT '0000-00-00 00:00:00',
`last_failure` datetime DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`last_poco_query` datetime DEFAULT '0001-01-01 00:00:00',
`last_contact` datetime DEFAULT '0001-01-01 00:00:00',
`last_failure` datetime DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY(`id`),
INDEX `nurl` (`nurl`(32))
) DEFAULT CHARSET=utf8mb4;
@ -450,7 +438,7 @@ CREATE TABLE IF NOT EXISTS `intro` (
`duplex` tinyint(1) NOT NULL DEFAULT 0,
`note` text,
`hash` varchar(255) NOT NULL DEFAULT '',
`datetime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`datetime` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`blocked` tinyint(1) NOT NULL DEFAULT 1,
`ignore` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY(`id`)
@ -473,11 +461,11 @@ CREATE TABLE IF NOT EXISTS `item` (
`parent-uri` varchar(255) NOT NULL DEFAULT '',
`extid` varchar(255) NOT NULL DEFAULT '',
`thr-parent` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`edited` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`commented` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`received` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`changed` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`edited` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`commented` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`received` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`changed` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`owner-id` int(11) NOT NULL DEFAULT 0,
`owner-name` varchar(255) NOT NULL DEFAULT '',
`owner-link` varchar(255) NOT NULL DEFAULT '',
@ -576,7 +564,7 @@ CREATE TABLE IF NOT EXISTS `locks` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(128) NOT NULL DEFAULT '',
`locked` tinyint(1) NOT NULL DEFAULT 0,
`created` datetime DEFAULT '0000-00-00 00:00:00',
`created` datetime DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8mb4;
@ -600,7 +588,7 @@ CREATE TABLE IF NOT EXISTS `mail` (
`unknown` tinyint(1) NOT NULL DEFAULT 0,
`uri` varchar(255) NOT NULL DEFAULT '',
`parent-uri` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY(`id`),
INDEX `uid_seen` (`uid`,`seen`),
INDEX `convid` (`convid`),
@ -624,7 +612,7 @@ CREATE TABLE IF NOT EXISTS `mailacct` (
`action` int(11) NOT NULL DEFAULT 0,
`movetofolder` varchar(255) NOT NULL DEFAULT '',
`pubmail` tinyint(1) NOT NULL DEFAULT 0,
`last_check` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`last_check` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8mb4;
@ -649,7 +637,7 @@ CREATE TABLE IF NOT EXISTS `notify` (
`name` varchar(255) NOT NULL DEFAULT '',
`url` varchar(255) NOT NULL DEFAULT '',
`photo` varchar(255) NOT NULL DEFAULT '',
`date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`date` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`msg` mediumtext,
`uid` int(11) NOT NULL DEFAULT 0,
`link` varchar(255) NOT NULL DEFAULT '',
@ -685,7 +673,7 @@ CREATE TABLE IF NOT EXISTS `notify-threads` (
CREATE TABLE IF NOT EXISTS `oembed` (
`url` varbinary(255) NOT NULL,
`content` mediumtext,
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY(`url`),
INDEX `created` (`created`)
) DEFAULT CHARSET=utf8mb4;
@ -698,7 +686,7 @@ CREATE TABLE IF NOT EXISTS `parsed_url` (
`guessing` tinyint(1) NOT NULL DEFAULT 0,
`oembed` tinyint(1) NOT NULL DEFAULT 0,
`content` mediumtext,
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY(`url`,`guessing`,`oembed`),
INDEX `created` (`created`)
) DEFAULT CHARSET=utf8mb4;
@ -725,8 +713,8 @@ CREATE TABLE IF NOT EXISTS `photo` (
`contact-id` int(10) unsigned NOT NULL DEFAULT 0,
`guid` varchar(64) NOT NULL DEFAULT '',
`resource-id` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`edited` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`edited` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`title` varchar(255) NOT NULL DEFAULT '',
`desc` text,
`album` varchar(255) NOT NULL DEFAULT '',
@ -788,7 +776,7 @@ CREATE TABLE IF NOT EXISTS `poll_result` (
CREATE TABLE IF NOT EXISTS `process` (
`pid` int(10) unsigned NOT NULL,
`command` varbinary(32) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY(`pid`),
INDEX `command` (`command`)
) DEFAULT CHARSET=utf8mb4;
@ -814,7 +802,7 @@ CREATE TABLE IF NOT EXISTS `profile` (
`gender` varchar(32) NOT NULL DEFAULT '',
`marital` varchar(255) NOT NULL DEFAULT '',
`with` text,
`howlong` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`howlong` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`sexual` varchar(255) NOT NULL DEFAULT '',
`politic` varchar(255) NOT NULL DEFAULT '',
`religion` varchar(255) NOT NULL DEFAULT '',
@ -866,7 +854,7 @@ CREATE TABLE IF NOT EXISTS `push_subscriber` (
`topic` varchar(255) NOT NULL DEFAULT '',
`nickname` varchar(255) NOT NULL DEFAULT '',
`push` int(11) NOT NULL DEFAULT 0,
`last_update` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`last_update` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`secret` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8mb4;
@ -878,8 +866,8 @@ CREATE TABLE IF NOT EXISTS `queue` (
`id` int(11) NOT NULL auto_increment,
`cid` int(11) NOT NULL DEFAULT 0,
`network` varchar(32) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`last` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`last` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`content` mediumtext,
`batch` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY(`id`),
@ -896,7 +884,7 @@ CREATE TABLE IF NOT EXISTS `queue` (
CREATE TABLE IF NOT EXISTS `register` (
`id` int(11) unsigned NOT NULL auto_increment,
`hash` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`uid` int(11) unsigned NOT NULL DEFAULT 0,
`password` varchar(255) NOT NULL DEFAULT '',
`language` varchar(16) NOT NULL DEFAULT '',
@ -950,7 +938,7 @@ CREATE TABLE IF NOT EXISTS `spam` (
`spam` int(11) NOT NULL DEFAULT 0,
`ham` int(11) NOT NULL DEFAULT 0,
`term` varchar(255) NOT NULL DEFAULT '',
`date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`date` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY(`id`),
INDEX `uid` (`uid`),
INDEX `spam` (`spam`),
@ -969,8 +957,8 @@ CREATE TABLE IF NOT EXISTS `term` (
`term` varchar(255) NOT NULL DEFAULT '',
`url` varchar(255) NOT NULL DEFAULT '',
`guid` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`received` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`received` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`global` tinyint(1) NOT NULL DEFAULT 0,
`aid` int(10) unsigned NOT NULL DEFAULT 0,
`uid` int(10) unsigned NOT NULL DEFAULT 0,
@ -991,11 +979,11 @@ CREATE TABLE IF NOT EXISTS `thread` (
`gcontact-id` int(11) unsigned NOT NULL DEFAULT 0,
`owner-id` int(11) unsigned NOT NULL DEFAULT 0,
`author-id` int(11) unsigned NOT NULL DEFAULT 0,
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`edited` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`commented` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`received` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`changed` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`edited` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`commented` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`received` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`changed` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`wall` tinyint(1) NOT NULL DEFAULT 0,
`private` tinyint(1) NOT NULL DEFAULT 0,
`pubmail` tinyint(1) NOT NULL DEFAULT 0,
@ -1047,8 +1035,8 @@ CREATE TABLE IF NOT EXISTS `user` (
`openid` varchar(255) NOT NULL DEFAULT '',
`timezone` varchar(128) NOT NULL DEFAULT '',
`language` varchar(32) NOT NULL DEFAULT 'en',
`register_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`login_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`register_date` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`login_date` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`default-location` varchar(255) NOT NULL DEFAULT '',
`allow_location` tinyint(1) NOT NULL DEFAULT 0,
`theme` varchar(255) NOT NULL DEFAULT '',
@ -1072,8 +1060,8 @@ CREATE TABLE IF NOT EXISTS `user` (
`expire` int(11) unsigned NOT NULL DEFAULT 0,
`account_removed` tinyint(1) NOT NULL DEFAULT 0,
`account_expired` tinyint(1) NOT NULL DEFAULT 0,
`account_expires_on` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`expire_notification_sent` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`account_expires_on` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`expire_notification_sent` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`service_class` varchar(32) NOT NULL DEFAULT '',
`def_gid` int(11) NOT NULL DEFAULT 0,
`allow_cid` mediumtext,
@ -1102,9 +1090,9 @@ CREATE TABLE IF NOT EXISTS `workerqueue` (
`id` int(11) NOT NULL auto_increment,
`parameter` text,
`priority` tinyint(3) unsigned NOT NULL DEFAULT 0,
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`pid` int(11) NOT NULL DEFAULT 0,
`executed` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`executed` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8mb4;

View file

@ -152,13 +152,6 @@ Value is in seconds.
Default is 60 seconds.
Set to 0 for unlimited (not recommended).
#### UTF-8 Regular Expressions
During registrations, full names are checked using UTF-8 regular expressions.
This requires PHP to have been compiled with a special setting to allow UTF-8 expressions.
If you are completely unable to register accounts, set no_utf to true.
The default is set to false (meaning UTF8 regular expressions are supported and working).
#### Verify SSL Certitificates
By default Friendica allows SSL communication between websites that have "self-signed" SSL certificates.

View file

@ -127,7 +127,7 @@ function mark_for_death($contact) {
if($contact['archive'])
return;
if($contact['term-date'] == '0000-00-00 00:00:00') {
if ($contact['term-date'] <= NULL_DATE) {
q("UPDATE `contact` SET `term-date` = '%s' WHERE `id` = %d",
dbesc(datetime_convert()),
intval($contact['id'])
@ -185,13 +185,13 @@ function unmark_for_death($contact) {
// It's a miracle. Our dead contact has inexplicably come back to life.
q("UPDATE `contact` SET `term-date` = '%s' WHERE `id` = %d",
dbesc('0000-00-00 00:00:00'),
dbesc(NULL_DATE),
intval($contact['id'])
);
if ($contact['url'] != '') {
q("UPDATE `contact` SET `term-date` = '%s' WHERE `nurl` = '%s'",
dbesc('0000-00-00 00:00:00'),
dbesc(NULL_DATE),
dbesc(normalise_link($contact['url']))
);
}

View file

@ -6,26 +6,9 @@
* This script is started from mod/item.php to save some time when doing a post.
*/
use \Friendica\Core\Config;
require_once("boot.php");
require_once("include/threads.php");
function create_shadowentry_run($argv, $argc) {
global $a, $db;
if (is_null($a))
$a = new App;
if (is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
}
Config::load();
if ($argc != 2) {
return;
}
@ -34,9 +17,4 @@ function create_shadowentry_run($argv, $argc) {
add_shadow_entry($message_id);
}
if (array_search(__file__,get_included_files())===0){
create_shadowentry_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}
?>

View file

@ -1,62 +1,24 @@
<?php
if (!file_exists("boot.php") AND (sizeof($_SERVER["argv"]) != 0)) {
$directory = dirname($_SERVER["argv"][0]);
if (substr($directory, 0, 1) != "/")
$directory = $_SERVER["PWD"]."/".$directory;
$directory = realpath($directory."/..");
chdir($directory);
}
use \Friendica\Core\Config;
require_once("boot.php");
require_once("include/photos.php");
require_once("include/user.php");
function cron_run(&$argv, &$argc){
global $a, $db;
global $a;
if(is_null($a)) {
$a = new App;
}
if(is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once('include/session.php');
require_once('include/datetime.php');
require_once('include/items.php');
require_once('include/Contact.php');
require_once('include/email.php');
require_once('include/socgraph.php');
require_once('mod/nodeinfo.php');
require_once('include/post_update.php');
Config::load();
// Don't check this stuff if the function is called by the poller
if (App::callstack() != "poller_run") {
if ($a->maxload_reached())
return;
if (App::is_already_running('cron', 'include/cron.php', 540))
return;
// Poll contacts with specific parameters
if ($argc > 1) {
cron_poll_contacts($argc, $argv);
return;
}
$last = get_config('system','last_cron');
$poll_interval = intval(get_config('system','cron_interval'));
if(! $poll_interval)
if (! $poll_interval) {
$poll_interval = 10;
if($last) {
}
if ($last) {
$next = $last + ($poll_interval * 60);
if($next > time()) {
logger('cron intervall not reached');
@ -64,64 +26,50 @@ function cron_run(&$argv, &$argc){
}
}
$a->set_baseurl(get_config('system','url'));
load_hooks();
logger('cron: start');
// run queue delivery process in the background
proc_run(PRIORITY_NEGLIGIBLE, "include/queue.php");
// run the process to discover global contacts in the background
proc_run(PRIORITY_LOW, "include/discover_poco.php");
// run the process to update locally stored global contacts in the background
proc_run(PRIORITY_LOW, "include/discover_poco.php", "checkcontact");
// Expire and remove user entries
cron_expire_and_remove_users();
proc_run(PRIORITY_MEDIUM, "include/cronjobs.php", "expire_and_remove_users");
// If the worker is active, split the jobs in several sub processes
if (get_config("system", "worker")) {
// Check OStatus conversations
proc_run(PRIORITY_MEDIUM, "include/cronjobs.php", "ostatus_mentions");
// Check OStatus conversations
proc_run(PRIORITY_MEDIUM, "include/cronjobs.php", "ostatus_mentions");
// Check every conversation
proc_run(PRIORITY_MEDIUM, "include/cronjobs.php", "ostatus_conversations");
// Check every conversation
proc_run(PRIORITY_MEDIUM, "include/cronjobs.php", "ostatus_conversations");
// Call possible post update functions
proc_run(PRIORITY_LOW, "include/cronjobs.php", "post_update");
// Call possible post update functions
proc_run(PRIORITY_LOW, "include/cronjobs.php", "post_update");
// update nodeinfo data
proc_run(PRIORITY_LOW, "include/cronjobs.php", "nodeinfo");
} else {
// Check OStatus conversations
// Check only conversations with mentions (for a longer time)
ostatus::check_conversations(true);
// update nodeinfo data
proc_run(PRIORITY_LOW, "include/cronjobs.php", "nodeinfo");
// Check every conversation
ostatus::check_conversations(false);
// Clear cache entries
proc_run(PRIORITY_LOW, "include/cronjobs.php", "clear_cache");
// Call possible post update functions
// see include/post_update.php for more details
post_update();
// Repair missing Diaspora values in contacts
proc_run(PRIORITY_LOW, "include/cronjobs.php", "repair_diaspora");
// update nodeinfo data
nodeinfo_cron();
}
// Repair entries in the database
proc_run(PRIORITY_LOW, "include/cronjobs.php", "repair_database");
// once daily run birthday_updates and then expire in background
$d1 = get_config('system','last_expire_day');
$d2 = intval(datetime_convert('UTC','UTC','now','d'));
if($d2 != intval($d1)) {
update_contact_birthdays();
proc_run(PRIORITY_LOW, "include/cronjobs.php", "update_contact_birthdays");
proc_run(PRIORITY_LOW, "include/discover_poco.php", "update_server");
proc_run(PRIORITY_LOW, "include/discover_poco.php", "suggestions");
@ -131,18 +79,9 @@ function cron_run(&$argv, &$argc){
proc_run(PRIORITY_MEDIUM, 'include/dbclean.php');
cron_update_photo_albums();
proc_run(PRIORITY_LOW, "include/cronjobs.php", "update_photo_albums");
}
// Clear cache entries
cron_clear_cache($a);
// Repair missing Diaspora values in contacts
cron_repair_diaspora($a);
// Repair entries in the database
cron_repair_database();
// Poll contacts
cron_poll_contacts($argc, $argv);
@ -153,39 +92,6 @@ function cron_run(&$argv, &$argc){
return;
}
/**
* @brief Update the cached values for the number of photo albums per user
*/
function cron_update_photo_albums() {
$r = q("SELECT `uid` FROM `user` WHERE NOT `account_expired` AND NOT `account_removed`");
if (!dbm::is_result($r)) {
return;
}
foreach ($r AS $user) {
photo_albums($user['uid'], true);
}
}
/**
* @brief Expire and remove user entries
*/
function cron_expire_and_remove_users() {
// expire any expired accounts
q("UPDATE user SET `account_expired` = 1 where `account_expired` = 0
AND `account_expires_on` != '0000-00-00 00:00:00'
AND `account_expires_on` < UTC_TIMESTAMP() ");
// delete user and contact records for recently removed accounts
$r = q("SELECT * FROM `user` WHERE `account_removed` AND `account_expires_on` < UTC_TIMESTAMP() - INTERVAL 3 DAY");
if ($r) {
foreach($r as $user) {
q("DELETE FROM `contact` WHERE `uid` = %d", intval($user['uid']));
q("DELETE FROM `user` WHERE `uid` = %d", intval($user['uid']));
}
}
}
/**
* @brief Poll contacts for unreceived messages
*
@ -198,14 +104,15 @@ function cron_poll_contacts($argc, $argv) {
$force = false;
$restart = false;
if (($argc > 1) && ($argv[1] == 'force'))
if (($argc > 1) && ($argv[1] == 'force')) {
$force = true;
}
if (($argc > 1) && ($argv[1] == 'restart')) {
$restart = true;
$generation = intval($argv[2]);
if (!$generation)
if (!$generation) {
killme();
}
}
if (($argc > 1) && intval($argv[1])) {
@ -213,14 +120,6 @@ function cron_poll_contacts($argc, $argv) {
$force = true;
}
$interval = intval(get_config('system','poll_interval'));
if (!$interval)
$interval = ((get_config('system','delivery_interval') === false) ? 3 : intval(get_config('system','delivery_interval')));
// If we are using the worker we don't need a delivery interval
if (get_config("system", "worker"))
$interval = false;
$sql_extra = (($manual_id) ? " AND `id` = $manual_id " : "");
reload_plugins();
@ -232,9 +131,9 @@ function cron_poll_contacts($argc, $argv) {
// we are unable to match those posts with a Diaspora GUID and prevent duplicates.
$abandon_days = intval(get_config('system','account_abandon_days'));
if($abandon_days < 1)
if ($abandon_days < 1) {
$abandon_days = 0;
}
$abandon_sql = (($abandon_days)
? sprintf(" AND `user`.`login_date` > UTC_TIMESTAMP() - INTERVAL %d DAY ", intval($abandon_days))
: ''
@ -275,13 +174,15 @@ function cron_poll_contacts($argc, $argv) {
$xml = false;
if($manual_id)
$contact['last-update'] = '0000-00-00 00:00:00';
if ($manual_id) {
$contact['last-update'] = NULL_DATE;
}
if(in_array($contact['network'], array(NETWORK_DFRN, NETWORK_ZOT, NETWORK_OSTATUS)))
if (in_array($contact['network'], array(NETWORK_DFRN, NETWORK_ZOT, NETWORK_OSTATUS))) {
$contact['priority'] = 2;
}
if($contact['subhub'] AND in_array($contact['network'], array(NETWORK_DFRN, NETWORK_ZOT, NETWORK_OSTATUS))) {
if ($contact['subhub'] AND in_array($contact['network'], array(NETWORK_DFRN, NETWORK_ZOT, NETWORK_OSTATUS))) {
// We should be getting everything via a hub. But just to be sure, let's check once a day.
// (You can make this more or less frequent if desired by setting 'pushpoll_frequency' appropriately)
// This also lets us update our subscription to the hub, and add or replace hubs in case it
@ -303,193 +204,44 @@ function cron_poll_contacts($argc, $argv) {
switch ($contact['priority']) {
case 5:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 month"))
if (datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 month")) {
$update = true;
}
break;
case 4:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 week"))
if (datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 week")) {
$update = true;
}
break;
case 3:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 day"))
if (datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 day")) {
$update = true;
}
break;
case 2:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 12 hour"))
if (datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 12 hour")) {
$update = true;
}
break;
case 1:
default:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 hour"))
if (datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 hour")) {
$update = true;
}
break;
}
if (!$update)
if (!$update) {
continue;
}
}
logger("Polling ".$contact["network"]." ".$contact["id"]." ".$contact["nick"]." ".$contact["name"]);
if (($contact['network'] == NETWORK_FEED) AND ($contact['priority'] <= 3)) {
proc_run(PRIORITY_MEDIUM, 'include/onepoll.php', $contact['id']);
proc_run(PRIORITY_MEDIUM, 'include/onepoll.php', intval($contact['id']));
} else {
proc_run(PRIORITY_LOW, 'include/onepoll.php', $contact['id']);
}
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
}
}
/**
* @brief Clear cache entries
*
* @param App $a
*/
function cron_clear_cache(App $a) {
$last = get_config('system','cache_last_cleared');
if($last) {
$next = $last + (3600); // Once per hour
$clear_cache = ($next <= time());
} else
$clear_cache = true;
if (!$clear_cache)
return;
// clear old cache
Cache::clear();
// clear old item cache files
clear_cache();
// clear cache for photos
clear_cache($a->get_basepath(), $a->get_basepath()."/photo");
// clear smarty cache
clear_cache($a->get_basepath()."/view/smarty3/compiled", $a->get_basepath()."/view/smarty3/compiled");
// clear cache for image proxy
if (!get_config("system", "proxy_disabled")) {
clear_cache($a->get_basepath(), $a->get_basepath()."/proxy");
$cachetime = get_config('system','proxy_cache_time');
if (!$cachetime) $cachetime = PROXY_DEFAULT_TIME;
q('DELETE FROM `photo` WHERE `uid` = 0 AND `resource-id` LIKE "pic:%%" AND `created` < NOW() - INTERVAL %d SECOND', $cachetime);
}
// Delete the cached OEmbed entries that are older than one year
q("DELETE FROM `oembed` WHERE `created` < NOW() - INTERVAL 3 MONTH");
// Delete the cached "parse_url" entries that are older than one year
q("DELETE FROM `parsed_url` WHERE `created` < NOW() - INTERVAL 3 MONTH");
// Maximum table size in megabyte
$max_tablesize = intval(get_config('system','optimize_max_tablesize')) * 1000000;
if ($max_tablesize == 0)
$max_tablesize = 100 * 1000000; // Default are 100 MB
if ($max_tablesize > 0) {
// Minimum fragmentation level in percent
$fragmentation_level = intval(get_config('system','optimize_fragmentation')) / 100;
if ($fragmentation_level == 0)
$fragmentation_level = 0.3; // Default value is 30%
// Optimize some tables that need to be optimized
$r = q("SHOW TABLE STATUS");
foreach($r as $table) {
// Don't optimize tables that are too large
if ($table["Data_length"] > $max_tablesize)
continue;
// Don't optimize empty tables
if ($table["Data_length"] == 0)
continue;
// Calculate fragmentation
$fragmentation = $table["Data_free"] / ($table["Data_length"] + $table["Index_length"]);
logger("Table ".$table["Name"]." - Fragmentation level: ".round($fragmentation * 100, 2), LOGGER_DEBUG);
// Don't optimize tables that needn't to be optimized
if ($fragmentation < $fragmentation_level)
continue;
// So optimize it
logger("Optimize Table ".$table["Name"], LOGGER_DEBUG);
q("OPTIMIZE TABLE `%s`", dbesc($table["Name"]));
}
}
set_config('system','cache_last_cleared', time());
}
/**
* @brief Repair missing values in Diaspora contacts
*
* @param App $a
*/
function cron_repair_diaspora(App $a) {
$r = q("SELECT `id`, `url` FROM `contact`
WHERE `network` = '%s' AND (`batch` = '' OR `notify` = '' OR `poll` = '' OR pubkey = '')
ORDER BY RAND() LIMIT 50", dbesc(NETWORK_DIASPORA));
if (dbm::is_result($r)) {
foreach ($r AS $contact) {
if (poco_reachable($contact["url"])) {
$data = probe_url($contact["url"]);
if ($data["network"] == NETWORK_DIASPORA) {
logger("Repair contact ".$contact["id"]." ".$contact["url"], LOGGER_DEBUG);
q("UPDATE `contact` SET `batch` = '%s', `notify` = '%s', `poll` = '%s', pubkey = '%s' WHERE `id` = %d",
dbesc($data["batch"]), dbesc($data["notify"]), dbesc($data["poll"]), dbesc($data["pubkey"]),
intval($contact["id"]));
}
proc_run(PRIORITY_LOW, 'include/onepoll.php', intval($contact['id']));
}
}
}
}
/**
* @brief Do some repairs in database entries
*
*/
function cron_repair_database() {
// Sometimes there seem to be issues where the "self" contact vanishes.
// We haven't found the origin of the problem by now.
$r = q("SELECT `uid` FROM `user` WHERE NOT EXISTS (SELECT `uid` FROM `contact` WHERE `contact`.`uid` = `user`.`uid` AND `contact`.`self`)");
if (dbm::is_result($r)) {
foreach ($r AS $user) {
logger('Create missing self contact for user '.$user['uid']);
user_create_self_contact($user['uid']);
}
}
// Set the parent if it wasn't set. (Shouldn't happen - but does sometimes)
// This call is very "cheap" so we can do it at any time without a problem
q("UPDATE `item` INNER JOIN `item` AS `parent` ON `parent`.`uri` = `item`.`parent-uri` AND `parent`.`uid` = `item`.`uid` SET `item`.`parent` = `parent`.`id` WHERE `item`.`parent` = 0");
// There was an issue where the nick vanishes from the contact table
q("UPDATE `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` SET `nick` = `nickname` WHERE `self` AND `nick`=''");
// Update the global contacts for local users
$r = q("SELECT `uid` FROM `user` WHERE `verified` AND NOT `blocked` AND NOT `account_removed` AND NOT `account_expired`");
if (dbm::is_result($r))
foreach ($r AS $user)
update_gcontact_for_user($user["uid"]);
/// @todo
/// - remove thread entries without item
/// - remove sign entries without item
/// - remove children when parent got lost
/// - set contact-id in item when not present
}
if (array_search(__file__,get_included_files())===0){
cron_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -2,37 +2,11 @@
use \Friendica\Core\Config;
require_once("boot.php");
function cronhooks_run(&$argv, &$argc){
global $a, $db;
global $a;
if(is_null($a)) {
$a = new App;
}
if(is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once('include/session.php');
require_once('include/datetime.php');
Config::load();
// Don't check this stuff if the function is called by the poller
if (App::callstack() != "poller_run") {
if ($a->maxload_reached())
return;
if (App::is_already_running('cronhooks', 'include/cronhooks.php', 1140))
return;
}
load_hooks();
if (($argc == 2) AND is_array($a->hooks) AND array_key_exists("cron", $a->hooks)) {
foreach ($a->hooks["cron"] as $hook)
if ($hook[1] == $argv[1]) {
@ -42,7 +16,7 @@ function cronhooks_run(&$argv, &$argc){
return;
}
$last = get_config('system','last_cronhook');
$last = get_config('system', 'last_cronhook');
$poll_interval = intval(get_config('system','cronhook_interval'));
if(! $poll_interval)
@ -62,22 +36,16 @@ function cronhooks_run(&$argv, &$argc){
$d = datetime_convert();
if (get_config("system", "worker") AND is_array($a->hooks) AND array_key_exists("cron", $a->hooks)) {
if (is_array($a->hooks) AND array_key_exists("cron", $a->hooks)) {
foreach ($a->hooks["cron"] as $hook) {
logger("Calling cronhooks for '".$hook[1]."'", LOGGER_DEBUG);
proc_run(PRIORITY_MEDIUM, "include/cronhooks.php", $hook[1]);
}
} else
call_hooks('cron', $d);
}
logger('cronhooks: end');
set_config('system','last_cronhook', time());
set_config('system', 'last_cronhook', time());
return;
}
if (array_search(__file__,get_included_files())===0){
cronhooks_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -1,47 +1,24 @@
<?php
use \Friendica\Core\Config;
if (!file_exists("boot.php") AND (sizeof($_SERVER["argv"]) != 0)) {
$directory = dirname($_SERVER["argv"][0]);
if (substr($directory, 0, 1) != "/")
$directory = $_SERVER["PWD"]."/".$directory;
$directory = realpath($directory."/..");
chdir($directory);
}
require_once("boot.php");
function cronjobs_run(&$argv, &$argc){
global $a, $db;
global $a;
if(is_null($a)) {
$a = new App;
}
if(is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once('include/session.php');
require_once('include/datetime.php');
require_once('include/ostatus.php');
require_once('include/post_update.php');
require_once('mod/nodeinfo.php');
Config::load();
$a->set_baseurl(get_config('system','url'));
require_once('include/photos.php');
require_once('include/user.php');
require_once('include/socgraph.php');
require_once('include/Probe.php');
// No parameter set? So return
if ($argc <= 1)
if ($argc <= 1) {
return;
}
logger("Starting cronjob ".$argv[1], LOGGER_DEBUG);
// Check OStatus conversations
// Check only conversations with mentions (for a longer time)
@ -69,10 +46,244 @@ function cronjobs_run(&$argv, &$argc){
return;
}
// Expire and remove user entries
if ($argv[1] == 'expire_and_remove_users') {
cron_expire_and_remove_users();
return;
}
if ($argv[1] == 'update_contact_birthdays') {
update_contact_birthdays();
return;
}
if ($argv[1] == 'update_photo_albums') {
cron_update_photo_albums();
return;
}
// Clear cache entries
if ($argv[1] == 'clear_cache') {
cron_clear_cache($a);
return;
}
// Repair missing Diaspora values in contacts
if ($argv[1] == 'repair_diaspora') {
cron_repair_diaspora($a);
return;
}
// Repair entries in the database
if ($argv[1] == 'repair_database') {
cron_repair_database();
return;
}
logger("Xronjob ".$argv[1]." is unknown.", LOGGER_DEBUG);
return;
}
if (array_search(__file__,get_included_files())===0){
cronjobs_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
/**
* @brief Update the cached values for the number of photo albums per user
*/
function cron_update_photo_albums() {
$r = q("SELECT `uid` FROM `user` WHERE NOT `account_expired` AND NOT `account_removed`");
if (!dbm::is_result($r)) {
return;
}
foreach ($r AS $user) {
photo_albums($user['uid'], true);
}
}
/**
* @brief Expire and remove user entries
*/
function cron_expire_and_remove_users() {
// expire any expired accounts
q("UPDATE user SET `account_expired` = 1 where `account_expired` = 0
AND `account_expires_on` > '%s'
AND `account_expires_on` < UTC_TIMESTAMP()", dbesc(NULL_DATE));
// delete user and contact records for recently removed accounts
$r = q("SELECT * FROM `user` WHERE `account_removed` AND `account_expires_on` < UTC_TIMESTAMP() - INTERVAL 3 DAY");
if (dbm::is_result($r)) {
foreach ($r as $user) {
q("DELETE FROM `contact` WHERE `uid` = %d", intval($user['uid']));
q("DELETE FROM `user` WHERE `uid` = %d", intval($user['uid']));
}
}
}
/**
* @brief Clear cache entries
*
* @param App $a
*/
function cron_clear_cache(App $a) {
$last = get_config('system','cache_last_cleared');
if ($last) {
$next = $last + (3600); // Once per hour
$clear_cache = ($next <= time());
} else {
$clear_cache = true;
}
if (!$clear_cache) {
return;
}
// clear old cache
Cache::clear();
// clear old item cache files
clear_cache();
// clear cache for photos
clear_cache($a->get_basepath(), $a->get_basepath()."/photo");
// clear smarty cache
clear_cache($a->get_basepath()."/view/smarty3/compiled", $a->get_basepath()."/view/smarty3/compiled");
// clear cache for image proxy
if (!get_config("system", "proxy_disabled")) {
clear_cache($a->get_basepath(), $a->get_basepath()."/proxy");
$cachetime = get_config('system','proxy_cache_time');
if (!$cachetime) {
$cachetime = PROXY_DEFAULT_TIME;
}
q('DELETE FROM `photo` WHERE `uid` = 0 AND `resource-id` LIKE "pic:%%" AND `created` < NOW() - INTERVAL %d SECOND', $cachetime);
}
// Delete the cached OEmbed entries that are older than one year
q("DELETE FROM `oembed` WHERE `created` < NOW() - INTERVAL 3 MONTH");
// Delete the cached "parse_url" entries that are older than one year
q("DELETE FROM `parsed_url` WHERE `created` < NOW() - INTERVAL 3 MONTH");
// Maximum table size in megabyte
$max_tablesize = intval(get_config('system','optimize_max_tablesize')) * 1000000;
if ($max_tablesize == 0) {
$max_tablesize = 100 * 1000000; // Default are 100 MB
}
if ($max_tablesize > 0) {
// Minimum fragmentation level in percent
$fragmentation_level = intval(get_config('system','optimize_fragmentation')) / 100;
if ($fragmentation_level == 0) {
$fragmentation_level = 0.3; // Default value is 30%
}
// Optimize some tables that need to be optimized
$r = q("SHOW TABLE STATUS");
foreach ($r as $table) {
// Don't optimize tables that are too large
if ($table["Data_length"] > $max_tablesize) {
continue;
}
// Don't optimize empty tables
if ($table["Data_length"] == 0) {
continue;
}
// Calculate fragmentation
$fragmentation = $table["Data_free"] / ($table["Data_length"] + $table["Index_length"]);
logger("Table ".$table["Name"]." - Fragmentation level: ".round($fragmentation * 100, 2), LOGGER_DEBUG);
// Don't optimize tables that needn't to be optimized
if ($fragmentation < $fragmentation_level) {
continue;
}
// So optimize it
logger("Optimize Table ".$table["Name"], LOGGER_DEBUG);
q("OPTIMIZE TABLE `%s`", dbesc($table["Name"]));
}
}
set_config('system','cache_last_cleared', time());
}
/**
* @brief Repair missing values in Diaspora contacts
*
* @param App $a
*/
function cron_repair_diaspora(App $a) {
$starttime = time();
$r = q("SELECT `id`, `url` FROM `contact`
WHERE `network` = '%s' AND (`batch` = '' OR `notify` = '' OR `poll` = '' OR pubkey = '')
ORDER BY RAND() LIMIT 50", dbesc(NETWORK_DIASPORA));
if (!dbm::is_result($r)) {
return;
}
foreach ($r AS $contact) {
// Quit the loop after 3 minutes
if (time() > ($starttime + 180)) {
return;
}
if (!poco_reachable($contact["url"])) {
continue;
}
$data = Probe::uri($contact["url"]);
if ($data["network"] != NETWORK_DIASPORA) {
continue;
}
logger("Repair contact ".$contact["id"]." ".$contact["url"], LOGGER_DEBUG);
q("UPDATE `contact` SET `batch` = '%s', `notify` = '%s', `poll` = '%s', pubkey = '%s' WHERE `id` = %d",
dbesc($data["batch"]), dbesc($data["notify"]), dbesc($data["poll"]), dbesc($data["pubkey"]),
intval($contact["id"]));
}
}
/**
* @brief Do some repairs in database entries
*
*/
function cron_repair_database() {
// Sometimes there seem to be issues where the "self" contact vanishes.
// We haven't found the origin of the problem by now.
$r = q("SELECT `uid` FROM `user` WHERE NOT EXISTS (SELECT `uid` FROM `contact` WHERE `contact`.`uid` = `user`.`uid` AND `contact`.`self`)");
if (dbm::is_result($r)) {
foreach ($r AS $user) {
logger('Create missing self contact for user '.$user['uid']);
user_create_self_contact($user['uid']);
}
}
// Set the parent if it wasn't set. (Shouldn't happen - but does sometimes)
// This call is very "cheap" so we can do it at any time without a problem
q("UPDATE `item` INNER JOIN `item` AS `parent` ON `parent`.`uri` = `item`.`parent-uri` AND `parent`.`uid` = `item`.`uid` SET `item`.`parent` = `parent`.`id` WHERE `item`.`parent` = 0");
// There was an issue where the nick vanishes from the contact table
q("UPDATE `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` SET `nick` = `nickname` WHERE `self` AND `nick`=''");
// Update the global contacts for local users
$r = q("SELECT `uid` FROM `user` WHERE `verified` AND NOT `blocked` AND NOT `account_removed` AND NOT `account_expired`");
if (dbm::is_result($r)) {
foreach ($r AS $user) {
update_gcontact_for_user($user["uid"]);
}
}
/// @todo
/// - remove thread entries without item
/// - remove sign entries without item
/// - remove children when parent got lost
/// - set contact-id in item when not present
}

View file

@ -339,7 +339,7 @@ function relative_date($posted_date, $format = null) {
$abs = strtotime($localtime);
if (is_null($posted_date) || $posted_date === '0000-00-00 00:00:00' || $abs === False) {
if (is_null($posted_date) || $posted_date <= NULL_DATE || $abs === False) {
return t('never');
}

View file

@ -1,17 +1,5 @@
<?php
require_once("dbm.php");
# if PDO is avaible for mysql, use the new database abstraction
# TODO: PDO is disabled for release 3.3. We need to investigate why
# the update from 3.2 fails with pdo
/*
if (class_exists('\PDO') && in_array('mysql', PDO::getAvailableDrivers())) {
require_once("library/dddbl2/dddbl.php");
require_once("include/dba_pdo.php");
}
*/
require_once('include/datetime.php');
/**
@ -24,13 +12,12 @@ require_once('include/datetime.php');
*
*/
if (! class_exists('dba')) {
class dba {
private $debug = 0;
private $db;
private $result;
public $mysqli = true;
private $driver;
public $connected = false;
public $error = false;
@ -53,7 +40,7 @@ class dba {
if ($install) {
if (strlen($server) && ($server !== 'localhost') && ($server !== '127.0.0.1')) {
if (! dns_get_record($server, DNS_A + DNS_CNAME + DNS_PTR)) {
$this->error = sprintf( t('Cannot locate DNS info for database server \'%s\''), $server);
$this->error = sprintf(t('Cannot locate DNS info for database server \'%s\''), $server);
$this->connected = false;
$this->db = null;
return;
@ -61,37 +48,52 @@ class dba {
}
}
if (class_exists('mysqli')) {
$this->db = @new mysqli($server,$user,$pass,$db);
if (! mysqli_connect_errno()) {
if (class_exists('\PDO') && in_array('mysql', PDO::getAvailableDrivers())) {
$this->driver = 'pdo';
$connect = "mysql:host=".$server.";dbname=".$db;
if (isset($a->config["system"]["db_charset"])) {
$connect .= ";charset=".$a->config["system"]["db_charset"];
}
$this->db = @new PDO($connect, $user, $pass);
if (!$this->db->errorCode()) {
$this->connected = true;
}
if (isset($a->config["system"]["db_charset"])) {
$this->db->set_charset($a->config["system"]["db_charset"]);
} elseif (class_exists('mysqli')) {
$this->driver = 'mysqli';
$this->db = @new mysqli($server,$user,$pass,$db);
if (!mysqli_connect_errno()) {
$this->connected = true;
if (isset($a->config["system"]["db_charset"])) {
$this->db->set_charset($a->config["system"]["db_charset"]);
}
}
} else {
$this->mysqli = false;
} elseif (function_exists('mysql_connect')) {
$this->driver = 'mysql';
$this->db = mysql_connect($server,$user,$pass);
if ($this->db && mysql_select_db($db,$this->db)) {
$this->connected = true;
if (isset($a->config["system"]["db_charset"])) {
mysql_set_charset($a->config["system"]["db_charset"], $this->db);
}
}
} else {
// No suitable SQL driver was found.
if (!$install) {
system_unavailable();
}
if (isset($a->config["system"]["db_charset"]))
mysql_set_charset($a->config["system"]["db_charset"], $this->db);
}
if (!$this->connected) {
$this->db = null;
if (!$install) {
system_unavailable();
}
}
$a->save_timestamp($stamp1, "network");
}
public function getdb() {
return $this->db;
}
/**
* @brief Returns the MySQL server version string
*
@ -101,12 +103,18 @@ class dba {
* @return string
*/
public function server_info() {
if ($this->mysqli) {
$return = $this->db->server_info;
} else {
$return = mysql_get_server_info($this->db);
switch ($this->driver) {
case 'pdo':
$version = $this->db->getAttribute(PDO::ATTR_SERVER_VERSION);
break;
case 'mysqli':
$version = $this->db->server_info;
break;
case 'mysql':
$version = mysql_get_server_info($this->db);
break;
}
return $return;
return $version;
}
/**
@ -130,12 +138,18 @@ class dba {
return 0;
}
if ($this->mysqli) {
$return = $this->result->num_rows;
} else {
$return = mysql_num_rows($this->result);
switch ($this->driver) {
case 'pdo':
$rows = $this->result->rowCount();
break;
case 'mysqli':
$rows = $this->result->num_rows;
break;
case 'mysql':
$rows = mysql_num_rows($this->result);
break;
}
return $return;
return $rows;
}
/**
@ -172,8 +186,9 @@ class dba {
if ((intval($a->config["system"]["db_loglimit_index"]) > 0)) {
$log = (in_array($row['key'], $watchlist) AND
($row['rows'] >= intval($a->config["system"]["db_loglimit_index"])));
} else
} else {
$log = false;
}
if ((intval($a->config["system"]["db_loglimit_index_high"]) > 0) AND ($row['rows'] >= intval($a->config["system"]["db_loglimit_index_high"]))) {
$log = true;
@ -203,13 +218,7 @@ class dba {
$this->error = '';
// Check the connection (This can reconnect the connection - if configured)
if ($this->mysqli) {
$connected = $this->db->ping();
} else {
$connected = mysql_ping($this->db);
}
$connstr = ($connected ? "Connected" : "Disonnected");
$connstr = ($this->connected() ? "Connected" : "Disonnected");
$stamp1 = microtime(true);
@ -219,10 +228,22 @@ class dba {
$sql = "/*".$a->callstack()." */ ".$sql;
}
if ($this->mysqli) {
$result = @$this->db->query($sql);
} else {
$result = @mysql_query($sql,$this->db);
$columns = 0;
switch ($this->driver) {
case 'pdo':
$result = @$this->db->query($sql);
// Is used to separate between queries that returning data - or not
if (!is_bool($result)) {
$columns = $result->columnCount();
}
break;
case 'mysqli':
$result = @$this->db->query($sql);
break;
case 'mysql':
$result = @mysql_query($sql,$this->db);
break;
}
$stamp2 = microtime(true);
$duration = (float)($stamp2-$stamp1);
@ -243,16 +264,27 @@ class dba {
}
}
if ($this->mysqli) {
if ($this->db->errno) {
$this->error = $this->db->error;
$this->errorno = $this->db->errno;
}
} elseif (mysql_errno($this->db)) {
$this->error = mysql_error($this->db);
$this->errorno = mysql_errno($this->db);
switch ($this->driver) {
case 'pdo':
$errorInfo = $this->db->errorInfo();
if ($errorInfo) {
$this->error = $errorInfo[2];
$this->errorno = $errorInfo[1];
}
break;
case 'mysqli':
if ($this->db->errno) {
$this->error = $this->db->error;
$this->errorno = $this->db->errno;
}
break;
case 'mysql':
if (mysql_errno($this->db)) {
$this->error = mysql_error($this->db);
$this->errorno = mysql_errno($this->db);
}
break;
}
if (strlen($this->error)) {
logger('DB Error ('.$connstr.') '.$this->errorno.': '.$this->error);
}
@ -266,10 +298,16 @@ class dba {
} elseif ($result === true) {
$mesg = 'true';
} else {
if ($this->mysqli) {
$mesg = $result->num_rows . ' results' . EOL;
} else {
$mesg = mysql_num_rows($result) . ' results' . EOL;
switch ($this->driver) {
case 'pdo':
$mesg = $result->rowCount().' results'.EOL;
break;
case 'mysqli':
$mesg = $result->num_rows.' results'.EOL;
break;
case 'mysql':
$mesg = mysql_num_rows($result).' results'.EOL;
break;
}
}
@ -293,7 +331,7 @@ class dba {
}
}
if (($result === true) || ($result === false)) {
if (is_bool($result)) {
return $result;
}
if ($onlyquery) {
@ -302,18 +340,32 @@ class dba {
}
$r = array();
if ($this->mysqli) {
if ($result->num_rows) {
while($x = $result->fetch_array(MYSQLI_ASSOC))
switch ($this->driver) {
case 'pdo':
while ($x = $result->fetch(PDO::FETCH_ASSOC)) {
$r[] = $x;
}
$result->closeCursor();
break;
case 'mysqli':
while ($x = $result->fetch_array(MYSQLI_ASSOC)) {
$r[] = $x;
}
$result->free_result();
}
} else {
if (mysql_num_rows($result)) {
while($x = mysql_fetch_array($result, MYSQL_ASSOC))
break;
case 'mysql':
while ($x = mysql_fetch_array($result, MYSQL_ASSOC)) {
$r[] = $x;
}
mysql_free_result($result);
}
break;
}
// PDO doesn't return "true" on successful operations - like mysqli does
// Emulate this behaviour by checking if the query returned data and had columns
// This should be reliable enough
if (($this->driver == 'pdo') AND (count($r) == 0) AND ($columns == 0)) {
return true;
}
//$a->save_timestamp($stamp1, "database");
@ -328,12 +380,16 @@ class dba {
$x = false;
if ($this->result) {
if ($this->mysqli) {
if ($this->result->num_rows)
switch ($this->driver) {
case 'pdo':
$x = $this->result->fetch(PDO::FETCH_ASSOC);
break;
case 'mysqli':
$x = $this->result->fetch_array(MYSQLI_ASSOC);
} else {
if (mysql_num_rows($this->result))
break;
case 'mysql':
$x = mysql_fetch_array($this->result, MYSQL_ASSOC);
break;
}
}
return($x);
@ -341,10 +397,16 @@ class dba {
public function qclose() {
if ($this->result) {
if ($this->mysqli) {
$this->result->free_result();
} else {
mysql_free_result($this->result);
switch ($this->driver) {
case 'pdo':
$this->result->closeCursor();
break;
case 'mysqli':
$this->result->free_result();
break;
case 'mysql':
mysql_free_result($this->result);
break;
}
}
}
@ -355,35 +417,65 @@ class dba {
public function escape($str) {
if ($this->db && $this->connected) {
if ($this->mysqli) {
return @$this->db->real_escape_string($str);
} else {
return @mysql_real_escape_string($str,$this->db);
switch ($this->driver) {
case 'pdo':
return substr(@$this->db->quote($str, PDO::PARAM_STR), 1, -1);
case 'mysqli':
return @$this->db->real_escape_string($str);
case 'mysql':
return @mysql_real_escape_string($str,$this->db);
}
}
}
function connected() {
if ($this->mysqli) {
$connected = $this->db->ping();
} else {
$connected = mysql_ping($this->db);
switch ($this->driver) {
case 'pdo':
// Not sure if this really is working like expected
$connected = ($this->db->getAttribute(PDO::ATTR_CONNECTION_STATUS) != "");
break;
case 'mysqli':
$connected = $this->db->ping();
break;
case 'mysql':
$connected = mysql_ping($this->db);
break;
}
return $connected;
}
function insert_id() {
switch ($this->driver) {
case 'pdo':
$id = $this->db->lastInsertId();
break;
case 'mysqli':
$id = $this->db->insert_id;
break;
case 'mysql':
$id = mysql_insert_id($this->db);
break;
}
return $id;
}
function __destruct() {
if ($this->db) {
if ($this->mysqli) {
$this->db->close();
} else {
mysql_close($this->db);
switch ($this->driver) {
case 'pdo':
$this->db = null;
break;
case 'mysqli':
$this->db->close();
break;
case 'mysql':
mysql_close($this->db);
break;
}
}
}
}}
}
if (! function_exists('printable')) {
function printable($s) {
$s = preg_replace("~([\x01-\x08\x0E-\x0F\x10-\x1F\x7F-\xFF])~",".", $s);
$s = str_replace("\x00",'.',$s);
@ -391,37 +483,32 @@ function printable($s) {
$s = escape_tags($s);
}
return $s;
}}
}
// Procedural functions
if (! function_exists('dbg')) {
function dbg($state) {
global $db;
if ($db) {
$db->dbg($state);
}
}}
}
if (! function_exists('dbesc')) {
function dbesc($str) {
global $db;
if ($db && $db->connected) {
return($db->escape($str));
} else {
return(str_replace("'","\\'",$str));
}
}}
}
// Function: q($sql,$args);
// Description: execute SQL query with printf style args.
// Example: $r = q("SELECT * FROM `%s` WHERE `uid` = %d",
// 'user', 1);
if (! function_exists('q')) {
function q($sql) {
global $db;
$args = func_get_args();
unset($args[0]);
@ -445,8 +532,7 @@ function q($sql) {
*/
logger('dba: no database: ' . print_r($args,true));
return false;
}}
}
/**
* @brief Performs a query with "dirty reads"
@ -458,8 +544,8 @@ function q($sql) {
* @return array Query array
*/
function qu($sql) {
global $db;
$args = func_get_args();
unset($args[0]);
@ -484,7 +570,6 @@ function qu($sql) {
*/
logger('dba: no database: ' . print_r($args,true));
return false;
}
/**
@ -492,40 +577,31 @@ function qu($sql) {
* Raw db query, no arguments
*
*/
if (! function_exists('dbq')) {
function dbq($sql) {
global $db;
if ($db && $db->connected) {
$ret = $db->q($sql);
} else {
$ret = false;
}
return $ret;
}}
}
// Caller is responsible for ensuring that any integer arguments to
// dbesc_array are actually integers and not malformed strings containing
// SQL injection vectors. All integer array elements should be specifically
// cast to int to avoid trouble.
if (! function_exists('dbesc_array_cb')) {
function dbesc_array_cb(&$item, $key) {
if (is_string($item))
$item = dbesc($item);
}}
}
if (! function_exists('dbesc_array')) {
function dbesc_array(&$arr) {
if (is_array($arr) && count($arr)) {
array_walk($arr,'dbesc_array_cb');
}
}}
}
function dba_timer() {
return microtime(true);

View file

@ -5,26 +5,8 @@
*/
use \Friendica\Core\Config;
use \Friendica\Core\PConfig;
require_once("boot.php");
function dbclean_run(&$argv, &$argc) {
global $a, $db;
if (is_null($a)) {
$a = new App;
}
if (is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
}
Config::load();
if (!Config::get('system', 'dbclean', false)) {
return;
}
@ -35,7 +17,7 @@ function dbclean_run(&$argv, &$argc) {
$stage = 0;
}
if (Config::get("system", "worker") AND ($stage == 0)) {
if ($stage == 0) {
proc_run(PRIORITY_LOW, 'include/dbclean.php', 1);
proc_run(PRIORITY_LOW, 'include/dbclean.php', 2);
proc_run(PRIORITY_LOW, 'include/dbclean.php', 3);
@ -56,12 +38,8 @@ function remove_orphans($stage = 0) {
$count = 0;
// With activated worker we split the deletion in many small tasks
if (Config::get("system", "worker")) {
$limit = 1000;
} else {
$limit = 10000;
}
// We split the deletion in many small tasks
$limit = 1000;
if (($stage == 1) OR ($stage == 0)) {
logger("Deleting old global item entries from item table without user copy");
@ -159,14 +137,9 @@ function remove_orphans($stage = 0) {
}
// Call it again if not all entries were purged
if (($stage != 0) AND ($count > 0) AND Config::get("system", "worker")) {
if (($stage != 0) AND ($count > 0)) {
proc_run(PRIORITY_MEDIUM, 'include/dbclean.php');
}
}
if (array_search(__file__,get_included_files())===0){
dbclean_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}
?>

View file

@ -96,17 +96,10 @@ class dbm {
public static function date($date = 'now') {
$timestamp = strtotime($date);
// Workaround for 3.5.1
if ($timestamp < -62135596800) {
return '0000-00-00 00:00:00';
}
// The above will be removed in 3.5.2
// The following will then be enabled
// Don't allow lower date strings as '0001-01-01 00:00:00'
//if ($timestamp < -62135596800) {
// $timestamp = -62135596800;
//}
if ($timestamp < -62135596800) {
$timestamp = -62135596800;
}
return date('Y-m-d H:i:s', $timestamp);
}

View file

@ -1,4 +1,7 @@
<?php
use \Friendica\Core\Config;
require_once("boot.php");
require_once("include/text.php");
@ -144,7 +147,8 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
global $a, $db;
if ($action) {
set_config('system', 'maintenance', 1);
Config::set('system', 'maintenance', 1);
Config::set('system', 'maintenance_reason', 'Database update');
}
if (isset($a->config["system"]["db_charset"])) {
@ -361,8 +365,10 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
}
}
if ($action)
set_config('system', 'maintenance', 0);
if ($action) {
Config::set('system', 'maintenance', 0);
Config::set('system', 'maintenance_reason', '');
}
return $errors;
}
@ -536,8 +542,8 @@ function db_definition($charset) {
"filetype" => array("type" => "varchar(64)", "not null" => "1", "default" => ""),
"filesize" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"data" => array("type" => "longblob", "not null" => "1"),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"edited" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"edited" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"allow_cid" => array("type" => "mediumtext"),
"allow_gid" => array("type" => "mediumtext"),
"deny_cid" => array("type" => "mediumtext"),
@ -564,7 +570,7 @@ function db_definition($charset) {
"k" => array("type" => "varbinary(255)", "not null" => "1", "primary" => "1"),
"v" => array("type" => "mediumtext"),
"expire_mode" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"updated" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"updated" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
),
"indexes" => array(
"PRIMARY" => array("k"),
@ -613,7 +619,7 @@ function db_definition($charset) {
"fields" => array(
"id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"uid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"self" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"remote_self" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"rel" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
@ -651,14 +657,14 @@ function db_definition($charset) {
"usehub" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"subhub" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"hub-verify" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"last-update" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"success_update" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"failure_update" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"name-date" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"uri-date" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"avatar-date" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"term-date" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"last-item" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"last-update" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"success_update" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"failure_update" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"name-date" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"uri-date" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"avatar-date" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"term-date" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"last-item" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"priority" => array("type" => "tinyint(3)", "not null" => "1", "default" => "0"),
"blocked" => array("type" => "tinyint(1)", "not null" => "1", "default" => "1"),
"readonly" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
@ -703,8 +709,8 @@ function db_definition($charset) {
"recips" => array("type" => "text"),
"uid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"creator" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"updated" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"updated" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"subject" => array("type" => "text"),
),
"indexes" => array(
@ -712,18 +718,6 @@ function db_definition($charset) {
"uid" => array("uid"),
)
);
$database["deliverq"] = array(
"fields" => array(
"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"cmd" => array("type" => "varbinary(32)", "not null" => "1", "default" => ""),
"item" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"contact" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
),
"indexes" => array(
"PRIMARY" => array("id"),
"cmd_item_contact" => array("UNIQUE", "cmd", "item", "contact"),
)
);
$database["event"] = array(
"fields" => array(
"id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
@ -731,10 +725,10 @@ function db_definition($charset) {
"uid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"cid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"uri" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"edited" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"start" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"finish" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"edited" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"start" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"finish" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"summary" => array("type" => "text"),
"desc" => array("type" => "text"),
"location" => array("type" => "text"),
@ -770,7 +764,7 @@ function db_definition($charset) {
"network" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"alias" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"pubkey" => array("type" => "text"),
"updated" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"updated" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -811,7 +805,7 @@ function db_definition($charset) {
"request" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"photo" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"note" => array("type" => "text"),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -838,10 +832,10 @@ function db_definition($charset) {
"nurl" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"photo" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"connect" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"updated" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
"last_contact" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
"last_failure" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"updated" => array("type" => "datetime", "default" => NULL_DATE),
"last_contact" => array("type" => "datetime", "default" => NULL_DATE),
"last_failure" => array("type" => "datetime", "default" => NULL_DATE),
"location" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"about" => array("type" => "text"),
"keywords" => array("type" => "text"),
@ -875,7 +869,7 @@ function db_definition($charset) {
"uid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"gcid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"zcid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"updated" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"updated" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -923,10 +917,10 @@ function db_definition($charset) {
"noscrape" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"network" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"platform" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"last_poco_query" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
"last_contact" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
"last_failure" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"last_poco_query" => array("type" => "datetime", "default" => NULL_DATE),
"last_contact" => array("type" => "datetime", "default" => NULL_DATE),
"last_failure" => array("type" => "datetime", "default" => NULL_DATE),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -956,7 +950,7 @@ function db_definition($charset) {
"duplex" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"note" => array("type" => "text"),
"hash" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"datetime" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"datetime" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"blocked" => array("type" => "tinyint(1)", "not null" => "1", "default" => "1"),
"ignore" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
),
@ -979,11 +973,11 @@ function db_definition($charset) {
"parent-uri" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"extid" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"thr-parent" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"edited" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"commented" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"received" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"changed" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"edited" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"commented" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"received" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"changed" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"owner-id" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"owner-name" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"owner-link" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
@ -1082,7 +1076,7 @@ function db_definition($charset) {
"id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"name" => array("type" => "varchar(128)", "not null" => "1", "default" => ""),
"locked" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"created" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "default" => NULL_DATE),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -1106,7 +1100,7 @@ function db_definition($charset) {
"unknown" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"uri" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"parent-uri" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -1130,7 +1124,7 @@ function db_definition($charset) {
"action" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"movetofolder" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"pubmail" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"last_check" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"last_check" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -1155,7 +1149,7 @@ function db_definition($charset) {
"name" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"photo" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"date" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"date" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"msg" => array("type" => "mediumtext"),
"uid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"link" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
@ -1191,7 +1185,7 @@ function db_definition($charset) {
"fields" => array(
"url" => array("type" => "varbinary(255)", "not null" => "1", "primary" => "1"),
"content" => array("type" => "mediumtext"),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
),
"indexes" => array(
"PRIMARY" => array("url"),
@ -1204,7 +1198,7 @@ function db_definition($charset) {
"guessing" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0", "primary" => "1"),
"oembed" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0", "primary" => "1"),
"content" => array("type" => "mediumtext"),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
),
"indexes" => array(
"PRIMARY" => array("url", "guessing", "oembed"),
@ -1231,8 +1225,8 @@ function db_definition($charset) {
"contact-id" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0"),
"guid" => array("type" => "varchar(64)", "not null" => "1", "default" => ""),
"resource-id" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"edited" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"edited" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"title" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"desc" => array("type" => "text"),
"album" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
@ -1294,7 +1288,7 @@ function db_definition($charset) {
"fields" => array(
"pid" => array("type" => "int(10) unsigned", "not null" => "1", "primary" => "1"),
"command" => array("type" => "varbinary(32)", "not null" => "1", "default" => ""),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
),
"indexes" => array(
"PRIMARY" => array("pid"),
@ -1320,7 +1314,7 @@ function db_definition($charset) {
"gender" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"marital" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"with" => array("type" => "text"),
"howlong" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"howlong" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"sexual" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"politic" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"religion" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
@ -1372,7 +1366,7 @@ function db_definition($charset) {
"topic" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"nickname" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"push" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"last_update" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"last_update" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"secret" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
),
"indexes" => array(
@ -1384,8 +1378,8 @@ function db_definition($charset) {
"id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"cid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"network" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"last" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"last" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"content" => array("type" => "mediumtext"),
"batch" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
),
@ -1402,7 +1396,7 @@ function db_definition($charset) {
"fields" => array(
"id" => array("type" => "int(11) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"hash" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"uid" => array("type" => "int(11) unsigned", "not null" => "1", "default" => "0"),
"password" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"language" => array("type" => "varchar(16)", "not null" => "1", "default" => ""),
@ -1456,7 +1450,7 @@ function db_definition($charset) {
"spam" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"ham" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"term" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"date" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"date" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -1475,8 +1469,8 @@ function db_definition($charset) {
"term" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"guid" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"received" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"received" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"global" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"aid" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0"),
"uid" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0"),
@ -1497,11 +1491,11 @@ function db_definition($charset) {
"gcontact-id" => array("type" => "int(11) unsigned", "not null" => "1", "default" => "0"),
"owner-id" => array("type" => "int(11) unsigned", "not null" => "1", "default" => "0"),
"author-id" => array("type" => "int(11) unsigned", "not null" => "1", "default" => "0"),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"edited" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"commented" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"received" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"changed" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"edited" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"commented" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"received" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"changed" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"wall" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"private" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"pubmail" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
@ -1553,8 +1547,8 @@ function db_definition($charset) {
"openid" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"timezone" => array("type" => "varchar(128)", "not null" => "1", "default" => ""),
"language" => array("type" => "varchar(32)", "not null" => "1", "default" => "en"),
"register_date" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"login_date" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"register_date" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"login_date" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"default-location" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"allow_location" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"theme" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
@ -1578,8 +1572,8 @@ function db_definition($charset) {
"expire" => array("type" => "int(11) unsigned", "not null" => "1", "default" => "0"),
"account_removed" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"account_expired" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"account_expires_on" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"expire_notification_sent" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"account_expires_on" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"expire_notification_sent" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"service_class" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"def_gid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"allow_cid" => array("type" => "mediumtext"),
@ -1608,9 +1602,9 @@ function db_definition($charset) {
"id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"parameter" => array("type" => "text"),
"priority" => array("type" => "tinyint(3) unsigned", "not null" => "1", "default" => "0"),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"created" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
"pid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"executed" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"executed" => array("type" => "datetime", "not null" => "1", "default" => NULL_DATE),
),
"indexes" => array(
"PRIMARY" => array("id"),

View file

@ -2,32 +2,12 @@
use \Friendica\Core\Config;
require_once("boot.php");
function dbupdate_run(&$argv, &$argc) {
global $a, $db;
if(is_null($a)){
$a = new App;
}
if(is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
}
Config::load();
global $a;
// We are deleting the latest dbupdate entry.
// This is done to avoid endless loops because the update was interupted.
Config::delete('database','dbupdate_'.DB_UPDATE_VERSION);
Config::delete('database', 'dbupdate_'.DB_UPDATE_VERSION);
update_db($a);
}
if (array_search(__file__,get_included_files())===0){
dbupdate_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -2,44 +2,25 @@
use \Friendica\Core\Config;
require_once("boot.php");
require_once('include/queue_fn.php');
require_once('include/html2plain.php');
require_once("include/Scrape.php");
require_once('include/Scrape.php');
require_once('include/diaspora.php');
require_once("include/ostatus.php");
require_once("include/dfrn.php");
require_once('include/ostatus.php');
require_once('include/dfrn.php');
function delivery_run(&$argv, &$argc){
global $a, $db;
global $a;
if (is_null($a)) {
$a = new App;
}
if (is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
}
require_once("include/session.php");
require_once("include/datetime.php");
require_once('include/datetime.php');
require_once('include/items.php');
require_once('include/bbcode.php');
require_once('include/email.php');
Config::load();
load_hooks();
if ($argc < 3) {
return;
}
$a->set_baseurl(get_config('system','url'));
logger('delivery: invoked: '. print_r($argv,true), LOGGER_DEBUG);
$cmd = $argv[1];
@ -49,30 +30,6 @@ function delivery_run(&$argv, &$argc){
$contact_id = intval($argv[$x]);
/// @todo When switching completely to the worker we won't need this anymore
// Some other process may have delivered this item already.
$r = q("SELECT * FROM `deliverq` WHERE `cmd` = '%s' AND `item` = %d AND `contact` = %d LIMIT 1",
dbesc($cmd),
dbesc($item_id),
dbesc($contact_id)
);
if (!dbm::is_result($r)) {
continue;
}
if ($a->maxload_reached()) {
return;
}
// It's ours to deliver. Remove it from the queue.
q("DELETE FROM `deliverq` WHERE `cmd` = '%s' AND `item` = %d AND `contact` = %d",
dbesc($cmd),
dbesc($item_id),
dbesc($contact_id)
);
if (!$item_id || !$contact_id) {
continue;
}
@ -577,8 +534,3 @@ function delivery_run(&$argv, &$argc){
return;
}
if (array_search(__file__,get_included_files())===0){
delivery_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -1094,7 +1094,7 @@ class dfrn {
return 3;
}
if($contact['term-date'] != '0000-00-00 00:00:00') {
if ($contact['term-date'] > NULL_DATE) {
logger("dfrn_deliver: $url back from the dead - removing mark for death");
require_once('include/Contact.php');
unmark_for_death($contact);

View file

@ -1,36 +1,16 @@
<?php
require_once("boot.php");
use \Friendica\Core\Config;
function directory_run(&$argv, &$argc){
global $a, $db;
if(is_null($a)) {
$a = new App;
if ($argc != 2) {
return;
}
if(is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
$dir = get_config('system', 'directory');
Config::load();
if($argc != 2)
return;
load_hooks();
$a->set_baseurl(get_config('system','url'));
$dir = get_config('system','directory');
if(! strlen($dir))
if (!strlen($dir)) {
return;
}
$dir .= "/submit";
@ -39,13 +19,8 @@ function directory_run(&$argv, &$argc){
call_hooks('globaldir_update', $arr);
logger('Updating directory: ' . $arr['url'], LOGGER_DEBUG);
if(strlen($arr['url']))
if (strlen($arr['url'])) {
fetch_url($dir . '?url=' . bin2hex($arr['url']));
}
return;
}
if (array_search(__file__,get_included_files())===0){
directory_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -2,62 +2,87 @@
use \Friendica\Core\Config;
require_once("boot.php");
require_once("include/socgraph.php");
require_once('include/socgraph.php');
require_once('include/datetime.php');
function discover_poco_run(&$argv, &$argc){
global $a, $db;
function discover_poco_run(&$argv, &$argc) {
if(is_null($a)) {
$a = new App;
}
/*
This function can be called in these ways:
- dirsearch <search pattern>: Searches for "search pattern" in the directory. "search pattern" is url encoded.
- checkcontact: Updates gcontact entries
- suggestions: Discover other servers for their contacts.
- server <poco url>: Searches for the poco server list. "poco url" is base64 encoded.
- update_server: Frequently check the first 250 servers for vitality.
- update_server_directory: Discover the given server id for their contacts
- poco_load: Load POCO data from a given POCO address
- check_profile: Update remote profile data
*/
if(is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once('include/session.php');
require_once('include/datetime.php');
Config::load();
// Don't check this stuff if the function is called by the poller
if (App::callstack() != "poller_run")
if ($a->maxload_reached())
return;
if(($argc > 2) && ($argv[1] == "dirsearch")) {
if (($argc > 2) && ($argv[1] == "dirsearch")) {
$search = urldecode($argv[2]);
$mode = 1;
} elseif(($argc == 2) && ($argv[1] == "checkcontact")) {
} elseif (($argc == 2) && ($argv[1] == "checkcontact")) {
$mode = 2;
} elseif(($argc == 2) && ($argv[1] == "suggestions")) {
} elseif (($argc == 2) && ($argv[1] == "suggestions")) {
$mode = 3;
} elseif (($argc == 3) && ($argv[1] == "server")) {
$mode = 4;
} elseif (($argc == 2) && ($argv[1] == "update_server")) {
$mode = 5;
} elseif (($argc == 3) && ($argv[1] == "update_server_directory")) {
$mode = 6;
} elseif (($argc > 5) && ($argv[1] == "poco_load")) {
$mode = 7;
} elseif (($argc == 3) && ($argv[1] == "check_profile")) {
$mode = 8;
} elseif ($argc == 1) {
$search = "";
$mode = 0;
} else
} else {
die("Unknown or missing parameter ".$argv[1]."\n");
// Don't check this stuff if the function is called by the poller
if (App::callstack() != "poller_run")
if (App::is_already_running('discover_poco'.$mode.urlencode($search), 'include/discover_poco.php', 1140))
return;
$a->set_baseurl(get_config('system','url'));
load_hooks();
}
logger('start '.$search);
if ($mode==3)
if ($mode == 8) {
$profile_url = base64_decode($argv[2]);
if ($profile_url != "") {
poco_last_updated($profile_url, true);
}
} elseif ($mode == 7) {
if ($argc == 6) {
$url = base64_decode($argv[5]);
} else {
$url = '';
}
poco_load_worker(intval($argv[2]), intval($argv[3]), intval($argv[4]), $url);
} elseif ($mode == 6) {
poco_discover_single_server(intval($argv[2]));
} elseif ($mode == 5) {
update_server();
} elseif ($mode == 4) {
$server_url = base64_decode($argv[2]);
if ($server_url == "") {
return;
}
$server_url = filter_var($server_url, FILTER_SANITIZE_URL);
if (substr(normalise_link($server_url), 0, 7) != "http://") {
return;
}
$result = "Checking server ".$server_url." - ";
$ret = poco_check_server($server_url);
if ($ret) {
$result .= "success";
} else {
$result .= "failed";
}
logger($result, LOGGER_DEBUG);
} elseif ($mode == 3) {
update_suggestions();
elseif (($mode == 2) AND get_config('system','poco_completion'))
} elseif (($mode == 2) AND get_config('system','poco_completion')) {
discover_users();
elseif (($mode == 1) AND ($search != "") and get_config('system','poco_local_search')) {
} elseif (($mode == 1) AND ($search != "") and get_config('system','poco_local_search')) {
discover_directory($search);
gs_search_user($search);
} elseif (($mode == 0) AND ($search == "") and (get_config('system','poco_discovery') > 0)) {
@ -74,19 +99,48 @@ function discover_poco_run(&$argv, &$argc){
return;
}
/**
* @brief Updates the first 250 servers
*
*/
function update_server() {
$r = q("SELECT `url`, `created`, `last_failure`, `last_contact` FROM `gserver` ORDER BY rand()");
if (!dbm::is_result($r)) {
return;
}
$updated = 0;
foreach ($r AS $server) {
if (!poco_do_update($server["created"], "", $server["last_failure"], $server["last_contact"])) {
continue;
}
logger('Update server status for server '.$server["url"], LOGGER_DEBUG);
proc_run(PRIORITY_LOW, "include/discover_poco.php", "server", base64_encode($server["url"]));
if (++$updated > 250) {
return;
}
}
}
function discover_users() {
logger("Discover users", LOGGER_DEBUG);
$users = q("SELECT `url`, `created`, `updated`, `last_failure`, `last_contact`, `server_url` FROM `gcontact`
$starttime = time();
$users = q("SELECT `url`, `created`, `updated`, `last_failure`, `last_contact`, `server_url`, `network` FROM `gcontact`
WHERE `last_contact` < UTC_TIMESTAMP - INTERVAL 1 MONTH AND
`last_failure` < UTC_TIMESTAMP - INTERVAL 1 MONTH AND
`network` IN ('%s', '%s', '%s', '%s', '') ORDER BY rand()",
dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA),
dbesc(NETWORK_OSTATUS), dbesc(NETWORK_FEED));
if (!$users)
if (!$users) {
return;
}
$checked = 0;
foreach ($users AS $user) {
@ -111,27 +165,34 @@ function discover_users() {
continue;
}
if ($user["server_url"] != "")
if ($user["server_url"] != "") {
$server_url = $user["server_url"];
else
} else {
$server_url = poco_detect_server($user["url"]);
}
if ((($server_url == "") AND ($user["network"] == NETWORK_FEED)) OR poco_check_server($server_url, $user["network"])) {
logger('Check profile '.$user["url"]);
proc_run(PRIORITY_LOW, "include/discover_poco.php", "check_profile", base64_encode($user["url"]));
if (($server_url == "") OR poco_check_server($server_url, $gcontacts[0]["network"])) {
logger('Check user '.$user["url"]);
poco_last_updated($user["url"], true);
if (++$checked > 100)
if (++$checked > 100) {
return;
} else
}
} else {
q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($user["url"])));
}
// Quit the loop after 3 minutes
if (time() > ($starttime + 180)) {
return;
}
}
}
function discover_directory($search) {
$data = Cache::get("dirsearch:".$search);
if (!is_null($data)){
if (!is_null($data)) {
// Only search for the same item every 24 hours
if (time() < $data + (60 * 60 * 24)) {
logger("Already searched for ".$search." in the last 24 hours", LOGGER_DEBUG);
@ -142,7 +203,7 @@ function discover_directory($search) {
$x = fetch_url(get_server()."/lsearch?p=1&n=500&search=".urlencode($search));
$j = json_decode($x);
if(count($j->results))
if (count($j->results)) {
foreach($j->results as $jj) {
// Check if the contact already exists
$exists = q("SELECT `id`, `last_contact`, `last_failure`, `updated` FROM `gcontact` WHERE `nurl` = '%s'", normalise_link($jj->url));
@ -150,32 +211,33 @@ function discover_directory($search) {
logger("Profile ".$jj->url." already exists (".$search.")", LOGGER_DEBUG);
if (($exists[0]["last_contact"] < $exists[0]["last_failure"]) AND
($exists[0]["updated"] < $exists[0]["last_failure"]))
($exists[0]["updated"] < $exists[0]["last_failure"])) {
continue;
}
// Update the contact
poco_last_updated($jj->url);
continue;
}
// Harcoded paths aren't so good. But in this case it is okay.
// First: We only will get Friendica contacts (which always are using this url schema)
// Second: There will be no further problems if we are doing a mistake
$server_url = preg_replace("=(https?://)(.*)/profile/(.*)=ism", "$1$2", $jj->url);
if ($server_url != $jj->url)
$server_url = poco_detect_server($jj->url);
if ($server_url != '') {
if (!poco_check_server($server_url)) {
logger("Friendica server ".$server_url." doesn't answer.", LOGGER_DEBUG);
continue;
}
logger("Friendica server ".$server_url." seems to be okay.", LOGGER_DEBUG);
logger("Friendica server ".$server_url." seems to be okay.", LOGGER_DEBUG);
}
logger("Check if profile ".$jj->url." is reachable (".$search.")", LOGGER_DEBUG);
$data = probe_url($jj->url);
if ($data["network"] == NETWORK_DFRN) {
logger("Profile ".$jj->url." is reachable (".$search.")", LOGGER_DEBUG);
logger("Add profile ".$jj->url." to local directory (".$search.")", LOGGER_DEBUG);
poco_check($data["url"], $data["name"], $data["network"], $data["photo"], "", "", "", $jj->tags, $data["addr"], "", 0);
} else {
logger("Profile ".$jj->url." is not responding or no Friendica contact - but network ".$data["network"], LOGGER_DEBUG);
}
}
}
Cache::set("dirsearch:".$search, time(), CACHE_DAY);
}
@ -195,14 +257,14 @@ function gs_search_user($search) {
$url = "http://gstools.org/api/users_search/".urlencode($search);
$result = z_fetch_url($url);
if (!$result["success"])
if (!$result["success"]) {
return false;
}
$contacts = json_decode($result["body"]);
if ($contacts->status == 'ERROR')
if ($contacts->status == 'ERROR') {
return false;
}
foreach($contacts->data AS $user) {
$contact = probe_url($user->site_address."/".$user->name);
if ($contact["network"] != NETWORK_PHANTOM) {
@ -211,9 +273,3 @@ function gs_search_user($search) {
}
}
}
if (array_search(__file__,get_included_files())===0){
discover_poco_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -4,39 +4,42 @@
* @brief functions specific to event handling
*/
require_once('include/bbcode.php');
require_once('include/map.php');
require_once('include/datetime.php');
require_once 'include/bbcode.php';
require_once 'include/map.php';
require_once 'include/datetime.php';
function format_event_html($ev, $simple = false) {
if(! ((is_array($ev)) && count($ev)))
if(! ((is_array($ev)) && count($ev))) {
return '';
}
$bd_format = t('l F d, Y \@ g:i A') ; // Friday January 18, 2011 @ 8 AM
$event_start = (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(),
$ev['start'] , $bd_format ))
: day_translate(datetime_convert('UTC', 'UTC',
: day_translate(datetime_convert('UTC', 'UTC',
$ev['start'] , $bd_format)));
$event_end = (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(),
$ev['finish'] , $bd_format ))
: day_translate(datetime_convert('UTC', 'UTC',
: day_translate(datetime_convert('UTC', 'UTC',
$ev['finish'] , $bd_format )));
if ($simple) {
$o = "<h3>".bbcode($ev['summary'])."</h3>";
$o = "<h3>" . bbcode($ev['summary']) . "</h3>";
$o .= "<p>".bbcode($ev['desc'])."</p>";
$o .= "<p>" . bbcode($ev['desc']) . "</p>";
$o .= "<h4>".t('Starts:')."</h4><p>".$event_start."</p>";
$o .= "<h4>" . t('Starts:') . "</h4><p>" . $event_start . "</p>";
if(! $ev['nofinish'])
$o .= "<h4>".t('Finishes:')."</h4><p>".$event_end."</p>";
if (! $ev['nofinish']) {
$o .= "<h4>" . t('Finishes:') . "</h4><p>" . $event_end ."</p>";
}
if(strlen($ev['location']))
$o .= "<h4>".t('Location:')."</h4><p>".$ev['location']."</p>";
if (strlen($ev['location'])) {
$o .= "<h4>" . t('Location:') . "</h4><p>" . $ev['location'] . "</p>";
}
return $o;
}
@ -44,31 +47,34 @@ function format_event_html($ev, $simple = false) {
$o = '<div class="vevent">' . "\r\n";
$o .= '<p class="summary event-summary">' . bbcode($ev['summary']) . '</p>' . "\r\n";
$o .= '<p class="summary event-summary">' . bbcode($ev['summary']) . '</p>' . "\r\n";
$o .= '<p class="description event-description">' . bbcode($ev['desc']) . '</p>' . "\r\n";
$o .= '<p class="description event-description">' . bbcode($ev['desc']) . '</p>' . "\r\n";
$o .= '<p class="event-start">' . t('Starts:') . ' <abbr class="dtstart" title="'
. datetime_convert('UTC','UTC',$ev['start'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
. datetime_convert('UTC', 'UTC', $ev['start'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
. '" >'.$event_start
. '</abbr></p>' . "\r\n";
if(! $ev['nofinish'])
if (! $ev['nofinish']) {
$o .= '<p class="event-end" >' . t('Finishes:') . ' <abbr class="dtend" title="'
. datetime_convert('UTC','UTC',$ev['finish'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
. datetime_convert('UTC', 'UTC', $ev['finish'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
. '" >'.$event_end
. '</abbr></p>' . "\r\n";
. '</abbr></p>' . "\r\n";
}
if(strlen($ev['location'])){
if (strlen($ev['location'])) {
$o .= '<p class="event-location"> ' . t('Location:') . ' <span class="location">'
. bbcode($ev['location'])
. '</span></p>' . "\r\n";
if (strpos($ev['location'], "[map") !== False) {
// Include a map of the location if the [map] BBCode is used
if (strpos($ev['location'], "[map") !== false) {
$map = generate_named_map($ev['location']);
if ($map!==$ev['location']) $o.=$map;
if ($map !== $ev['location']) {
$o.= $map;
}
}
}
$o .= '</div>' . "\r\n";
@ -146,63 +152,81 @@ function format_event_bbcode($ev) {
$o = '';
if($ev['summary'])
if ($ev['summary']) {
$o .= '[event-summary]' . $ev['summary'] . '[/event-summary]';
}
if($ev['desc'])
if ($ev['desc']) {
$o .= '[event-description]' . $ev['desc'] . '[/event-description]';
}
if($ev['start'])
if ($ev['start']) {
$o .= '[event-start]' . $ev['start'] . '[/event-start]';
}
if(($ev['finish']) && (! $ev['nofinish']))
if (($ev['finish']) && (! $ev['nofinish'])) {
$o .= '[event-finish]' . $ev['finish'] . '[/event-finish]';
}
if($ev['location'])
if ($ev['location']) {
$o .= '[event-location]' . $ev['location'] . '[/event-location]';
}
if($ev['adjust'])
if ($ev['adjust']) {
$o .= '[event-adjust]' . $ev['adjust'] . '[/event-adjust]';
}
return $o;
}
function bbtovcal($s) {
$o = '';
$ev = bbtoevent($s);
if($ev['desc'])
if ($ev['desc']) {
$o = format_event_html($ev);
}
return $o;
}
function bbtoevent($s) {
$ev = array();
$match = '';
if(preg_match("/\[event\-summary\](.*?)\[\/event\-summary\]/is",$s,$match))
if (preg_match("/\[event\-summary\](.*?)\[\/event\-summary\]/is", $s, $match)) {
$ev['summary'] = $match[1];
$match = '';
if(preg_match("/\[event\-description\](.*?)\[\/event\-description\]/is",$s,$match))
$ev['desc'] = $match[1];
$match = '';
if(preg_match("/\[event\-start\](.*?)\[\/event\-start\]/is",$s,$match))
$ev['start'] = $match[1];
$match = '';
if(preg_match("/\[event\-finish\](.*?)\[\/event\-finish\]/is",$s,$match))
$ev['finish'] = $match[1];
$match = '';
if(preg_match("/\[event\-location\](.*?)\[\/event\-location\]/is",$s,$match))
$ev['location'] = $match[1];
$match = '';
if(preg_match("/\[event\-adjust\](.*?)\[\/event\-adjust\]/is",$s,$match))
$ev['adjust'] = $match[1];
$ev['nofinish'] = (((x($ev, 'start') && $ev['start']) && (!x($ev, 'finish') || !$ev['finish'])) ? 1 : 0);
return $ev;
}
$match = '';
if (preg_match("/\[event\-description\](.*?)\[\/event\-description\]/is", $s, $match)) {
$ev['desc'] = $match[1];
}
$match = '';
if (preg_match("/\[event\-start\](.*?)\[\/event\-start\]/is", $s, $match)) {
$ev['start'] = $match[1];
}
$match = '';
if (preg_match("/\[event\-finish\](.*?)\[\/event\-finish\]/is", $s, $match)) {
$ev['finish'] = $match[1];
}
$match = '';
if (preg_match("/\[event\-location\](.*?)\[\/event\-location\]/is", $s, $match)) {
$ev['location'] = $match[1];
}
$match = '';
if (preg_match("/\[event\-adjust\](.*?)\[\/event\-adjust\]/is", $s, $match)) {
$ev['adjust'] = $match[1];
}
$ev['nofinish'] = (((x($ev, 'start') && $ev['start']) && (!x($ev, 'finish') || !$ev['finish'])) ? 1 : 0);
return $ev;
}
@ -212,21 +236,22 @@ function sort_by_date($a) {
return $a;
}
function ev_compare($a,$b) {
$date_a = (($a['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$a['start']) : $a['start']);
$date_b = (($b['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$b['start']) : $b['start']);
$date_a = (($a['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $a['start']) : $a['start']);
$date_b = (($b['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $b['start']) : $b['start']);
if($date_a === $date_b)
return strcasecmp($a['desc'],$b['desc']);
if ($date_a === $date_b) {
return strcasecmp($a['desc'], $b['desc']);
}
return strcmp($date_a,$date_b);
return strcmp($date_a, $date_b);
}
function event_delete($event_id) {
if ($event_id == 0)
if ($event_id == 0) {
return;
}
q("DELETE FROM `event` WHERE `id` = %d", intval($event_id));
logger("Deleted event ".$event_id, LOGGER_DEBUG);
@ -234,37 +259,39 @@ function event_delete($event_id) {
function event_store($arr) {
require_once('include/datetime.php');
require_once('include/items.php');
require_once('include/bbcode.php');
require_once 'include/datetime.php';
require_once 'include/items.php';
require_once 'include/bbcode.php';
$a = get_app();
$arr['created'] = (($arr['created']) ? $arr['created'] : datetime_convert());
$arr['edited'] = (($arr['edited']) ? $arr['edited'] : datetime_convert());
$arr['type'] = (($arr['type']) ? $arr['type'] : 'event' );
$arr['cid'] = ((intval($arr['cid'])) ? intval($arr['cid']) : 0);
$arr['uri'] = (x($arr,'uri') ? $arr['uri'] : item_new_uri($a->get_hostname(),$arr['uid']));
$arr['private'] = ((x($arr,'private')) ? intval($arr['private']) : 0);
$arr['created'] = (($arr['created']) ? $arr['created'] : datetime_convert());
$arr['edited'] = (($arr['edited']) ? $arr['edited'] : datetime_convert());
$arr['type'] = (($arr['type']) ? $arr['type'] : 'event' );
$arr['cid'] = ((intval($arr['cid'])) ? intval($arr['cid']) : 0);
$arr['uri'] = (x($arr, 'uri') ? $arr['uri'] : item_new_uri($a->get_hostname(), $arr['uid']));
$arr['private'] = ((x($arr, 'private')) ? intval($arr['private']) : 0);
$arr['guid'] = get_guid(32);
if($arr['cid'])
if ($arr['cid']) {
$c = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($arr['cid']),
intval($arr['uid'])
);
else
} else {
$c = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
intval($arr['uid'])
);
}
if(count($c))
if (dbm::is_result($c)) {
$contact = $c[0];
}
// Existing event being modified
if($arr['id']) {
if ($arr['id']) {
// has the event actually changed?
@ -272,7 +299,7 @@ function event_store($arr) {
intval($arr['id']),
intval($arr['uid'])
);
if((! dbm::is_result($r)) || ($r[0]['edited'] === $arr['edited'])) {
if ((! dbm::is_result($r)) || ($r[0]['edited'] === $arr['edited'])) {
// Nothing has changed. Grab the item id to return.
@ -280,7 +307,7 @@ function event_store($arr) {
intval($arr['id']),
intval($arr['uid'])
);
return((dbm::is_result($r)) ? $r[0]['id'] : 0);
return ((dbm::is_result($r)) ? $r[0]['id'] : 0);
}
// The event changed. Update it.
@ -318,7 +345,6 @@ function event_store($arr) {
$object .= '<content>' . xmlify(format_event_bbcode($arr)) . '</content>';
$object .= '</object>' . "\n";
q("UPDATE `item` SET `body` = '%s', `object` = '%s', `edited` = '%s' WHERE `id` = %d AND `uid` = %d",
dbesc(format_event_bbcode($arr)),
dbesc($object),
@ -328,8 +354,9 @@ function event_store($arr) {
);
$item_id = $r[0]['id'];
} else
} else {
$item_id = 0;
}
call_hooks("event_updated", $arr['id']);
@ -366,8 +393,9 @@ function event_store($arr) {
dbesc($arr['uri']),
intval($arr['uid'])
);
if (dbm::is_result($r))
if (dbm::is_result($r)) {
$event = $r[0];
}
$item_arr = array();
@ -399,7 +427,7 @@ function event_store($arr) {
$item_arr['body'] = format_event_bbcode($event);
$item_arr['object'] = '<object><type>' . xmlify(ACTIVITY_OBJ_EVENT) . '</type><title></title><id>' . xmlify($arr['uri']) . '</id>';
$item_arr['object'] = '<object><type>' . xmlify(ACTIVITY_OBJ_EVENT) . '</type><title></title><id>' . xmlify($arr['uri']) . '</id>';
$item_arr['object'] .= '<content>' . xmlify(format_event_bbcode($event)) . '</content>';
$item_arr['object'] .= '</object>' . "\n";
@ -412,7 +440,7 @@ function event_store($arr) {
// $plink = App::get_baseurl() . '/display/' . $r[0]['nickname'] . '/' . $item_id;
if($item_id) {
if ($item_id) {
//q("UPDATE `item` SET `plink` = '%s', `event-id` = %d WHERE `uid` = %d AND `id` = %d",
// dbesc($plink),
// intval($event['id']),
@ -433,12 +461,17 @@ function event_store($arr) {
}
function get_event_strings() {
// First day of the week (0 = Sunday)
$firstDay = get_pconfig(local_user(),'system','first_day_of_week');
if ($firstDay === false) $firstDay=0;
$firstDay = get_pconfig(local_user(), 'system', 'first_day_of_week');
if ($firstDay === false) {
$firstDay = 0;
}
$i18n = array(
"firstDay" => $firstDay,
"allday" => t("all-day"),
"Sun" => t("Sun"),
"Mon" => t("Mon"),
"Tue" => t("Tue"),
@ -446,13 +479,15 @@ function get_event_strings() {
"Thu" => t("Thu"),
"Fri" => t("Fri"),
"Sat" => t("Sat"),
"Sunday" => t("Sunday"),
"Monday" => t("Monday"),
"Tuesday" => t("Tuesday"),
"Sunday" => t("Sunday"),
"Monday" => t("Monday"),
"Tuesday" => t("Tuesday"),
"Wednesday" => t("Wednesday"),
"Thursday" => t("Thursday"),
"Friday" => t("Friday"),
"Saturday" => t("Saturday"),
"Thursday" => t("Thursday"),
"Friday" => t("Friday"),
"Saturday" => t("Saturday"),
"Jan" => t("Jan"),
"Feb" => t("Feb"),
"Mar" => t("Mar"),
@ -465,47 +500,49 @@ function get_event_strings() {
"Oct" => t("Oct"),
"Nov" => t("Nov"),
"Dec" => t("Dec"),
"January" => t("January"),
"February" => t("February"),
"March" => t("March"),
"April" => t("April"),
"May" => t("May"),
"June" => t("June"),
"July" => t("July"),
"August" => t("August"),
"January" => t("January"),
"February" => t("February"),
"March" => t("March"),
"April" => t("April"),
"May" => t("May"),
"June" => t("June"),
"July" => t("July"),
"August" => t("August"),
"September" => t("September"),
"October" => t("October"),
"November" => t("November"),
"December" => t("December"),
"October" => t("October"),
"November" => t("November"),
"December" => t("December"),
"today" => t("today"),
"month" => t("month"),
"week" => t("week"),
"day" => t("day"),
"allday" => t("all-day"),
"week" => t("week"),
"day" => t("day"),
"noevent" => t("No events to display"),
"dtstart_label" => t("Starts:"),
"dtend_label" => t("Finishes:"),
"dtstart_label" => t("Starts:"),
"dtend_label" => t("Finishes:"),
"location_label" => t("Location:")
);
return $i18n;
}
/// @todo We should replace this with a separate update function if there is some time left
/**
* @brief Removes duplicated birthday events
*
* @param array $dates Array of possibly duplicated events
* @return array Cleaned events
*
* @todo We should replace this with a separate update function if there is some time left
*/
function event_remove_duplicates($dates) {
$dates2 = array();
foreach ($dates AS $date) {
if ($date['type'] == 'birthday') {
$dates2[$date['uid']."-".$date['cid']."-".$date['start']] = $date;
$dates2[$date['uid'] . "-" . $date['cid'] . "-" . $date['start']] = $date;
} else {
$dates2[] = $date;
}
@ -524,10 +561,11 @@ function event_remove_duplicates($dates) {
*/
function event_by_id($owner_uid = 0, $event_params, $sql_extra = '') {
// ownly allow events if there is a valid owner_id
if($owner_uid == 0)
if ($owner_uid == 0) {
return;
}
// query for the event by event id
// Query for the event by event id
$r = q("SELECT `event`.*, `item`.`id` AS `itemid`,`item`.`plink`,
`item`.`author-name`, `item`.`author-avatar`, `item`.`author-link` FROM `event`
LEFT JOIN `item` ON `item`.`event-id` = `event`.`id` AND `item`.`uid` = `event`.`uid`
@ -556,11 +594,12 @@ function event_by_id($owner_uid = 0, $event_params, $sql_extra = '') {
* @return array Query results
*/
function events_by_date($owner_uid = 0, $event_params, $sql_extra = '') {
// ownly allow events if there is a valid owner_id
if($owner_uid == 0)
// Only allow events if there is a valid owner_id
if($owner_uid == 0) {
return;
}
// query for the event by date
// Query for the event by date
$r = q("SELECT `event`.*, `item`.`id` AS `itemid`,`item`.`plink`,
`item`.`author-name`, `item`.`author-avatar`, `item`.`author-link` FROM `event`
LEFT JOIN `item` ON `item`.`event-id` = `event`.`id` AND `item`.`uid` = `event`.`uid`
@ -595,46 +634,54 @@ function process_events($arr) {
$last_date = '';
$fmt = t('l, F j');
if (count($arr)) {
foreach($arr as $rr) {
foreach ($arr as $rr) {
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'j') : datetime_convert('UTC','UTC',$rr['start'],'j'));
$d = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], $fmt) : datetime_convert('UTC','UTC',$rr['start'],$fmt));
$j = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['start'], 'j') : datetime_convert('UTC', 'UTC', $rr['start'], 'j'));
$d = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['start'], $fmt) : datetime_convert('UTC', 'UTC', $rr['start'], $fmt));
$d = day_translate($d);
$start = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'c') : datetime_convert('UTC','UTC',$rr['start'],'c'));
if ($rr['nofinish']){
$start = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['start'], 'c') : datetime_convert('UTC', 'UTC', $rr['start'], 'c'));
if ($rr['nofinish']) {
$end = null;
} else {
$end = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['finish'], 'c') : datetime_convert('UTC','UTC',$rr['finish'],'c'));
$end = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['finish'], 'c') : datetime_convert('UTC', 'UTC', $rr['finish'], 'c'));
}
$is_first = ($d !== $last_date);
$last_date = $d;
$edit = ((! $rr['cid']) ? array(App::get_baseurl().'/events/event/'.$rr['id'],t('Edit event'),'','') : null);
$title = strip_tags(html_entity_decode(bbcode($rr['summary']),ENT_QUOTES,'UTF-8'));
if(! $title) {
list($title, $_trash) = explode("<br",bbcode($rr['desc']),2);
$title = strip_tags(html_entity_decode($title,ENT_QUOTES,'UTF-8'));
// Show edit and drop actions only if the user is the owner of the event and the event
// is a real event (no bithdays)
if (local_user() && local_user() == $rr['uid'] && $rr['type'] == 'event') {
$edit = ((! $rr['cid']) ? array(App::get_baseurl() . '/events/event/' . $rr['id'], t('Edit event'), '', '') : null);
$drop = array(App::get_baseurl() . '/events/drop/' . $rr['id'], t('Delete event'), '', '');
}
$title = strip_tags(html_entity_decode(bbcode($rr['summary']), ENT_QUOTES, 'UTF-8'));
if (! $title) {
list($title, $_trash) = explode("<br", bbcode($rr['desc']), 2);
$title = strip_tags(html_entity_decode($title, ENT_QUOTES, 'UTF-8'));
}
$html = format_event_html($rr);
$rr['desc'] = bbcode($rr['desc']);
$rr['location'] = bbcode($rr['location']);
$events[] = array(
'id'=>$rr['id'],
'start'=> $start,
'end' => $end,
'id' => $rr['id'],
'start' => $start,
'end' => $end,
'allDay' => false,
'title' => $title,
'title' => $title,
'j' => $j,
'd' => $d,
'is_first'=>$is_first,
'item'=>$rr,
'html'=>$html,
'plink' => array($rr['plink'],t('link to source'),'',''),
'j' => $j,
'd' => $d,
'edit' => $edit,
'drop' => $drop,
'is_first' => $is_first,
'item' => $rr,
'html' => $html,
'plink' => array($rr['plink'], t('link to source'), '', ''),
);
}
}
@ -652,34 +699,36 @@ function process_events($arr) {
* @return string Content according to selected export format
*/
function event_format_export ($events, $format = 'ical', $timezone) {
if(! ((is_array($events)) && count($events)))
if (! ((is_array($events)) && count($events))) {
return;
}
switch ($format) {
// format the exported data as a CSV file
// Format the exported data as a CSV file
case "csv":
header("Content-type: text/csv");
$o = '"Subject", "Start Date", "Start Time", "Description", "End Date", "End Time", "Location"' . PHP_EOL;
foreach ($events as $event) {
/// @todo the time / date entries don't include any information about the
// timezone the event is scheduled in :-/
/// @todo The time / date entries don't include any information about the
/// timezone the event is scheduled in :-/
$tmp1 = strtotime($event['start']);
$tmp2 = strtotime($event['finish']);
$time_format = "%H:%M:%S";
$date_format = "%Y-%m-%d";
$o .= '"'.$event['summary'].'", "'.strftime($date_format, $tmp1) .
'", "'.strftime($time_format, $tmp1).'", "'.$event['desc'] .
'", "'.strftime($date_format, $tmp2) .
'", "'.strftime($time_format, $tmp2) .
'", "'.$event['location'].'"' . PHP_EOL;
$o .= '"' . $event['summary'] . '", "' . strftime($date_format, $tmp1) .
'", "' . strftime($time_format, $tmp1) . '", "' . $event['desc'] .
'", "' . strftime($date_format, $tmp2) .
'", "' . strftime($time_format, $tmp2) .
'", "' . $event['location'] . '"' . PHP_EOL;
}
break;
// format the exported data as a ics file
// Format the exported data as a ics file
case "ical":
header("Content-type: text/ics");
$o = 'BEGIN:VCALENDAR'. PHP_EOL
$o = 'BEGIN:VCALENDAR' . PHP_EOL
. 'VERSION:2.0' . PHP_EOL
. 'PRODID:-//friendica calendar export//0.1//EN' . PHP_EOL;
/// @todo include timezone informations in cases were the time is not in UTC
@ -691,35 +740,43 @@ function event_format_export ($events, $format = 'ical', $timezone) {
// but test your solution against http://icalvalid.cloudapp.net/
// also long lines SHOULD be split at 75 characters length
foreach ($events as $event) {
if ($event['adjust'] == 1) {
$UTC = 'Z';
} else {
$UTC = '';
}
$o .= 'BEGIN:VEVENT' . PHP_EOL;
if ($event[start]) {
if ($event['start']) {
$tmp = strtotime($event['start']);
$dtformat = "%Y%m%dT%H%M%S".$UTC;
$o .= 'DTSTART:'.strftime($dtformat, $tmp).PHP_EOL;
$dtformat = "%Y%m%dT%H%M%S" . $UTC;
$o .= 'DTSTART:' . strftime($dtformat, $tmp) . PHP_EOL;
}
if (!$event['nofinish']) {
$tmp = strtotime($event['finish']);
$dtformat = "%Y%m%dT%H%M%S".$UTC;
$o .= 'DTEND:'.strftime($dtformat, $tmp).PHP_EOL;
$dtformat = "%Y%m%dT%H%M%S" . $UTC;
$o .= 'DTEND:' . strftime($dtformat, $tmp) . PHP_EOL;
}
if ($event['summary'])
if ($event['summary']) {
$tmp = $event['summary'];
$tmp = str_replace(PHP_EOL, PHP_EOL.' ',$tmp);
$tmp = str_replace(PHP_EOL, PHP_EOL . ' ', $tmp);
$tmp = addcslashes($tmp, ',;');
$o .= 'SUMMARY:' . $tmp . PHP_EOL;
if ($event['desc'])
}
if ($event['desc']) {
$tmp = $event['desc'];
$tmp = str_replace(PHP_EOL, PHP_EOL.' ',$tmp);
$tmp = str_replace(PHP_EOL, PHP_EOL . ' ', $tmp);
$tmp = addcslashes($tmp, ',;');
$o .= 'DESCRIPTION:' . $tmp . PHP_EOL;
}
if ($event['location']) {
$tmp = $event['location'];
$tmp = str_replace(PHP_EOL, PHP_EOL.' ',$tmp);
$tmp = str_replace(PHP_EOL, PHP_EOL . ' ', $tmp);
$tmp = addcslashes($tmp, ',;');
$o .= 'LOCATION:' . $tmp . PHP_EOL;
}
@ -750,16 +807,18 @@ function event_format_export ($events, $format = 'ical', $timezone) {
* @return array Query results
*/
function events_by_uid($uid = 0, $sql_extra = '') {
if($uid == 0)
if ($uid == 0) {
return;
}
// The permission condition if no condition was transmitted
if($sql_extra == '')
if ($sql_extra == '') {
$sql_extra = " AND `allow_cid` = '' AND `allow_gid` = '' ";
}
// does the user who requests happen to be the owner of the events
// requested? then show all of your events, otherwise only those that
// don't have limitations set in allow_cid and allow_gid
// Does the user who requests happen to be the owner of the events
// requested? then show all of your events, otherwise only those that
// don't have limitations set in allow_cid and allow_gid
if (local_user() == $uid) {
$r = q("SELECT `start`, `finish`, `adjust`, `summary`, `desc`, `location`, `nofinish`
FROM `event` WHERE `uid`= %d AND `cid` = 0 ",
@ -772,8 +831,9 @@ function events_by_uid($uid = 0, $sql_extra = '') {
);
}
if (dbm::is_result($r))
if (dbm::is_result($r)) {
return $r;
}
}
/**
@ -792,25 +852,28 @@ function event_export($uid, $format = 'ical') {
$process = false;
// we are allowed to show events
// We are allowed to show events
// get the timezone the user is in
$r = q("SELECT `timezone` FROM `user` WHERE `uid` = %d LIMIT 1", intval($uid));
if (dbm::is_result($r))
if (dbm::is_result($r)) {
$timezone = $r[0]['timezone'];
}
// get all events which are owned by a uid (respects permissions);
// Get all events which are owned by a uid (respects permissions);
$events = events_by_uid($uid);
// we have the events that are available for the requestor
// now format the output according to the requested format
if(count($events))
// We have the events that are available for the requestor
// now format the output according to the requested format
if (count($events)) {
$res = event_format_export($events, $format, $timezone);
}
// If there are results the precess was successfull
if(x($res))
if (x($res)) {
$process = true;
}
// get the file extension for the format
// Get the file extension for the format
switch ($format) {
case "ical":
$file_ext = "ics";
@ -825,10 +888,10 @@ function event_export($uid, $format = 'ical') {
}
$arr = array(
'success' => $process,
'format' => $format,
'success' => $process,
'format' => $format,
'extension' => $file_ext,
'content' => $res,
'content' => $res,
);
return $arr;
@ -851,8 +914,9 @@ function widget_events() {
// The permission testing is a little bit tricky because we have to respect many cases
// It's not the private events page (we don't get the $owner_uid for /events)
if(! local_user() && ! $owner_uid)
if (! local_user() && ! $owner_uid) {
return;
}
// Cal logged in user (test permission at foreign profile page)
// If the $owner uid is available we know it is part of one of the profile pages (like /cal)
@ -860,13 +924,15 @@ function widget_events() {
// or a foreign one. For foreign profile pages we need to check if the feature
// for exporting the cal is enabled (otherwise the widget would appear for logged in users
// on foreigen profile pages even if the widget is disabled)
if(intval($owner_uid) && local_user() !== $owner_uid && ! feature_enabled($owner_uid, "export_calendar"))
if (intval($owner_uid) && local_user() !== $owner_uid && ! feature_enabled($owner_uid, "export_calendar")) {
return;
}
// If it's a kind of profile page (intval($owner_uid)) return if the user not logged in and
// export feature isn't enabled
if(intval($owner_uid) && ! local_user() && ! feature_enabled($owner_uid, "export_calendar"))
if (intval($owner_uid) && ! local_user() && ! feature_enabled($owner_uid, "export_calendar")) {
return;
}
return replace_macros(get_markup_template("events_aside.tpl"), array(
'$etitle' => t("Export"),
@ -874,5 +940,4 @@ function widget_events() {
'$export_csv' => t("Export calendar as csv"),
'$user' => $user
));
}

View file

@ -2,32 +2,13 @@
use \Friendica\Core\Config;
require_once("boot.php");
function expire_run(&$argv, &$argc){
global $a, $db;
global $a;
if(is_null($a)) {
$a = new App;
}
if(is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once('include/session.php');
require_once('include/datetime.php');
require_once('include/items.php');
require_once('include/Contact.php');
Config::load();
$a->set_baseurl(get_config('system','url'));
// physically remove anything that has been deleted for more than two months
$r = q("delete from item where deleted = 1 and changed < UTC_TIMESTAMP() - INTERVAL 60 DAY");
@ -53,8 +34,3 @@ function expire_run(&$argv, &$argc){
return;
}
if (array_search(__file__,get_included_files())===0){
expire_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -2,36 +2,14 @@
use \Friendica\Core\Config;
require_once("boot.php");
require_once('include/Scrape.php');
require_once('include/socgraph.php');
require_once('include/datetime.php');
function gprobe_run(&$argv, &$argc){
global $a, $db;
if(is_null($a)) {
$a = new App;
}
if(is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once('include/session.php');
require_once('include/datetime.php');
Config::load();
$a->set_baseurl(get_config('system','url'));
load_hooks();
if($argc != 2)
if ($argc != 2) {
return;
}
$url = hex2bin($argv[1]);
$r = q("SELECT `id`, `url`, `network` FROM `gcontact` WHERE `nurl` = '%s' ORDER BY `id` LIMIT 1",
@ -74,8 +52,3 @@ function gprobe_run(&$argv, &$argc){
logger("gprobe end for ".normalise_link($url), LOGGER_DEBUG);
return;
}
if (array_search(__file__,get_included_files())===0){
gprobe_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -652,7 +652,7 @@ function advanced_profile(App $a) {
$profile['marital']['with'] = $a->profile['with'];
}
if (strlen($a->profile['howlong']) && $a->profile['howlong'] !== '0000-00-00 00:00:00') {
if (strlen($a->profile['howlong']) && $a->profile['howlong'] >= NULL_DATE) {
$profile['howlong'] = relative_date($a->profile['howlong'], t('for %1$d %2$s'));
}

View file

@ -68,7 +68,8 @@ function block_on_function_lock($fn_name, $wait_sec = 2, $timeout = 30) {
if(! function_exists('unlock_function')) {
function unlock_function($fn_name) {
$r = q("UPDATE `locks` SET `locked` = 0, `created` = '0000-00-00 00:00:00' WHERE `name` = '%s'",
$r = q("UPDATE `locks` SET `locked` = 0, `created` = '%s' WHERE `name` = '%s'",
dbesc(NULL_DATE),
dbesc($fn_name)
);

View file

@ -72,8 +72,9 @@ function z_fetch_url($url,$binary = false, &$redirects = 0, $opts=array()) {
$a = get_app();
$ch = @curl_init($url);
if(($redirects > 8) || (! $ch))
return false;
if(($redirects > 8) || (! $ch)) {
return $ret;
}
@curl_setopt($ch, CURLOPT_HEADER, true);

View file

@ -2,12 +2,11 @@
use \Friendica\Core\Config;
require_once("boot.php");
require_once('include/queue_fn.php');
require_once('include/html2plain.php');
require_once("include/Scrape.php");
require_once('include/Scrape.php');
require_once('include/diaspora.php');
require_once("include/ostatus.php");
require_once('include/ostatus.php');
require_once('include/salmon.php');
/*
@ -44,35 +43,17 @@ require_once('include/salmon.php');
function notifier_run(&$argv, &$argc){
global $a, $db;
global $a;
if (is_null($a)) {
$a = new App;
}
if (is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
}
require_once("include/session.php");
require_once("include/datetime.php");
require_once('include/datetime.php');
require_once('include/items.php');
require_once('include/bbcode.php');
require_once('include/email.php');
Config::load();
load_hooks();
if ($argc < 3) {
return;
}
$a->set_baseurl(get_config('system','url'));
logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG);
$cmd = $argv[1];
@ -490,79 +471,22 @@ function notifier_run(&$argv, &$argc){
if ($relocate) {
$r = $recipients_relocate;
} else {
$r = q("SELECT * FROM `contact` WHERE `id` IN (%s) AND NOT `blocked` AND NOT `pending` AND NOT `archive`".$sql_extra,
$r = q("SELECT `id`, `url`, `network`, `self` FROM `contact`
WHERE `id` IN (%s) AND NOT `blocked` AND NOT `pending` AND NOT `archive`".$sql_extra,
dbesc($recip_str)
);
}
$interval = ((get_config('system','delivery_interval') === false) ? 2 : intval(get_config('system','delivery_interval')));
// If we are using the worker we don't need a delivery interval
if (get_config("system", "worker")) {
$interval = false;
}
// delivery loop
if (dbm::is_result($r)) {
foreach ($r as $contact) {
if (!$contact['self']) {
if (($contact['network'] === NETWORK_DIASPORA) && ($public_message)) {
continue;
}
q("INSERT INTO `deliverq` (`cmd`,`item`,`contact`) VALUES ('%s', %d, %d)",
dbesc($cmd),
intval($item_id),
intval($contact['id'])
);
}
}
// This controls the number of deliveries to execute with each separate delivery process.
// By default we'll perform one delivery per process. Assuming a hostile shared hosting
// provider, this provides the greatest chance of deliveries if processes start getting
// killed. We can also space them out with the delivery_interval to also help avoid them
// getting whacked.
// If $deliveries_per_process > 1, we will chain this number of multiple deliveries
// together into a single process. This will reduce the overall number of processes
// spawned for each delivery, but they will run longer.
// When using the workerqueue, we don't need this functionality.
$deliveries_per_process = intval(get_config('system','delivery_batch_count'));
if (($deliveries_per_process <= 0) OR get_config("system", "worker")) {
$deliveries_per_process = 1;
}
$this_batch = array();
for ($x = 0; $x < count($r); $x ++) {
$contact = $r[$x];
if ($contact['self']) {
continue;
}
logger("Deliver ".$target_item["guid"]." to ".$contact['url']." via network ".$contact['network'], LOGGER_DEBUG);
// potentially more than one recipient. Start a new process and space them out a bit.
// we will deliver single recipient types of message and email recipients here.
$this_batch[] = $contact['id'];
if (count($this_batch) >= $deliveries_per_process) {
proc_run(PRIORITY_HIGH,'include/delivery.php',$cmd,$item_id,$this_batch);
$this_batch = array();
if ($interval) {
@time_sleep_until(microtime(true) + (float) $interval);
}
}
continue;
}
// be sure to pick up any stragglers
if (count($this_batch)) {
proc_run(PRIORITY_HIGH,'include/delivery.php',$cmd,$item_id,$this_batch);
proc_run(PRIORITY_HIGH,'include/delivery.php', $cmd, $item_id, $contact['id']);
}
}
@ -614,18 +538,6 @@ function notifier_run(&$argv, &$argc){
if (dbm::is_result($r)) {
logger('pubdeliver '.$target_item["guid"].': '.print_r($r,true), LOGGER_DEBUG);
// throw everything into the queue in case we get killed
foreach ($r as $rr) {
if ((! $mail) && (! $fsuggest) && (! $followup)) {
q("INSERT INTO `deliverq` (`cmd`,`item`,`contact`) VALUES ('%s', %d, %d)
ON DUPLICATE KEY UPDATE `cmd` = '%s', `item` = %d, `contact` = %d",
dbesc($cmd), intval($item_id), intval($rr['id']),
dbesc($cmd), intval($item_id), intval($rr['id'])
);
}
}
foreach ($r as $rr) {
// except for Diaspora batch jobs
@ -639,9 +551,6 @@ function notifier_run(&$argv, &$argc){
if ((! $mail) && (! $fsuggest) && (! $followup)) {
logger('notifier: delivery agent: '.$rr['name'].' '.$rr['id'].' '.$rr['network'].' '.$target_item["guid"]);
proc_run(PRIORITY_HIGH,'include/delivery.php',$cmd,$item_id,$rr['id']);
if ($interval) {
@time_sleep_until(microtime(true) + (float) $interval);
}
}
}
}
@ -694,9 +603,3 @@ function notifier_run(&$argv, &$argc){
return;
}
if (array_search(__file__,get_included_files())===0){
notifier_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -17,10 +17,10 @@ function oembed_replacecb($matches){
/**
* @brief Get data from an URL to embed its content.
*
*
* @param string $embedurl The URL from which the data should be fetched.
* @param bool $no_rich_type If set to true rich type content won't be fetched.
*
*
* @return bool|object Returns object with embed content or false if no embedable
* content exists
*/
@ -41,8 +41,8 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){
// These media files should now be caught in bbcode.php
// left here as a fallback in case this is called from another source
$noexts = array("mp3","mp4","ogg","ogv","oga","ogm","webm");
$ext = pathinfo(strtolower($embedurl),PATHINFO_EXTENSION);
$noexts = array("mp3", "mp4", "ogg", "ogv", "oga", "ogm", "webm");
$ext = pathinfo(strtolower($embedurl), PATHINFO_EXTENSION);
if (is_null($txt)) {
@ -74,21 +74,10 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){
}
}
if ($txt==false || $txt=="") {
$embedly = Config::get("system", "embedly");
if ($embedly != "") {
// try embedly service
$ourl = "https://api.embed.ly/1/oembed?key=".$embedly."&url=".urlencode($embedurl);
$txt = fetch_url($ourl);
$txt = trim($txt);
logger("oembed_fetch_url: ".$txt, LOGGER_DEBUG);
}
}
$txt=trim($txt);
if ($txt[0]!="{") {
$txt='{"type":"error"}';
if ($txt[0] != "{") {
$txt = '{"type":"error"}';
} else { //save in cache
$j = json_decode($txt);
if ($j->type != "error") {

View file

@ -2,8 +2,7 @@
use \Friendica\Core\Config;
require_once("boot.php");
require_once("include/follow.php");
require_once('include/follow.php');
function RemoveReply($subject) {
while (in_array(strtolower(substr($subject, 0, 3)), array("re:", "aw:")))
@ -13,20 +12,8 @@ function RemoveReply($subject) {
}
function onepoll_run(&$argv, &$argc){
global $a, $db;
global $a;
if (is_null($a)) {
$a = new App;
}
if (is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once('include/session.php');
require_once('include/datetime.php');
require_once('include/items.php');
require_once('include/Contact.php');
@ -34,12 +21,6 @@ function onepoll_run(&$argv, &$argc){
require_once('include/socgraph.php');
require_once('include/queue_fn.php');
Config::load();
$a->set_baseurl(get_config('system','url'));
load_hooks();
logger('onepoll: start');
$manual_id = 0;
@ -61,13 +42,6 @@ function onepoll_run(&$argv, &$argc){
return;
}
// Don't check this stuff if the function is called by the poller
if (App::callstack() != "poller_run") {
if (App::is_already_running('onepoll'.$contact_id, '', 540)) {
return;
}
}
$d = datetime_convert();
// Only poll from those with suitable relationships,
@ -159,7 +133,7 @@ function onepoll_run(&$argv, &$argc){
logger("onepoll: poll: ({$contact['id']}) IMPORTER: {$importer['name']}, CONTACT: {$contact['name']}");
$last_update = (($contact['last-update'] === '0000-00-00 00:00:00')
$last_update = (($contact['last-update'] <= NULL_DATE)
? datetime_convert('UTC','UTC','now - 7 days', ATOM_TIME)
: datetime_convert('UTC','UTC',$contact['last-update'], ATOM_TIME)
);
@ -265,7 +239,7 @@ function onepoll_run(&$argv, &$argc){
intval($contact['id'])
);
mark_for_death($contact);
} elseif ($contact['term-date'] != '0000-00-00 00:00:00') {
} elseif ($contact['term-date'] > NULL_DATE) {
logger("poller: $url back from the dead - removing mark for death");
unmark_for_death($contact);
}
@ -697,8 +671,3 @@ function onepoll_run(&$argv, &$argc){
return;
}
if (array_search(__file__,get_included_files())===0) {
onepoll_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -35,6 +35,10 @@ function poller_run($argv, $argc){
return;
}
$a->set_baseurl(Config::get('system', 'url'));
load_hooks();
$a->start_process();
if (poller_max_connections_reached()) {
@ -353,18 +357,18 @@ function poller_max_connections_reached() {
*
*/
function poller_kill_stale_workers() {
$r = q("SELECT `pid`, `executed`, `priority`, `parameter` FROM `workerqueue` WHERE `executed` != '0000-00-00 00:00:00'");
$r = q("SELECT `pid`, `executed`, `priority`, `parameter` FROM `workerqueue` WHERE `executed` > '%s'", dbesc(NULL_DATE));
if (!dbm::is_result($r)) {
// No processing here needed
return;
}
foreach($r AS $pid)
if (!posix_kill($pid["pid"], 0))
q("UPDATE `workerqueue` SET `executed` = '0000-00-00 00:00:00', `pid` = 0 WHERE `pid` = %d",
intval($pid["pid"]));
else {
foreach ($r AS $pid) {
if (!posix_kill($pid["pid"], 0)) {
q("UPDATE `workerqueue` SET `executed` = '%s', `pid` = 0 WHERE `pid` = %d",
dbesc(NULL_DATE), intval($pid["pid"]));
} else {
// Kill long running processes
// Check if the priority is in a valid range
@ -387,14 +391,17 @@ function poller_kill_stale_workers() {
// We killed the stale process.
// To avoid a blocking situation we reschedule the process at the beginning of the queue.
// Additionally we are lowering the priority.
q("UPDATE `workerqueue` SET `executed` = '0000-00-00 00:00:00', `created` = '%s',
q("UPDATE `workerqueue` SET `executed` = '%s', `created` = '%s',
`priority` = %d, `pid` = 0 WHERE `pid` = %d",
dbesc(NULL_DATE),
dbesc(datetime_convert()),
intval(PRIORITY_NEGLIGIBLE),
intval($pid["pid"]));
} else
} else {
logger("Worker process ".$pid["pid"]." (".implode(" ", $argv).") now runs for ".round($duration)." of ".$max_duration." allowed minutes. That's okay.", LOGGER_DEBUG);
}
}
}
}
/**
@ -421,15 +428,15 @@ function poller_too_much_workers() {
$slope = $maxworkers / pow($maxsysload, $exponent);
$queues = ceil($slope * pow(max(0, $maxsysload - $load), $exponent));
$s = q("SELECT COUNT(*) AS `total` FROM `workerqueue` WHERE `executed` = '0000-00-00 00:00:00'");
$s = q("SELECT COUNT(*) AS `total` FROM `workerqueue` WHERE `executed` <= '%s'", dbesc(NULL_DATE));
$entries = $s[0]["total"];
if (Config::get("system", "worker_fastlane", false) AND ($queues > 0) AND ($entries > 0) AND ($active >= $queues)) {
$s = q("SELECT `priority` FROM `workerqueue` WHERE `executed` = '0000-00-00 00:00:00' ORDER BY `priority` LIMIT 1");
$s = q("SELECT `priority` FROM `workerqueue` WHERE `executed` <= '%s' ORDER BY `priority` LIMIT 1", dbesc(NULL_DATE));
$top_priority = $s[0]["priority"];
$s = q("SELECT `id` FROM `workerqueue` WHERE `priority` <= %d AND `executed` != '0000-00-00 00:00:00' LIMIT 1",
intval($top_priority));
$s = q("SELECT `id` FROM `workerqueue` WHERE `priority` <= %d AND `executed` > '%s' LIMIT 1",
intval($top_priority), dbesc(NULL_DATE));
$high_running = dbm::is_result($s);
if (!$high_running AND ($top_priority > PRIORITY_UNDEFINED) AND ($top_priority < PRIORITY_NEGLIGIBLE)) {
@ -464,7 +471,7 @@ function poller_too_much_workers() {
// Are there fewer workers running as possible? Then fork a new one.
if (!Config::get("system", "worker_dont_fork") AND ($queues > ($active + 1)) AND ($entries > 1)) {
logger("Active workers: ".$active."/".$queues." Fork a new worker.", LOGGER_DEBUG);
$args = array("php", "include/poller.php", "no_cron");
$args = array("include/poller.php", "no_cron");
$a = get_app();
$a->proc_run($args);
}
@ -549,21 +556,25 @@ function poller_worker_process() {
if (poller_passing_slow($highest_priority)) {
// Are there waiting processes with a higher priority than the currently highest?
$r = q("SELECT * FROM `workerqueue`
WHERE `executed` = '0000-00-00 00:00:00' AND `priority` < %d
ORDER BY `priority`, `created` LIMIT 1", dbesc($highest_priority));
if (dbm::is_result($r))
WHERE `executed` <= '%s' AND `priority` < %d
ORDER BY `priority`, `created` LIMIT 1",
dbesc(NULL_DATE),
intval($highest_priority));
if (dbm::is_result($r)) {
return $r;
}
// Give slower processes some processing time
$r = q("SELECT * FROM `workerqueue`
WHERE `executed` = '0000-00-00 00:00:00' AND `priority` > %d
ORDER BY `priority`, `created` LIMIT 1", dbesc($highest_priority));
WHERE `executed` <= '%s' AND `priority` > %d
ORDER BY `priority`, `created` LIMIT 1",
dbesc(NULL_DATE),
intval($highest_priority));
}
// If there is no result (or we shouldn't pass lower processes) we check without priority limit
if (($highest_priority == 0) OR !dbm::is_result($r))
$r = q("SELECT * FROM `workerqueue` WHERE `executed` = '0000-00-00 00:00:00' ORDER BY `priority`, `created` LIMIT 1");
if (($highest_priority == 0) OR !dbm::is_result($r)) {
$r = q("SELECT * FROM `workerqueue` WHERE `executed` <= '%s' ORDER BY `priority`, `created` LIMIT 1", dbesc(NULL_DATE));
}
return $r;
}
@ -571,7 +582,7 @@ function poller_worker_process() {
* @brief Call the front end worker
*/
function call_worker() {
if (!Config::get("system", "frontend_worker") OR !Config::get("system", "worker")) {
if (!Config::get("system", "frontend_worker")) {
return;
}
@ -583,7 +594,7 @@ function call_worker() {
* @brief Call the front end worker if there aren't any active
*/
function call_worker_if_idle() {
if (!Config::get("system", "frontend_worker") OR !Config::get("system", "worker")) {
if (!Config::get("system", "frontend_worker")) {
return;
}
@ -610,7 +621,7 @@ function call_worker_if_idle() {
logger('Call poller', LOGGER_DEBUG);
$args = array("php", "include/poller.php", "no_cron");
$args = array("include/poller.php", "no_cron");
$a = get_app();
$a->proc_run($args);
return;

View file

@ -1,12 +1,31 @@
<?php
require_once("boot.php");
require_once("include/ostatus.php");
use \Friendica\Core\Config;
use \Friendica\Core\PConfig;
require_once('include/items.php');
require_once('include/ostatus.php');
function pubsubpublish_run(&$argv, &$argc){
if ($argc > 1) {
$pubsubpublish_id = intval($argv[1]);
} else {
// We'll push to each subscriber that has push > 0,
// i.e. there has been an update (set in notifier.php).
$r = q("SELECT `id`, `callback_url` FROM `push_subscriber` WHERE `push` > 0");
foreach ($r as $rr) {
logger("Publish feed to ".$rr["callback_url"], LOGGER_DEBUG);
proc_run(PRIORITY_HIGH, 'include/pubsubpublish.php', $rr["id"]);
}
}
handle_pubsubhubbub($pubsubpublish_id);
return;
}
function handle_pubsubhubbub($id) {
global $a, $db;
global $a;
$r = q("SELECT * FROM `push_subscriber` WHERE `id` = %d", intval($id));
if (!$r)
@ -54,70 +73,3 @@ function handle_pubsubhubbub($id) {
intval($rr['id']));
}
}
function pubsubpublish_run(&$argv, &$argc){
global $a, $db;
if(is_null($a)){
$a = new App;
}
if(is_null($db)){
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once('include/items.php');
Config::load();
// Don't check this stuff if the function is called by the poller
if (App::callstack() != "poller_run") {
if (App::is_already_running("pubsubpublish", "include/pubsubpublish.php", 540)) {
return;
}
}
$a->set_baseurl(get_config('system','url'));
load_hooks();
if ($argc > 1) {
$pubsubpublish_id = intval($argv[1]);
}
else {
// We'll push to each subscriber that has push > 0,
// i.e. there has been an update (set in notifier.php).
$r = q("SELECT `id`, `callback_url` FROM `push_subscriber` WHERE `push` > 0");
// Use the delivery interval that is also used for the notifier
$interval = Config::get("system", "delivery_interval", 2);
// If we are using the worker we don't need a delivery interval
if (get_config("system", "worker")) {
$interval = false;
}
foreach ($r as $rr) {
logger("Publish feed to ".$rr["callback_url"], LOGGER_DEBUG);
proc_run(PRIORITY_HIGH, 'include/pubsubpublish.php', $rr["id"]);
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
}
handle_pubsubhubbub($pubsubpublish_id);
return;
}
if (array_search(__file__,get_included_files())===0){
pubsubpublish_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -2,41 +2,16 @@
use \Friendica\Core\Config;
require_once("boot.php");
require_once('include/queue_fn.php');
require_once('include/dfrn.php');
require_once("include/datetime.php");
require_once('include/items.php');
require_once('include/bbcode.php');
require_once('include/socgraph.php');
require_once('include/cache.php');
function queue_run(&$argv, &$argc){
global $a, $db;
if (is_null($a)){
$a = new App;
}
if (is_null($db)){
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once("include/session.php");
require_once("include/datetime.php");
require_once('include/items.php');
require_once('include/bbcode.php');
require_once('include/socgraph.php');
Config::load();
// Don't check this stuff if the function is called by the poller
if (App::callstack() != "poller_run")
if (App::is_already_running('queue', 'include/queue.php', 540))
return;
$a->set_baseurl(get_config('system','url'));
load_hooks();
global $a;
if ($argc > 1) {
$queue_id = intval($argv[1]);
@ -54,30 +29,13 @@ function queue_run(&$argv, &$argc){
// Handling the pubsubhubbub requests
proc_run(PRIORITY_HIGH,'include/pubsubpublish.php');
$interval = ((get_config('system','delivery_interval') === false) ? 2 : intval(get_config('system','delivery_interval')));
// If we are using the worker we don't need a delivery interval
if (get_config("system", "worker"))
$interval = false;
$r = q("select * from deliverq where 1");
if ($r) {
foreach ($r as $rr) {
logger('queue: deliverq');
proc_run(PRIORITY_HIGH,'include/delivery.php',$rr['cmd'],$rr['item'],$rr['contact']);
if ($interval) {
time_sleep_until(microtime(true) + (float) $interval);
}
}
}
$r = q("SELECT `queue`.*, `contact`.`name`, `contact`.`uid` FROM `queue`
INNER JOIN `contact` ON `queue`.`cid` = `contact`.`id`
WHERE `queue`.`created` < UTC_TIMESTAMP() - INTERVAL 3 DAY");
if ($r) {
foreach ($r as $rr) {
logger('Removing expired queue item for ' . $rr['name'] . ', uid=' . $rr['uid']);
logger('Expired queue data :' . $rr['content'], LOGGER_DATA);
logger('Expired queue data: ' . $rr['content'], LOGGER_DATA);
}
q("DELETE FROM `queue` WHERE `created` < UTC_TIMESTAMP() - INTERVAL 3 DAY");
}
@ -86,158 +44,137 @@ function queue_run(&$argv, &$argc){
// After that, we'll only attempt delivery once per hour.
$r = q("SELECT `id` FROM `queue` WHERE ((`created` > UTC_TIMESTAMP() - INTERVAL 12 HOUR && `last` < UTC_TIMESTAMP() - INTERVAL 15 MINUTE) OR (`last` < UTC_TIMESTAMP() - INTERVAL 1 HOUR)) ORDER BY `cid`, `created`");
} else {
logger('queue: start for id '.$queue_id);
$r = q("SELECT `id` FROM `queue` WHERE `id` = %d LIMIT 1",
intval($queue_id)
);
}
call_hooks('queue_predeliver', $a, $r);
if (!$r){
if (dbm::is_result($r)) {
foreach ($r as $q_item) {
logger('Call queue for id '.$q_item['id']);
proc_run(PRIORITY_LOW, "include/queue.php", $q_item['id']);
}
}
return;
}
if (!$queue_id)
call_hooks('queue_predeliver', $a, $r);
// delivery loop
// delivering
require_once('include/salmon.php');
require_once('include/diaspora.php');
foreach($r as $q_item) {
$r = q("SELECT * FROM `queue` WHERE `id` = %d LIMIT 1",
intval($queue_id));
// queue_predeliver hooks may have changed the queue db details,
// so check again if this entry still needs processing
if (!dbm::is_result($r)) {
return;
}
if ($queue_id) {
$qi = q("SELECT * FROM `queue` WHERE `id` = %d LIMIT 1",
intval($queue_id));
} elseif (get_config("system", "worker")) {
logger('Call queue for id '.$q_item['id']);
proc_run(PRIORITY_LOW, "include/queue.php", $q_item['id']);
continue;
} else
$qi = q("SELECT * FROM `queue` WHERE `id` = %d AND `last` < UTC_TIMESTAMP() - INTERVAL 15 MINUTE ",
intval($q_item['id']));
$q_item = $r[0];
if (!dbm::is_result($qi)) {
continue;
$c = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1",
intval($q_item['cid'])
);
if (!dbm::is_result($c)) {
remove_queue_item($q_item['id']);
return;
}
$dead = Cache::get($cachekey_deadguy.$c[0]['notify']);
if (!is_null($dead) AND $dead) {
logger('queue: skipping known dead url: '.$c[0]['notify']);
update_queue_time($q_item['id']);
return;
}
$server = poco_detect_server($c[0]['url']);
if ($server != "") {
$vital = Cache::get($cachekey_server.$server);
if (is_null($vital)) {
logger("Check server ".$server." (".$c[0]["network"].")");
$vital = poco_check_server($server, $c[0]["network"], true);
Cache::set($cachekey_server.$server, $vital, CACHE_QUARTER_HOUR);
}
$c = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1",
intval($qi[0]['cid'])
);
if (! dbm::is_result($c)) {
remove_queue_item($q_item['id']);
continue;
}
$dead = Cache::get($cachekey_deadguy.$c[0]['notify']);
if (!is_null($dead) AND $dead) {
logger('queue: skipping known dead url: '.$c[0]['notify']);
if (!is_null($vital) AND !$vital) {
logger('queue: skipping dead server: '.$server);
update_queue_time($q_item['id']);
continue;
return;
}
}
$server = poco_detect_server($c[0]['url']);
$u = q("SELECT `user`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`
FROM `user` WHERE `uid` = %d LIMIT 1",
intval($c[0]['uid'])
);
if (!dbm::is_result($u)) {
remove_queue_item($q_item['id']);
return;
}
if ($server != "") {
$vital = Cache::get($cachekey_server.$server);
$data = $q_item['content'];
$public = $q_item['batch'];
$contact = $c[0];
$owner = $u[0];
if (is_null($vital)) {
logger("Check server ".$server." (".$c[0]["network"].")");
$deliver_status = 0;
$vital = poco_check_server($server, $c[0]["network"], true);
Cache::set($cachekey_server.$server, $vital, CACHE_QUARTER_HOUR);
}
switch ($contact['network']) {
case NETWORK_DFRN:
logger('queue: dfrndelivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>');
$deliver_status = dfrn::deliver($owner, $contact, $data);
if (!is_null($vital) AND !$vital) {
logger('queue: skipping dead server: '.$server);
if ($deliver_status == (-1)) {
update_queue_time($q_item['id']);
continue;
Cache::set($cachekey_deadguy.$contact['notify'], true, CACHE_QUARTER_HOUR);
} else {
remove_queue_item($q_item['id']);
}
}
break;
case NETWORK_OSTATUS:
if ($contact['notify']) {
logger('queue: slapdelivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>');
$deliver_status = slapper($owner, $contact['notify'], $data);
$u = q("SELECT `user`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`
FROM `user` WHERE `uid` = %d LIMIT 1",
intval($c[0]['uid'])
);
if (! dbm::is_result($u)) {
remove_queue_item($q_item['id']);
continue;
}
$data = $qi[0]['content'];
$public = $qi[0]['batch'];
$contact = $c[0];
$owner = $u[0];
$deliver_status = 0;
switch($contact['network']) {
case NETWORK_DFRN:
logger('queue: dfrndelivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>');
$deliver_status = dfrn::deliver($owner,$contact,$data);
if ($deliver_status < 0) {
if ($deliver_status == (-1)) {
update_queue_time($q_item['id']);
Cache::set($cachekey_deadguy.$contact['notify'], true, CACHE_QUARTER_HOUR);
} else {
remove_queue_item($q_item['id']);
}
break;
case NETWORK_OSTATUS:
if ($contact['notify']) {
logger('queue: slapdelivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>');
$deliver_status = slapper($owner,$contact['notify'],$data);
}
break;
case NETWORK_DIASPORA:
if ($contact['notify']) {
logger('queue: diaspora_delivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>');
$deliver_status = Diaspora::transmit($owner, $contact, $data, $public, true);
if ($deliver_status == (-1)) {
update_queue_time($q_item['id']);
Cache::set($cachekey_deadguy.$contact['notify'], true, CACHE_QUARTER_HOUR);
} else {
remove_queue_item($q_item['id']);
}
}
break;
case NETWORK_DIASPORA:
if ($contact['notify']) {
logger('queue: diaspora_delivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>');
$deliver_status = Diaspora::transmit($owner,$contact,$data,$public,true);
if ($deliver_status == (-1)) {
update_queue_time($q_item['id']);
Cache::set($cachekey_deadguy.$contact['notify'], true, CACHE_QUARTER_HOUR);
} else {
remove_queue_item($q_item['id']);
}
}
break;
default:
$params = array('owner' => $owner, 'contact' => $contact, 'queue' => $q_item, 'result' => false);
call_hooks('queue_deliver', $a, $params);
if ($params['result']) {
remove_queue_item($q_item['id']);
} else {
if ($deliver_status == (-1)) {
update_queue_time($q_item['id']);
Cache::set($cachekey_deadguy.$contact['notify'], true, CACHE_QUARTER_HOUR);
} else {
remove_queue_item($q_item['id']);
}
break;
}
break;
default:
$params = array('owner' => $owner, 'contact' => $contact, 'queue' => $q_item, 'result' => false);
call_hooks('queue_deliver', $a, $params);
if ($params['result']) {
remove_queue_item($q_item['id']);
} else {
update_queue_time($q_item['id']);
}
break;
}
logger('Deliver status '.(int)$deliver_status.' for item '.$q_item['id'].' to '.$contact['name'].' <'.$contact['url'].'>');
}
logger('Deliver status '.(int)$deliver_status.' for item '.$q_item['id'].' to '.$contact['name'].' <'.$contact['url'].'>');
return;
}
if (array_search(__file__,get_included_files())===0){
queue_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -6,24 +6,7 @@
use \Friendica\Core\Config;
require_once("boot.php");
function remove_contact_run($argv, $argc) {
global $a, $db;
if (is_null($a)) {
$a = new App;
}
if (is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
}
Config::load();
if ($argc != 2) {
return;
}
@ -46,9 +29,4 @@ function remove_contact_run($argv, $argc) {
q("DELETE FROM `queue` WHERE `cid` = %d", intval($id));
}
if (array_search(__file__, get_included_files()) === 0) {
remove_contact_run($_SERVER["argv"], $_SERVER["argc"]);
killme();
}
?>

View file

@ -55,7 +55,7 @@ function authenticate_success($user_record, $login_initial = false, $interactive
$a->user = $user_record;
if($interactive) {
if($a->user['login_date'] === '0000-00-00 00:00:00') {
if ($a->user['login_date'] <= NULL_DATE) {
$_SESSION['return_url'] = 'profile_photo/new';
$a->module = 'profile_photo';
info( t("Welcome ") . $a->user['username'] . EOL);

View file

@ -5,20 +5,26 @@ use \Friendica\Core\Config;
require_once("boot.php");
require_once("include/threads.php");
global $a, $db;
function shadowupdate_run(&$argv, &$argc){
global $a, $db;
if(is_null($a))
$a = new App;
if (is_null($a)) {
$a = new App;
}
if(is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
if (is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
}
Config::load();
update_shadow_copy();
}
Config::load();
update_shadow_copy();
killme();
?>
if (array_search(__file__,get_included_files())===0){
shadowupdate_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -14,8 +14,13 @@ require_once("include/html2bbcode.php");
require_once("include/Contact.php");
require_once("include/Photo.php");
/*
* poco_load
/**
* @brief Fetch POCO data
*
* @param integer $cid Contact ID
* @param integer $uid User ID
* @param integer $zcid Global Contact ID
* @param integer $url POCO address that should be polled
*
* Given a contact-id (minimum), load the PortableContacts friend list for that contact,
* and add the entries to the gcontact (Global Contact) table, or update existing entries
@ -27,12 +32,21 @@ require_once("include/Photo.php");
* pointing to the same global contact id.
*
*/
function poco_load($cid, $uid = 0, $zcid = 0, $url = null) {
// Call the function "poco_load_worker" via the worker
proc_run(PRIORITY_LOW, "include/discover_poco.php", "poco_load", intval($cid), intval($uid), intval($zcid), base64_encode($url));
}
function poco_load($cid,$uid = 0,$zcid = 0,$url = null) {
/**
* @brief Fetch POCO data from the worker
*
* @param integer $cid Contact ID
* @param integer $uid User ID
* @param integer $zcid Global Contact ID
* @param integer $url POCO address that should be polled
*
*/
function poco_load_worker($cid, $uid, $zcid, $url) {
$a = get_app();
if($cid) {
@ -81,7 +95,7 @@ function poco_load($cid,$uid = 0,$zcid = 0,$url = null) {
$connect_url = '';
$name = '';
$network = '';
$updated = '0000-00-00 00:00:00';
$updated = NULL_DATE;
$location = '';
$about = '';
$keywords = '';
@ -239,12 +253,12 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
);
if (count($x)) {
if (($network == "") AND ($x[0]["network"] != NETWORK_STATUSNET))
if (($network == "") AND ($x[0]["network"] != NETWORK_STATUSNET)) {
$network = $x[0]["network"];
if ($updated == "0000-00-00 00:00:00")
}
if ($updated <= NULL_DATE) {
$updated = $x[0]["updated"];
}
$created = $x[0]["created"];
$server_url = $x[0]["server_url"];
$nick = $x[0]["nick"];
@ -252,7 +266,7 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
$alias = $x[0]["alias"];
$notify = $x[0]["notify"];
} else {
$created = "0000-00-00 00:00:00";
$created = NULL_DATE;
$server_url = "";
$urlparts = parse_url($profile_url);
@ -309,7 +323,18 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
logger("profile-check generation: ".$generation." Network: ".$network." URL: ".$profile_url." name: ".$name." avatar: ".$profile_photo, LOGGER_DEBUG);
poco_check_server($server_url, $network);
// We check the server url to be sure that it is a real one
$server_url2 = poco_detect_server($profile_url);
// We are no sure that it is a correct URL. So we use it in the future
if ($server_url2 != "") {
$server_url = $server_url2;
}
// The server URL doesn't seem to be valid, so we don't store it.
if (!poco_check_server($server_url, $network)) {
$server_url = "";
}
$gcontact = array("url" => $profile_url,
"addr" => $addr,
@ -401,13 +426,47 @@ function poco_detect_server($profile) {
// Mastodon
if ($server_url == "") {
$red = preg_replace("=(https?://)(.*)/users/(.*)=ism", "$1$2", $profile);
if ($red != $profile) {
$server_url = $red;
$mastodon = preg_replace("=(https?://)(.*)/users/(.*)=ism", "$1$2", $profile);
if ($mastodon != $profile) {
$server_url = $mastodon;
$network = NETWORK_OSTATUS;
}
}
// Numeric OStatus variant
if ($server_url == "") {
$ostatus = preg_replace("=(https?://)(.*)/user/(.*)=ism", "$1$2", $profile);
if ($ostatus != $profile) {
$server_url = $ostatus;
$network = NETWORK_OSTATUS;
}
}
// Wild guess
if ($server_url == "") {
$base = preg_replace("=(https?://)(.*?)/(.*)=ism", "$1$2", $profile);
if ($base != $profile) {
$server_url = $base;
$network = NETWORK_PHANTOM;
}
}
if ($server_url == "") {
return "";
}
$r = q("SELECT `id` FROM `gserver` WHERE `nurl` = '%s' AND `last_contact` > `last_failure`",
dbesc(normalise_link($server_url)));
if (dbm::is_result($r)) {
return $server_url;
}
// Fetch the host-meta to check if this really is a server
$serverret = z_fetch_url($server_url."/.well-known/host-meta");
if (!$serverret["success"]) {
return "";
}
return $server_url;
}
@ -420,14 +479,16 @@ function poco_last_updated($profile, $force = false) {
$gcontacts = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s'",
dbesc(normalise_link($profile)));
if ($gcontacts[0]["created"] == "0000-00-00 00:00:00")
if ($gcontacts[0]["created"] <= NULL_DATE) {
q("UPDATE `gcontact` SET `created` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($profile)));
if ($gcontacts[0]["server_url"] != "")
}
if ($gcontacts[0]["server_url"] != "") {
$server_url = $gcontacts[0]["server_url"];
else
}
if (($server_url == '') OR ($gcontacts[0]["server_url"] == $gcontacts[0]["nurl"])) {
$server_url = poco_detect_server($profile);
}
if (!in_array($gcontacts[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_FEED, NETWORK_OSTATUS, ""))) {
logger("Profile ".$profile.": Network type ".$gcontacts[0]["network"]." can't be checked", LOGGER_DEBUG);
@ -617,10 +678,11 @@ function poco_last_updated($profile, $force = false) {
}
// Maybe there aren't any entries. Then check if it is a valid feed
if ($last_updated == "")
if ($xpath->query('/atom:feed')->length > 0)
$last_updated = "0000-00-00 00:00:00";
if ($last_updated == "") {
if ($xpath->query('/atom:feed')->length > 0) {
$last_updated = NULL_DATE;
}
}
q("UPDATE `gcontact` SET `updated` = '%s', `last_contact` = '%s' WHERE `nurl` = '%s'",
dbesc(dbm::date($last_updated)), dbesc(dbm::date()), dbesc(normalise_link($profile)));
@ -680,6 +742,213 @@ function poco_to_boolean($val) {
return ($val);
}
/**
* @brief Detect server type (Hubzilla or Friendica) via the poco data
*
* @param object $data POCO data
* @return array Server data
*/
function poco_detect_poco_data($data) {
$server = false;
if (!isset($data->entry)) {
return false;
}
if (count($data->entry) == 0) {
return false;
}
if (!isset($data->entry[0]->urls)) {
return false;
}
if (count($data->entry[0]->urls) == 0) {
return false;
}
foreach ($data->entry[0]->urls AS $url) {
if ($url->type == 'zot') {
$server = array();
$server["platform"] = 'Hubzilla';
$server["network"] = NETWORK_DIASPORA;
return $server;
}
}
return false;
}
/**
* @brief Detect server type by using the nodeinfo data
*
* @param string $server_url address of the server
* @return array Server data
*/
function poco_fetch_nodeinfo($server_url) {
$serverret = z_fetch_url($server_url."/.well-known/nodeinfo");
if (!$serverret["success"]) {
return false;
}
$nodeinfo = json_decode($serverret['body']);
if (!is_object($nodeinfo)) {
return false;
}
if (!is_array($nodeinfo->links)) {
return false;
}
$nodeinfo_url = '';
foreach ($nodeinfo->links AS $link) {
if ($link->rel == 'http://nodeinfo.diaspora.software/ns/schema/1.0') {
$nodeinfo_url = $link->href;
}
}
if ($nodeinfo_url == '') {
return false;
}
$serverret = z_fetch_url($nodeinfo_url);
if (!$serverret["success"]) {
return false;
}
$nodeinfo = json_decode($serverret['body']);
if (!is_object($nodeinfo)) {
return false;
}
$server = array();
$server['register_policy'] = REGISTER_CLOSED;
if (is_bool($nodeinfo->openRegistrations) AND $nodeinfo->openRegistrations) {
$server['register_policy'] = REGISTER_OPEN;
}
if (is_object($nodeinfo->software)) {
if (isset($nodeinfo->software->name)) {
$server['platform'] = $nodeinfo->software->name;
}
if (isset($nodeinfo->software->version)) {
$server['version'] = $nodeinfo->software->version;
// Version numbers on Nodeinfo are presented with additional info, e.g.:
// 0.6.3.0-p1702cc1c, 0.6.99.0-p1b9ab160 or 3.4.3-2-1191.
$server['version'] = preg_replace("=(.+)-(.{4,})=ism", "$1", $server['version']);
}
}
if (is_object($nodeinfo->metadata)) {
if (isset($nodeinfo->metadata->nodeName)) {
$server['site_name'] = $nodeinfo->metadata->nodeName;
}
}
$diaspora = false;
$friendica = false;
$gnusocial = false;
if (is_array($nodeinfo->protocols->inbound)) {
foreach ($nodeinfo->protocols->inbound AS $inbound) {
if ($inbound == 'diaspora') {
$diaspora = true;
}
if ($inbound == 'friendica') {
$friendica = true;
}
if ($inbound == 'gnusocial') {
$gnusocial = true;
}
}
}
if ($gnusocial) {
$server['network'] = NETWORK_OSTATUS;
}
if ($diaspora) {
$server['network'] = NETWORK_DIASPORA;
}
if ($friendica) {
$server['network'] = NETWORK_DFRN;
}
if (!$server) {
return false;
}
return $server;
}
/**
* @brief Detect server type (Hubzilla or Friendica) via the front page body
*
* @param string $body Front page of the server
* @return array Server data
*/
function poco_detect_server_type($body) {
$server = false;
$doc = new \DOMDocument();
@$doc->loadHTML($body);
$xpath = new \DomXPath($doc);
$list = $xpath->query("//meta[@name]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length) {
foreach ($node->attributes as $attribute) {
$attr[$attribute->name] = $attribute->value;
}
}
if ($attr['name'] == 'generator') {
$version_part = explode(" ", $attr['content']);
if (count($version_part) == 2) {
if (in_array($version_part[0], array("Friendika", "Friendica"))) {
$server = array();
$server["platform"] = $version_part[0];
$server["version"] = $version_part[1];
$server["network"] = NETWORK_DFRN;
}
}
}
}
if (!$server) {
$list = $xpath->query("//meta[@property]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length) {
foreach ($node->attributes as $attribute) {
$attr[$attribute->name] = $attribute->value;
}
}
if ($attr['property'] == 'generator') {
if (in_array($attr['content'], array("hubzilla", "BlaBlaNet"))) {
$server = array();
$server["platform"] = $attr['content'];
$server["version"] = "";
$server["network"] = NETWORK_DIASPORA;
}
}
}
}
if (!$server) {
return false;
}
$server["site_name"] = $xpath->evaluate($element."//head/title/text()", $context)->item(0)->nodeValue;
return $server;
}
function poco_check_server($server_url, $network = "", $force = false) {
// Unify the server address
@ -692,10 +961,10 @@ function poco_check_server($server_url, $network = "", $force = false) {
$servers = q("SELECT * FROM `gserver` WHERE `nurl` = '%s'", dbesc(normalise_link($server_url)));
if (dbm::is_result($servers)) {
if ($servers[0]["created"] == "0000-00-00 00:00:00")
if ($servers[0]["created"] <= NULL_DATE) {
q("UPDATE `gserver` SET `created` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($server_url)));
}
$poco = $servers[0]["poco"];
$noscrape = $servers[0]["noscrape"];
@ -723,13 +992,15 @@ function poco_check_server($server_url, $network = "", $force = false) {
$info = "";
$register_policy = -1;
$last_contact = "0000-00-00 00:00:00";
$last_failure = "0000-00-00 00:00:00";
$last_contact = NULL_DATE;
$last_failure = NULL_DATE;
}
logger("Server ".$server_url." is outdated or unknown. Start discovery. Force: ".$force." Created: ".$servers[0]["created"]." Failure: ".$last_failure." Contact: ".$last_contact, LOGGER_DEBUG);
$failure = false;
$possible_failure = false;
$orig_last_failure = $last_failure;
$orig_last_contact = $last_contact;
// Check if the page is accessible via SSL.
$orig_server_url = $server_url;
@ -769,18 +1040,58 @@ function poco_check_server($server_url, $network = "", $force = false) {
$last_failure = datetime_convert();
$failure = true;
}
$possible_failure = true;
} elseif ($network == NETWORK_DIASPORA)
$last_contact = datetime_convert();
// If the server has no possible failure we reset the cached data
if (!$possible_failure) {
$version = "";
$platform = "";
$site_name = "";
$info = "";
$register_policy = -1;
}
// Look for poco
if (!$failure) {
// Test for Diaspora
$serverret = z_fetch_url($server_url."/poco");
if ($serverret["success"]) {
$data = json_decode($serverret["body"]);
if (isset($data->totalResults)) {
$poco = $server_url."/poco";
$last_contact = datetime_convert();
$server = poco_detect_poco_data($data);
if ($server) {
$platform = $server['platform'];
$network = $server['network'];
$version = '';
$site_name = '';
}
}
}
}
if (!$failure) {
// Test for Diaspora, Hubzilla, Mastodon or older Friendica servers
$serverret = z_fetch_url($server_url);
if (!$serverret["success"] OR ($serverret["body"] == ""))
if (!$serverret["success"] OR ($serverret["body"] == "")) {
$last_failure = datetime_convert();
$failure = true;
else {
} else {
$server = poco_detect_server_type($serverret["body"]);
if ($server) {
$platform = $server['platform'];
$network = $server['network'];
$version = $server['version'];
$site_name = $server['site_name'];
$last_contact = datetime_convert();
}
$lines = explode("\n",$serverret["header"]);
if(count($lines))
if(count($lines)) {
foreach($lines as $line) {
$line = trim($line);
if(stristr($line,'X-Diaspora-Version:')) {
@ -790,6 +1101,7 @@ function poco_check_server($server_url, $network = "", $force = false) {
$network = NETWORK_DIASPORA;
$versionparts = explode("-", $version);
$version = $versionparts[0];
$last_contact = datetime_convert();
}
if(stristr($line,'Server: Mastodon')) {
@ -797,12 +1109,14 @@ function poco_check_server($server_url, $network = "", $force = false) {
$network = NETWORK_OSTATUS;
// Mastodon doesn't reveal version numbers
$version = "";
$last_contact = datetime_convert();
}
}
}
}
}
if (!$failure) {
if (!$failure AND ($poco == "")) {
// Test for Statusnet
// Will also return data for Friendica and GNU Social - but it will be overwritten later
// The "not implemented" is a special treatment for really, really old Friendica versions
@ -810,8 +1124,11 @@ function poco_check_server($server_url, $network = "", $force = false) {
if ($serverret["success"] AND ($serverret["body"] != '{"error":"not implemented"}') AND
($serverret["body"] != '') AND (strlen($serverret["body"]) < 30)) {
$platform = "StatusNet";
$version = trim($serverret["body"], '"');
// Remove junk that some GNU Social servers return
$version = str_replace(chr(239).chr(187).chr(191), "", $serverret["body"]);
$version = trim($version, '"');
$network = NETWORK_OSTATUS;
$last_contact = datetime_convert();
}
// Test for GNU Social
@ -819,17 +1136,32 @@ function poco_check_server($server_url, $network = "", $force = false) {
if ($serverret["success"] AND ($serverret["body"] != '{"error":"not implemented"}') AND
($serverret["body"] != '') AND (strlen($serverret["body"]) < 30)) {
$platform = "GNU Social";
$version = trim($serverret["body"], '"');
// Remove junk that some GNU Social servers return
$version = str_replace(chr(239).chr(187).chr(191), "", $serverret["body"]);
$version = trim($version, '"');
$network = NETWORK_OSTATUS;
$last_contact = datetime_convert();
}
}
if (!$failure) {
// Test for Hubzilla, Redmatrix or Friendica
$serverret = z_fetch_url($server_url."/api/statusnet/config.json");
if ($serverret["success"]) {
$data = json_decode($serverret["body"]);
if (isset($data->site->server)) {
$last_contact = datetime_convert();
if (isset($data->site->platform)) {
$platform = $data->site->platform->PLATFORM_NAME;
$version = $data->site->platform->STD_VERSION;
$network = NETWORK_DIASPORA;
}
if (isset($data->site->BlaBlaNet)) {
$platform = $data->site->BlaBlaNet->PLATFORM_NAME;
$version = $data->site->BlaBlaNet->STD_VERSION;
$network = NETWORK_DIASPORA;
}
if (isset($data->site->hubzilla)) {
$platform = $data->site->hubzilla->PLATFORM_NAME;
$version = $data->site->hubzilla->RED_VERSION;
@ -866,32 +1198,66 @@ function poco_check_server($server_url, $network = "", $force = false) {
}
}
// Query statistics.json. Optional package for Diaspora, Friendica and Redmatrix
if (!$failure) {
$serverret = z_fetch_url($server_url."/statistics.json");
if ($serverret["success"]) {
$data = json_decode($serverret["body"]);
if ($version == "")
if (isset($data->version)) {
$version = $data->version;
// Version numbers on statistics.json are presented with additional info, e.g.:
// 0.6.3.0-p1702cc1c, 0.6.99.0-p1b9ab160 or 3.4.3-2-1191.
$version = preg_replace("=(.+)-(.{4,})=ism", "$1", $version);
}
$site_name = $data->name;
if (isset($data->network) AND ($platform == ""))
if (isset($data->network)) {
$platform = $data->network;
}
if ($platform == "Diaspora")
if ($platform == "Diaspora") {
$network = NETWORK_DIASPORA;
}
if ($data->registrations_open)
if ($data->registrations_open) {
$register_policy = REGISTER_OPEN;
else
} else {
$register_policy = REGISTER_CLOSED;
}
if (isset($data->version))
$last_contact = datetime_convert();
}
}
// Query nodeinfo. Working for (at least) Diaspora and Friendica.
if (!$failure) {
$server = poco_fetch_nodeinfo($server_url);
if ($server) {
$register_policy = $server['register_policy'];
if (isset($server['platform'])) {
$platform = $server['platform'];
}
if (isset($server['network'])) {
$network = $server['network'];
}
if (isset($server['version'])) {
$version = $server['version'];
}
if (isset($server['site_name'])) {
$site_name = $server['site_name'];
}
$last_contact = datetime_convert();
}
}
// Check for noscrape
// Friendica servers could be detected as OStatus servers
if (!$failure AND in_array($network, array(NETWORK_DFRN, NETWORK_OSTATUS))) {
@ -929,16 +1295,21 @@ function poco_check_server($server_url, $network = "", $force = false) {
}
}
// Look for poco
if (!$failure) {
$serverret = z_fetch_url($server_url."/poco");
if ($serverret["success"]) {
$data = json_decode($serverret["body"]);
if (isset($data->totalResults)) {
$poco = $server_url."/poco";
$last_contact = datetime_convert();
}
}
if ($possible_failure AND !$failure) {
$last_failure = datetime_convert();
$failure = true;
}
if ($failure) {
$last_contact = $orig_last_contact;
} else {
$last_failure = $orig_last_failure;
}
if (($last_contact <= $last_failure) AND !$failure) {
logger("Server ".$server_url." seems to be alive, but last contact wasn't set - could be a bug", LOGGER_DEBUG);
} else if (($last_contact >= $last_failure) AND $failure) {
logger("Server ".$server_url." seems to be dead, but last failure wasn't set - could be a bug", LOGGER_DEBUG);
}
// Check again if the server exists
@ -949,7 +1320,7 @@ function poco_check_server($server_url, $network = "", $force = false) {
$info = strip_tags($info);
$platform = strip_tags($platform);
if ($servers)
if ($servers) {
q("UPDATE `gserver` SET `url` = '%s', `version` = '%s', `site_name` = '%s', `info` = '%s', `register_policy` = %d, `poco` = '%s', `noscrape` = '%s',
`network` = '%s', `platform` = '%s', `last_contact` = '%s', `last_failure` = '%s' WHERE `nurl` = '%s'",
dbesc($server_url),
@ -965,7 +1336,7 @@ function poco_check_server($server_url, $network = "", $force = false) {
dbesc($last_failure),
dbesc(normalise_link($server_url))
);
else
} elseif (!$failure) {
q("INSERT INTO `gserver` (`url`, `nurl`, `version`, `site_name`, `info`, `register_policy`, `poco`, `noscrape`, `network`, `platform`, `created`, `last_contact`, `last_failure`)
VALUES ('%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s')",
dbesc($server_url),
@ -983,7 +1354,7 @@ function poco_check_server($server_url, $network = "", $force = false) {
dbesc($last_failure),
dbesc(datetime_convert())
);
}
logger("End discovery for server ".$server_url, LOGGER_DEBUG);
return !$failure;
@ -1147,7 +1518,7 @@ function suggestion_query($uid, $start = 0, $limit = 80) {
where uid = %d and not gcontact.nurl in ( select nurl from contact where uid = %d )
AND NOT `gcontact`.`name` IN (SELECT `name` FROM `contact` WHERE `uid` = %d)
AND NOT `gcontact`.`id` IN (SELECT `gcid` FROM `gcign` WHERE `uid` = %d)
AND `gcontact`.`updated` != '0000-00-00 00:00:00'
AND `gcontact`.`updated` >= '%s'
AND `gcontact`.`last_contact` >= `gcontact`.`last_failure`
AND `gcontact`.`network` IN (%s)
GROUP BY `glink`.`gcid` ORDER BY `gcontact`.`updated` DESC,`total` DESC LIMIT %d, %d",
@ -1155,6 +1526,7 @@ function suggestion_query($uid, $start = 0, $limit = 80) {
intval($uid),
intval($uid),
intval($uid),
dbesc(NULL_DATE),
$sql_network,
intval($start),
intval($limit)
@ -1173,13 +1545,14 @@ function suggestion_query($uid, $start = 0, $limit = 80) {
WHERE `glink`.`uid` = 0 AND `glink`.`cid` = 0 AND `glink`.`zcid` = 0 AND NOT `gcontact`.`nurl` IN (SELECT `nurl` FROM `contact` WHERE `uid` = %d)
AND NOT `gcontact`.`name` IN (SELECT `name` FROM `contact` WHERE `uid` = %d)
AND NOT `gcontact`.`id` IN (SELECT `gcid` FROM `gcign` WHERE `uid` = %d)
AND `gcontact`.`updated` != '0000-00-00 00:00:00'
AND `gcontact`.`updated` >= '%s'
AND `gcontact`.`last_contact` >= `gcontact`.`last_failure`
AND `gcontact`.`network` IN (%s)
ORDER BY rand() LIMIT %d, %d",
intval($uid),
intval($uid),
intval($uid),
dbesc(NULL_DATE),
$sql_network,
intval($start),
intval($limit)
@ -1244,6 +1617,33 @@ function update_suggestions() {
}
}
/**
* @brief Fetch server list from remote servers and adds them when they are new.
*
* @param string $poco URL to the POCO endpoint
*/
function poco_fetch_serverlist($poco) {
$serverret = z_fetch_url($poco."/@server");
if (!$serverret["success"]) {
return;
}
$serverlist = json_decode($serverret['body']);
if (!is_array($serverlist)) {
return;
}
foreach ($serverlist AS $server) {
$server_url = str_replace("/index.php", "", $server->url);
$r = q("SELECT `nurl` FROM `gserver` WHERE `nurl` = '%s'", dbesc(normalise_link($server_url)));
if (!dbm::is_result($r)) {
logger("Call server check for server ".$server_url, LOGGER_DEBUG);
proc_run(PRIORITY_LOW, "include/discover_poco.php", "server", base64_encode($server_url));
}
}
}
function poco_discover_federation() {
$last = get_config('poco','last_federation_discovery');
@ -1259,8 +1659,9 @@ function poco_discover_federation() {
if ($serverdata) {
$servers = json_decode($serverdata);
foreach($servers->pods AS $server)
poco_check_server("https://".$server->host);
foreach ($servers->pods AS $server) {
proc_run(PRIORITY_LOW, "include/discover_poco.php", "server", base64_encode("https://".$server->host));
}
}
// Currently disabled, since the service isn't available anymore.
@ -1281,6 +1682,68 @@ function poco_discover_federation() {
set_config('poco','last_federation_discovery', time());
}
function poco_discover_single_server($id) {
$r = q("SELECT `poco`, `nurl`, `url`, `network` FROM `gserver` WHERE `id` = %d", intval($id));
if (!dbm::is_result($r)) {
return false;
}
$server = $r[0];
// Discover new servers out there (Works from Friendica version 3.5.2)
poco_fetch_serverlist($server["poco"]);
// Fetch all users from the other server
$url = $server["poco"]."/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,contactType,generation";
logger("Fetch all users from the server ".$server["url"], LOGGER_DEBUG);
$retdata = z_fetch_url($url);
if ($retdata["success"]) {
$data = json_decode($retdata["body"]);
poco_discover_server($data, 2);
if (get_config('system','poco_discovery') > 1) {
$timeframe = get_config('system','poco_discovery_since');
if ($timeframe == 0) {
$timeframe = 30;
}
$updatedSince = date("Y-m-d H:i:s", time() - $timeframe * 86400);
// Fetch all global contacts from the other server (Not working with Redmatrix and Friendica versions before 3.3)
$url = $server["poco"]."/@global?updatedSince=".$updatedSince."&fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,contactType,generation";
$success = false;
$retdata = z_fetch_url($url);
if ($retdata["success"]) {
logger("Fetch all global contacts from the server ".$server["nurl"], LOGGER_DEBUG);
$success = poco_discover_server(json_decode($retdata["body"]));
}
if (!$success AND (get_config('system','poco_discovery') > 2)) {
logger("Fetch contacts from users of the server ".$server["nurl"], LOGGER_DEBUG);
poco_discover_server_users($data, $server);
}
}
q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"]));
return true;
} else {
// If the server hadn't replied correctly, then force a sanity check
poco_check_server($server["url"], $server["network"], true);
// If we couldn't reach the server, we will try it some time later
q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"]));
return false;
}
}
function poco_discover($complete = false) {
// Update the server list
@ -1290,13 +1753,13 @@ function poco_discover($complete = false) {
$requery_days = intval(get_config("system", "poco_requery_days"));
if ($requery_days == 0)
if ($requery_days == 0) {
$requery_days = 7;
}
$last_update = date("c", time() - (60 * 60 * 24 * $requery_days));
$r = q("SELECT `poco`, `nurl`, `url`, `network` FROM `gserver` WHERE `last_contact` >= `last_failure` AND `poco` != '' AND `last_poco_query` < '%s' ORDER BY RAND()", dbesc($last_update));
if ($r)
$r = q("SELECT `id`, `url`, `network` FROM `gserver` WHERE `last_contact` >= `last_failure` AND `poco` != '' AND `last_poco_query` < '%s' ORDER BY RAND()", dbesc($last_update));
if (dbm::is_result($r)) {
foreach ($r AS $server) {
if (!poco_check_server($server["url"], $server["network"])) {
@ -1305,53 +1768,14 @@ function poco_discover($complete = false) {
continue;
}
// Fetch all users from the other server
$url = $server["poco"]."/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,contactType,generation";
logger('Update directory from server '.$server['url'].' with ID '.$server['id'], LOGGER_DEBUG);
proc_run(PRIORITY_LOW, "include/discover_poco.php", "update_server_directory", intval($server['id']));
logger("Fetch all users from the server ".$server["nurl"], LOGGER_DEBUG);
$retdata = z_fetch_url($url);
if ($retdata["success"]) {
$data = json_decode($retdata["body"]);
poco_discover_server($data, 2);
if (get_config('system','poco_discovery') > 1) {
$timeframe = get_config('system','poco_discovery_since');
if ($timeframe == 0)
$timeframe = 30;
$updatedSince = date("Y-m-d H:i:s", time() - $timeframe * 86400);
// Fetch all global contacts from the other server (Not working with Redmatrix and Friendica versions before 3.3)
$url = $server["poco"]."/@global?updatedSince=".$updatedSince."&fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,contactType,generation";
$success = false;
$retdata = z_fetch_url($url);
if ($retdata["success"]) {
logger("Fetch all global contacts from the server ".$server["nurl"], LOGGER_DEBUG);
$success = poco_discover_server(json_decode($retdata["body"]));
}
if (!$success AND (get_config('system','poco_discovery') > 2)) {
logger("Fetch contacts from users of the server ".$server["nurl"], LOGGER_DEBUG);
poco_discover_server_users($data, $server);
}
}
q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"]));
if (!$complete AND (--$no_of_queries == 0))
break;
} else {
// If the server hadn't replied correctly, then force a sanity check
poco_check_server($server["url"], $server["network"], true);
// If we couldn't reach the server, we will try it some time later
q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"]));
if (!$complete AND (--$no_of_queries == 0)) {
break;
}
}
}
}
function poco_discover_server_users($data, $server) {
@ -1395,7 +1819,7 @@ function poco_discover_server($data, $default_generation = 0) {
$connect_url = '';
$name = '';
$network = '';
$updated = '0000-00-00 00:00:00';
$updated = NULL_DATE;
$location = '';
$about = '';
$keywords = '';
@ -1879,4 +2303,20 @@ function gs_discover() {
q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"]));
}
}
/**
* @brief Returns a list of all known servers
* @return array List of server urls
*/
function poco_serverlist() {
$r = q("SELECT `url`, `site_name` AS `displayName`, `network`, `platform`, `version` FROM `gserver`
WHERE `network` IN ('%s', '%s', '%s') AND `last_contact` > `last_failure`
ORDER BY `last_contact`
LIMIT 1000",
dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS));
if (!dbm::is_result($r)) {
return false;
}
return $r;
}
?>

View file

@ -6,24 +6,10 @@
use \Friendica\Core\Config;
require_once("boot.php");
require_once("include/items.php");
function spool_post_run($argv, $argc) {
global $a, $db;
if (is_null($a)) {
$a = new App;
}
if (is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
}
Config::load();
global $a;
$path = get_spoolpath();
@ -69,9 +55,4 @@ function spool_post_run($argv, $argc) {
}
}
}
if (array_search(__file__, get_included_files()) === 0) {
spool_post_run($_SERVER["argv"], $_SERVER["argc"]);
killme();
}
?>

View file

@ -1,24 +1,6 @@
<?php
use \Friendica\Core\Config;
require_once("boot.php");
require_once("include/tags.php");
global $a, $db;
if(is_null($a))
$a = new App;
if(is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
function tagupdate_run(&$argv, &$argc){
update_items();
}
Config::load();
update_items();
killme();
?>

View file

@ -903,10 +903,10 @@ function contact_block() {
intval($shown)
);
if (dbm::is_result($r)) {
$contacts = "";
foreach ($r AS $contact)
$contacts = array();
foreach ($r AS $contact) {
$contacts[] = $contact["id"];
}
$r = q("SELECT `id`, `uid`, `addr`, `url`, `name`, `thumb`, `network` FROM `contact` WHERE `id` IN (%s)",
dbesc(implode(",", $contacts)));

View file

@ -1,25 +1,7 @@
<?php
use \Friendica\Core\Config;
require_once("boot.php");
require_once("include/threads.php");
global $a, $db;
if(is_null($a))
$a = new App;
if(is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
function threadupdate_run(&$argv, &$argc){
update_threads();
update_threads_mention();
}
Config::load();
update_threads();
update_threads_mention();
killme();
?>

View file

@ -11,14 +11,11 @@ define("IMPORT_DEBUG", False);
function last_insert_id() {
global $db;
if (IMPORT_DEBUG)
return 1;
if ($db->mysqli) {
$thedb = $db->getdb();
return $thedb->insert_id;
} else {
return mysql_insert_id();
}
return $db->insert_id();
}
function last_error() {
@ -186,8 +183,8 @@ function import_account(App $a, $file) {
}
}
if ($contact['uid'] == $olduid && $contact['self'] == '0') {
// set contacts 'avatar-date' to "0000-00-00 00:00:00" to let poller to update urls
$contact["avatar-date"] = "0000-00-00 00:00:00" ;
// set contacts 'avatar-date' to NULL_DATE to let poller to update urls
$contact["avatar-date"] = NULL_DATE;
switch ($contact['network']) {

View file

@ -2,46 +2,23 @@
use \Friendica\Core\Config;
require_once("boot.php");
function update_gcontact_run(&$argv, &$argc){
global $a, $db;
if(is_null($a)) {
$a = new App;
}
if(is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
global $a;
require_once('include/Scrape.php');
require_once("include/socgraph.php");
Config::load();
$a->set_baseurl(get_config('system','url'));
load_hooks();
require_once('include/socgraph.php');
logger('update_gcontact: start');
if(($argc > 1) && (intval($argv[1])))
if (($argc > 1) && (intval($argv[1]))) {
$contact_id = intval($argv[1]);
}
if(!$contact_id) {
if (!$contact_id) {
logger('update_gcontact: no contact');
return;
}
// Don't check this stuff if the function is called by the poller
if (App::callstack() != "poller_run")
if (App::is_already_running('update_gcontact'.$contact_id, '', 540))
return;
$r = q("SELECT * FROM `gcontact` WHERE `id` = %d", intval($contact_id));
if (!$r)
@ -98,8 +75,3 @@ function update_gcontact_run(&$argv, &$argc){
dbesc(normalise_link($data["url"]))
);
}
if (array_search(__file__,get_included_files())===0){
update_gcontact_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -97,13 +97,6 @@ function create_user($arr) {
if(mb_strlen($username) < 3)
$result['message'] .= t('Name too short.') . EOL;
// I don't really like having this rule, but it cuts down
// on the number of auto-registrations by Russian spammers
// Using preg_match was completely unreliable, due to mixed UTF-8 regex support
// $no_utf = get_config('system','no_utf');
// $pat = (($no_utf) ? '/^[a-zA-Z]* [a-zA-Z]*$/' : '/^\p{L}* \p{L}*$/u' );
// So now we are just looking for a space in the full name.
$loose_reg = get_config('system','no_regfullname');

View file

@ -36,7 +36,7 @@ function smarty_modifier_date_format($string, $format = null, $default_date = ''
* Include the {@link shared.make_timestamp.php} plugin
*/
require_once(SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php');
if ($string != '' && $string != '0000-00-00' && $string != '0000-00-00 00:00:00') {
if ($string != '' && $string > '0001-01-01' && $string > NULL_DATE) {
$timestamp = smarty_make_timestamp($string);
} elseif ($default_date != '') {
$timestamp = smarty_make_timestamp($default_date);

View file

@ -1,24 +1,17 @@
<?php
//# Install PSR-0-compatible class autoloader
//spl_autoload_register(function($class){
// require preg_replace('{\\\\|_(?!.*\\\\)}', DIRECTORY_SEPARATOR, ltrim($class, '\\')).'.php';
//});
require_once("library/php-markdown/Michelf/MarkdownExtra.inc.php");
# Get Markdown class
require_once "library/php-markdown/Michelf/MarkdownExtra.inc.php";
use \Michelf\MarkdownExtra;
function Markdown($text) {
$a = get_app();
$stamp1 = microtime(true);
# Read file and pass content through the Markdown parser
$html = MarkdownExtra::defaultTransform($text);
$MarkdownParser = new MarkdownExtra();
$MarkdownParser->hard_wrap = true;
$html = $MarkdownParser->transform($text);
$a->save_timestamp($stamp1, "parser");
return $html;
}
?>

View file

@ -1,11 +1,11 @@
PHP Markdown Lib
Copyright (c) 2004-2014 Michel Fortin
<http://michelf.ca/>
Copyright (c) 2004-2016 Michel Fortin
<https://michelf.ca/>
All rights reserved.
Based on Markdown
Copyright (c) 2003-2006 John Gruber
<http://daringfireball.net/>
<https://daringfireball.net/>
All rights reserved.
Redistribution and use in source and binary forms, with or without

View file

@ -1,10 +1,10 @@
<?php
# Use this file if you cannot use class autoloading. It will include all the
# files needed for the Markdown parser.
#
# Take a look at the PSR-0-compatible class autoloading implementation
# in the Readme.php file if you want a simple autoloader setup.
// Use this file if you cannot use class autoloading. It will include all the
// files needed for the Markdown parser.
//
// Take a look at the PSR-0-compatible class autoloading implementation
// in the Readme.php file if you want a simple autoloader setup.
require_once dirname(__FILE__) . '/MarkdownInterface.php';
require_once dirname(__FILE__) . '/Markdown.php';

View file

@ -1,147 +1,227 @@
<?php
#
# Markdown - A text-to-HTML conversion tool for web writers
#
# PHP Markdown
# Copyright (c) 2004-2014 Michel Fortin
# <http://michelf.com/projects/php-markdown/>
#
# Original Markdown
# Copyright (c) 2004-2006 John Gruber
# <http://daringfireball.net/projects/markdown/>
#
/**
* Markdown - A text-to-HTML conversion tool for web writers
*
* @package php-markdown
* @author Michel Fortin <michel.fortin@michelf.com>
* @copyright 2004-2016 Michel Fortin <https://michelf.com/projects/php-markdown/>
* @copyright (Original Markdown) 2004-2006 John Gruber <https://daringfireball.net/projects/markdown/>
*/
namespace Michelf;
#
# Markdown Parser Class
#
/**
* Markdown Parser Class
*/
class Markdown implements MarkdownInterface {
/**
* Define the package version
* @var string
*/
const MARKDOWNLIB_VERSION = "1.7.0";
### Version ###
const MARKDOWNLIB_VERSION = "1.4.1";
### Simple Function Interface ###
/**
* Simple function interface - Initialize the parser and return the result
* of its transform method. This will work fine for derived classes too.
*
* @api
*
* @param string $text
* @return string
*/
public static function defaultTransform($text) {
#
# Initialize the parser and return the result of its transform method.
# This will work fine for derived classes too.
#
# Take parser class on which this function was called.
// Take parser class on which this function was called.
$parser_class = \get_called_class();
# try to take parser from the static parser list
// Try to take parser from the static parser list
static $parser_list;
$parser =& $parser_list[$parser_class];
# create the parser it not already set
if (!$parser)
// Create the parser it not already set
if (!$parser) {
$parser = new $parser_class;
}
# Transform text using parser.
// Transform text using parser.
return $parser->transform($text);
}
### Configuration Variables ###
/**
* Configuration variables
*/
# Change to ">" for HTML output.
/**
* Change to ">" for HTML output.
* @var string
*/
public $empty_element_suffix = " />";
/**
* The width of indentation of the output markup
* @var int
*/
public $tab_width = 4;
# Change to `true` to disallow markup or entities.
public $no_markup = false;
/**
* Change to `true` to disallow markup or entities.
* @var boolean
*/
public $no_markup = false;
public $no_entities = false;
# Predefined urls and titles for reference links and images.
public $predef_urls = array();
/**
* Change to `true` to enable line breaks on \n without two trailling spaces
* @var boolean
*/
public $hard_wrap = false;
/**
* Predefined URLs and titles for reference links and images.
* @var array
*/
public $predef_urls = array();
public $predef_titles = array();
# Optional filter function for URLs
/**
* Optional filter function for URLs
* @var callable
*/
public $url_filter_func = null;
/**
* Optional header id="" generation callback function.
* @var callable
*/
public $header_id_func = null;
### Parser Implementation ###
/**
* Optional function for converting code block content to HTML
* @var callable
*/
public $code_block_content_func = null;
# Regex to match balanced [brackets].
# Needed to insert a maximum bracked depth while converting to PHP.
/**
* Optional function for converting code span content to HTML.
* @var callable
*/
public $code_span_content_func = null;
/**
* Class attribute to toggle "enhanced ordered list" behaviour
* setting this to true will allow ordered lists to start from the index
* number that is defined first.
*
* For example:
* 2. List item two
* 3. List item three
*
* Becomes:
* <ol start="2">
* <li>List item two</li>
* <li>List item three</li>
* </ol>
*
* @var bool
*/
public $enhanced_ordered_list = false;
/**
* Parser implementation
*/
/**
* Regex to match balanced [brackets].
* Needed to insert a maximum bracked depth while converting to PHP.
* @var int
*/
protected $nested_brackets_depth = 6;
protected $nested_brackets_re;
protected $nested_url_parenthesis_depth = 4;
protected $nested_url_parenthesis_re;
# Table of hash values for escaped characters:
/**
* Table of hash values for escaped characters:
* @var string
*/
protected $escape_chars = '\`*_{}[]()>#+-.!';
protected $escape_chars_re;
/**
* Constructor function. Initialize appropriate member variables.
* @return void
*/
public function __construct() {
#
# Constructor function. Initialize appropriate member variables.
#
$this->_initDetab();
$this->prepareItalicsAndBold();
$this->nested_brackets_re =
$this->nested_brackets_re =
str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
str_repeat('\])*', $this->nested_brackets_depth);
$this->nested_url_parenthesis_re =
$this->nested_url_parenthesis_re =
str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
$this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
# Sort document, block, and span gamut in ascendent priority order.
// Sort document, block, and span gamut in ascendent priority order.
asort($this->document_gamut);
asort($this->block_gamut);
asort($this->span_gamut);
}
# Internal hashes used during transformation.
protected $urls = array();
protected $titles = array();
/**
* Internal hashes used during transformation.
* @var array
*/
protected $urls = array();
protected $titles = array();
protected $html_hashes = array();
# Status flag to avoid invalid nesting.
/**
* Status flag to avoid invalid nesting.
* @var boolean
*/
protected $in_anchor = false;
/**
* Called before the transformation process starts to setup parser states.
* @return void
*/
protected function setup() {
#
# Called before the transformation process starts to setup parser
# states.
#
# Clear global hashes.
$this->urls = $this->predef_urls;
$this->titles = $this->predef_titles;
// Clear global hashes.
$this->urls = $this->predef_urls;
$this->titles = $this->predef_titles;
$this->html_hashes = array();
$this->in_anchor = false;
$this->in_anchor = false;
}
/**
* Called after the transformation process to clear any variable which may
* be taking up memory unnecessarly.
* @return void
*/
protected function teardown() {
#
# Called after the transformation process to clear any variable
# which may be taking up memory unnecessarly.
#
$this->urls = array();
$this->titles = array();
$this->urls = array();
$this->titles = array();
$this->html_hashes = array();
}
/**
* Main function. Performs some preprocessing on the input text and pass
* it through the document gamut.
*
* @api
*
* @param string $text
* @return string
*/
public function transform($text) {
#
# Main function. Performs some preprocessing on the input text
# and pass it through the document gamut.
#
$this->setup();
# Remove UTF-8 BOM and marker character in input, if present.
$text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
@ -168,28 +248,33 @@ class Markdown implements MarkdownInterface {
foreach ($this->document_gamut as $method => $priority) {
$text = $this->$method($text);
}
$this->teardown();
return $text . "\n";
}
/**
* Define the document gamut
* @var array
*/
protected $document_gamut = array(
# Strip link definitions, store in hashes.
// Strip link definitions, store in hashes.
"stripLinkDefinitions" => 20,
"runBasicBlockGamut" => 30,
);
);
/**
* Strips link definitions from text, stores the URLs and titles in
* hash references
* @param string $text
* @return string
*/
protected function stripLinkDefinitions($text) {
#
# Strips link definitions from text, stores the URLs and titles in
# hash references.
#
$less_than_tab = $this->tab_width - 1;
# Link defs are in the form: ^[id]: url "optional title"
// Link defs are in the form: ^[id]: url "optional title"
$text = preg_replace_callback('{
^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1
[ ]*
@ -213,43 +298,58 @@ class Markdown implements MarkdownInterface {
(?:\n+|\Z)
}xm',
array($this, '_stripLinkDefinitions_callback'),
$text);
$text
);
return $text;
}
/**
* The callback to strip link definitions
* @param array $matches
* @return string
*/
protected function _stripLinkDefinitions_callback($matches) {
$link_id = strtolower($matches[1]);
$url = $matches[2] == '' ? $matches[3] : $matches[2];
$this->urls[$link_id] = $url;
$this->titles[$link_id] =& $matches[4];
return ''; # String that will replace the block
return ''; // String that will replace the block
}
/**
* Hashify HTML blocks
* @param string $text
* @return string
*/
protected function hashHTMLBlocks($text) {
if ($this->no_markup) return $text;
if ($this->no_markup) {
return $text;
}
$less_than_tab = $this->tab_width - 1;
# Hashify HTML blocks:
# We only want to do this for block-level HTML tags, such as headers,
# lists, and tables. That's because we still want to wrap <p>s around
# "paragraphs" that are wrapped in non-block-level tags, such as anchors,
# phrase emphasis, and spans. The list of tags we're looking for is
# hard-coded:
#
# * List "a" is made of tags which can be both inline or block-level.
# These will be treated block-level when the start tag is alone on
# its line, otherwise they're not matched here and will be taken as
# inline later.
# * List "b" is made of tags which are always block-level;
#
/**
* Hashify HTML blocks:
*
* We only want to do this for block-level HTML tags, such as headers,
* lists, and tables. That's because we still want to wrap <p>s around
* "paragraphs" that are wrapped in non-block-level tags, such as
* anchors, phrase emphasis, and spans. The list of tags we're looking
* for is hard-coded:
*
* * List "a" is made of tags which can be both inline or block-level.
* These will be treated block-level when the start tag is alone on
* its line, otherwise they're not matched here and will be taken as
* inline later.
* * List "b" is made of tags which are always block-level;
*/
$block_tags_a_re = 'ins|del';
$block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
'script|noscript|style|form|fieldset|iframe|math|svg|'.
'article|section|nav|aside|hgroup|header|footer|'.
'figure';
# Regular expression for the content of a block tag.
// Regular expression for the content of a block tag.
$nested_tags_level = 4;
$attr = '
(?> # optional tag attributes
@ -263,7 +363,7 @@ class Markdown implements MarkdownInterface {
|
\'[^\']*\' # text inside single quotes (tolerate ">")
)*
)?
)?
';
$content =
str_repeat('
@ -275,29 +375,32 @@ class Markdown implements MarkdownInterface {
(?>
/>
|
>', $nested_tags_level). # end of opening tag
'.*?'. # last level nested tag content
>', $nested_tags_level). // end of opening tag
'.*?'. // last level nested tag content
str_repeat('
</\2\s*> # closing nested tag
)
|
|
<(?!/\2\s*> # other tags with a different name
)
)*',
$nested_tags_level);
$content2 = str_replace('\2', '\3', $content);
# First, look for nested blocks, e.g.:
# <div>
# <div>
# tags for inner block must be indented.
# </div>
# </div>
#
# The outermost tags must start at the left margin for this to match, and
# the inner nested divs must be indented.
# We need to do this before the next, more liberal match, because the next
# match will start at the first `<div>` and stop at the first `</div>`.
/**
* First, look for nested blocks, e.g.:
* <div>
* <div>
* tags for inner block must be indented.
* </div>
* </div>
*
* The outermost tags must start at the left margin for this to match,
* and the inner nested divs must be indented.
* We need to do this before the next, more liberal match, because the
* next match will start at the first `<div>` and stop at the
* first `</div>`.
*/
$text = preg_replace_callback('{(?>
(?>
(?<=\n) # Starting on its own line
@ -306,9 +409,9 @@ class Markdown implements MarkdownInterface {
)
( # save in $1
# Match from `\n<tag>` to `</tag>\n`, handling nested tags
# Match from `\n<tag>` to `</tag>\n`, handling nested tags
# in between.
[ ]{0,'.$less_than_tab.'}
<('.$block_tags_b_re.')# start tag = $2
'.$attr.'> # attributes followed by > and \n
@ -326,28 +429,28 @@ class Markdown implements MarkdownInterface {
</\3> # the matching end tag
[ ]* # trailing spaces/tabs
(?=\n+|\Z) # followed by a newline or end of document
| # Special case just for <hr />. It was easier to make a special
| # Special case just for <hr />. It was easier to make a special
# case than to make the other regex more complicated.
[ ]{0,'.$less_than_tab.'}
<(hr) # start tag = $2
'.$attr.' # attributes
/?> # the matching end tag
[ ]*
(?=\n{2,}|\Z) # followed by a blank line or end of document
| # Special case for standalone HTML comments:
[ ]{0,'.$less_than_tab.'}
(?s:
<!-- .*? -->
)
[ ]*
(?=\n{2,}|\Z) # followed by a blank line or end of document
| # PHP and ASP-style processor instructions (<? and <%)
[ ]{0,'.$less_than_tab.'}
(?s:
<([?%]) # $2
@ -356,98 +459,118 @@ class Markdown implements MarkdownInterface {
)
[ ]*
(?=\n{2,}|\Z) # followed by a blank line or end of document
)
)}Sxmi',
array($this, '_hashHTMLBlocks_callback'),
$text);
$text
);
return $text;
}
/**
* The callback for hashing HTML blocks
* @param string $matches
* @return string
*/
protected function _hashHTMLBlocks_callback($matches) {
$text = $matches[1];
$key = $this->hashBlock($text);
return "\n\n$key\n\n";
}
/**
* Called whenever a tag must be hashed when a function insert an atomic
* element in the text stream. Passing $text to through this function gives
* a unique text-token which will be reverted back when calling unhash.
*
* The $boundary argument specify what character should be used to surround
* the token. By convension, "B" is used for block elements that needs not
* to be wrapped into paragraph tags at the end, ":" is used for elements
* that are word separators and "X" is used in the general case.
*
* @param string $text
* @param string $boundary
* @return string
*/
protected function hashPart($text, $boundary = 'X') {
#
# Called whenever a tag must be hashed when a function insert an atomic
# element in the text stream. Passing $text to through this function gives
# a unique text-token which will be reverted back when calling unhash.
#
# The $boundary argument specify what character should be used to surround
# the token. By convension, "B" is used for block elements that needs not
# to be wrapped into paragraph tags at the end, ":" is used for elements
# that are word separators and "X" is used in the general case.
#
# Swap back any tag hash found in $text so we do not have to `unhash`
# multiple times at the end.
// Swap back any tag hash found in $text so we do not have to `unhash`
// multiple times at the end.
$text = $this->unhash($text);
# Then hash the block.
// Then hash the block.
static $i = 0;
$key = "$boundary\x1A" . ++$i . $boundary;
$this->html_hashes[$key] = $text;
return $key; # String that will replace the tag.
return $key; // String that will replace the tag.
}
/**
* Shortcut function for hashPart with block-level boundaries.
* @param string $text
* @return string
*/
protected function hashBlock($text) {
#
# Shortcut function for hashPart with block-level boundaries.
#
return $this->hashPart($text, 'B');
}
/**
* Define the block gamut - these are all the transformations that form
* block-level tags like paragraphs, headers, and list items.
* @var array
*/
protected $block_gamut = array(
#
# These are all the transformations that form block-level
# tags like paragraphs, headers, and list items.
#
"doHeaders" => 10,
"doHorizontalRules" => 20,
"doLists" => 40,
"doCodeBlocks" => 50,
"doBlockQuotes" => 60,
);
);
/**
* Run block gamut tranformations.
*
* We need to escape raw HTML in Markdown source before doing anything
* else. This need to be done for each block, and not only at the
* begining in the Markdown function since hashed blocks can be part of
* list items and could have been indented. Indented blocks would have
* been seen as a code block in a previous pass of hashHTMLBlocks.
*
* @param string $text
* @return string
*/
protected function runBlockGamut($text) {
#
# Run block gamut tranformations.
#
# We need to escape raw HTML in Markdown source before doing anything
# else. This need to be done for each block, and not only at the
# begining in the Markdown function since hashed blocks can be part of
# list items and could have been indented. Indented blocks would have
# been seen as a code block in a previous pass of hashHTMLBlocks.
$text = $this->hashHTMLBlocks($text);
return $this->runBasicBlockGamut($text);
}
/**
* Run block gamut tranformations, without hashing HTML blocks. This is
* useful when HTML blocks are known to be already hashed, like in the first
* whole-document pass.
*
* @param string $text
* @return string
*/
protected function runBasicBlockGamut($text) {
#
# Run block gamut tranformations, without hashing HTML blocks. This is
# useful when HTML blocks are known to be already hashed, like in the first
# whole-document pass.
#
foreach ($this->block_gamut as $method => $priority) {
$text = $this->$method($text);
}
# Finally form paragraph and restore hashed blocks.
// Finally form paragraph and restore hashed blocks.
$text = $this->formParagraphs($text);
return $text;
}
/**
* Convert horizontal rules
* @param string $text
* @return string
*/
protected function doHorizontalRules($text) {
# Do Horizontal Rules:
return preg_replace(
'{
^[ ]{0,3} # Leading space
@ -459,67 +582,82 @@ class Markdown implements MarkdownInterface {
[ ]* # Tailing spaces
$ # End of line.
}mx',
"\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n",
$text);
"\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n",
$text
);
}
/**
* These are all the transformations that occur *within* block-level
* tags like paragraphs, headers, and list items.
* @var array
*/
protected $span_gamut = array(
#
# These are all the transformations that occur *within* block-level
# tags like paragraphs, headers, and list items.
#
# Process character escapes, code spans, and inline HTML
# in one shot.
// Process character escapes, code spans, and inline HTML
// in one shot.
"parseSpan" => -30,
# Process anchor and image tags. Images must come first,
# because ![foo][f] looks like an anchor.
// Process anchor and image tags. Images must come first,
// because ![foo][f] looks like an anchor.
"doImages" => 10,
"doAnchors" => 20,
# Make links out of things like `<http://example.com/>`
# Must come after doAnchors, because you can use < and >
# delimiters in inline links like [this](<url>).
// Make links out of things like `<https://example.com/>`
// Must come after doAnchors, because you can use < and >
// delimiters in inline links like [this](<url>).
"doAutoLinks" => 30,
"encodeAmpsAndAngles" => 40,
"doItalicsAndBold" => 50,
"doHardBreaks" => 60,
);
);
/**
* Run span gamut transformations
* @param string $text
* @return string
*/
protected function runSpanGamut($text) {
#
# Run span gamut tranformations.
#
foreach ($this->span_gamut as $method => $priority) {
$text = $this->$method($text);
}
return $text;
}
/**
* Do hard breaks
* @param string $text
* @return string
*/
protected function doHardBreaks($text) {
# Do hard breaks:
return preg_replace_callback('/ {2,}\n/',
array($this, '_doHardBreaks_callback'), $text);
if ($this->hard_wrap) {
return preg_replace_callback('/ *\n/',
array($this, '_doHardBreaks_callback'), $text);
} else {
return preg_replace_callback('/ {2,}\n/',
array($this, '_doHardBreaks_callback'), $text);
}
}
/**
* Trigger part hashing for the hard break (callback method)
* @param array $matches
* @return string
*/
protected function _doHardBreaks_callback($matches) {
return $this->hashPart("<br$this->empty_element_suffix\n");
}
/**
* Turn Markdown link shortcuts into XHTML <a> tags.
* @param string $text
* @return string
*/
protected function doAnchors($text) {
#
# Turn Markdown link shortcuts into XHTML <a> tags.
#
if ($this->in_anchor) return $text;
if ($this->in_anchor) {
return $text;
}
$this->in_anchor = true;
#
# First, handle reference-style links: [link text] [id]
#
// First, handle reference-style links: [link text] [id]
$text = preg_replace_callback('{
( # wrap whole match in $1
\[
@ -536,9 +674,7 @@ class Markdown implements MarkdownInterface {
}xs',
array($this, '_doAnchors_reference_callback'), $text);
#
# Next, inline-style links: [link text](url "optional title")
#
// Next, inline-style links: [link text](url "optional title")
$text = preg_replace_callback('{
( # wrap whole match in $1
\[
@ -563,11 +699,9 @@ class Markdown implements MarkdownInterface {
}xs',
array($this, '_doAnchors_inline_callback'), $text);
#
# Last, handle reference-style shortcuts: [link text]
# These must come last in case you've also got [link text][1]
# or [link text](/foo)
#
// Last, handle reference-style shortcuts: [link text]
// These must come last in case you've also got [link text][1]
// or [link text](/foo)
$text = preg_replace_callback('{
( # wrap whole match in $1
\[
@ -580,48 +714,60 @@ class Markdown implements MarkdownInterface {
$this->in_anchor = false;
return $text;
}
/**
* Callback method to parse referenced anchors
* @param string $matches
* @return string
*/
protected function _doAnchors_reference_callback($matches) {
$whole_match = $matches[1];
$link_text = $matches[2];
$link_id =& $matches[3];
if ($link_id == "") {
# for shortcut links like [this][] or [this].
// for shortcut links like [this][] or [this].
$link_id = $link_text;
}
# lower-case and turn embedded newlines into spaces
// lower-case and turn embedded newlines into spaces
$link_id = strtolower($link_id);
$link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
if (isset($this->urls[$link_id])) {
$url = $this->urls[$link_id];
$url = $this->encodeURLAttribute($url);
$result = "<a href=\"$url\"";
if ( isset( $this->titles[$link_id] ) ) {
$title = $this->titles[$link_id];
$title = $this->encodeAttribute($title);
$result .= " title=\"$title\"";
}
$link_text = $this->runSpanGamut($link_text);
$result .= ">$link_text</a>";
$result = $this->hashPart($result);
}
else {
} else {
$result = $whole_match;
}
return $result;
}
/**
* Callback method to parse inline anchors
* @param string $matches
* @return string
*/
protected function _doAnchors_inline_callback($matches) {
$whole_match = $matches[1];
$link_text = $this->runSpanGamut($matches[2]);
$url = $matches[3] == '' ? $matches[4] : $matches[3];
$title =& $matches[7];
// if the URL was of the form <s p a c e s> it got caught by the HTML
// tag parser and hashed. Need to reverse the process before using the URL.
// If the URL was of the form <s p a c e s> it got caught by the HTML
// tag parser and hashed. Need to reverse the process before using
// the URL.
$unhashed = $this->unhash($url);
if ($unhashed != $url)
$url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
@ -633,21 +779,20 @@ class Markdown implements MarkdownInterface {
$title = $this->encodeAttribute($title);
$result .= " title=\"$title\"";
}
$link_text = $this->runSpanGamut($link_text);
$result .= ">$link_text</a>";
return $this->hashPart($result);
}
/**
* Turn Markdown image shortcuts into <img> tags.
* @param string $text
* @return string
*/
protected function doImages($text) {
#
# Turn Markdown image shortcuts into <img> tags.
#
#
# First, handle reference-style labeled images: ![alt text][id]
#
// First, handle reference-style labeled images: ![alt text][id]
$text = preg_replace_callback('{
( # wrap whole match in $1
!\[
@ -662,13 +807,11 @@ class Markdown implements MarkdownInterface {
\]
)
}xs',
}xs',
array($this, '_doImages_reference_callback'), $text);
#
# Next, handle inline images: ![alt text](url "optional title")
# Don't forget: encode * and _
#
// Next, handle inline images: ![alt text](url "optional title")
// Don't forget: encode * and _
$text = preg_replace_callback('{
( # wrap whole match in $1
!\[
@ -696,13 +839,19 @@ class Markdown implements MarkdownInterface {
return $text;
}
/**
* Callback to parse references image tags
* @param array $matches
* @return string
*/
protected function _doImages_reference_callback($matches) {
$whole_match = $matches[1];
$alt_text = $matches[2];
$link_id = strtolower($matches[3]);
if ($link_id == "") {
$link_id = strtolower($alt_text); # for shortcut links like ![this][].
$link_id = strtolower($alt_text); // for shortcut links like ![this][].
}
$alt_text = $this->encodeAttribute($alt_text);
@ -716,14 +865,19 @@ class Markdown implements MarkdownInterface {
}
$result .= $this->empty_element_suffix;
$result = $this->hashPart($result);
}
else {
# If there's no such link ID, leave intact:
} else {
// If there's no such link ID, leave intact:
$result = $whole_match;
}
return $result;
}
/**
* Callback to parse inline image tags
* @param array $matches
* @return string
*/
protected function _doImages_inline_callback($matches) {
$whole_match = $matches[1];
$alt_text = $matches[2];
@ -735,32 +889,38 @@ class Markdown implements MarkdownInterface {
$result = "<img src=\"$url\" alt=\"$alt_text\"";
if (isset($title)) {
$title = $this->encodeAttribute($title);
$result .= " title=\"$title\""; # $title already quoted
$result .= " title=\"$title\""; // $title already quoted
}
$result .= $this->empty_element_suffix;
return $this->hashPart($result);
}
/**
* Parse Markdown heading elements to HTML
* @param string $text
* @return string
*/
protected function doHeaders($text) {
# Setext-style headers:
# Header 1
# ========
#
# Header 2
# --------
#
/**
* Setext-style headers:
* Header 1
* ========
*
* Header 2
* --------
*/
$text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx',
array($this, '_doHeaders_callback_setext'), $text);
# atx-style headers:
# # Header 1
# ## Header 2
# ## Header 2 with closing hashes ##
# ...
# ###### Header 6
#
/**
* atx-style headers:
* # Header 1
* ## Header 2
* ## Header 2 with closing hashes ##
* ...
* ###### Header 6
*/
$text = preg_replace_callback('{
^(\#{1,6}) # $1 = string of #\'s
[ ]*
@ -773,29 +933,72 @@ class Markdown implements MarkdownInterface {
return $text;
}
/**
* Setext header parsing callback
* @param array $matches
* @return string
*/
protected function _doHeaders_callback_setext($matches) {
# Terrible hack to check we haven't found an empty list item.
if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1]))
// Terrible hack to check we haven't found an empty list item.
if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1])) {
return $matches[0];
}
$level = $matches[2]{0} == '=' ? 1 : 2;
$block = "<h$level>".$this->runSpanGamut($matches[1])."</h$level>";
// ID attribute generation
$idAtt = $this->_generateIdFromHeaderValue($matches[1]);
$block = "<h$level$idAtt>".$this->runSpanGamut($matches[1])."</h$level>";
return "\n" . $this->hashBlock($block) . "\n\n";
}
/**
* ATX header parsing callback
* @param array $matches
* @return string
*/
protected function _doHeaders_callback_atx($matches) {
// ID attribute generation
$idAtt = $this->_generateIdFromHeaderValue($matches[2]);
$level = strlen($matches[1]);
$block = "<h$level>".$this->runSpanGamut($matches[2])."</h$level>";
$block = "<h$level$idAtt>".$this->runSpanGamut($matches[2])."</h$level>";
return "\n" . $this->hashBlock($block) . "\n\n";
}
/**
* If a header_id_func property is set, we can use it to automatically
* generate an id attribute.
*
* This method returns a string in the form id="foo", or an empty string
* otherwise.
* @param string $headerValue
* @return string
*/
protected function _generateIdFromHeaderValue($headerValue) {
if (!is_callable($this->header_id_func)) {
return "";
}
$idValue = call_user_func($this->header_id_func, $headerValue);
if (!$idValue) {
return "";
}
return ' id="' . $this->encodeAttribute($idValue) . '"';
}
/**
* Form HTML ordered (numbered) and unordered (bulleted) lists.
* @param string $text
* @return string
*/
protected function doLists($text) {
#
# Form HTML ordered (numbered) and unordered (bulleted) lists.
#
$less_than_tab = $this->tab_width - 1;
# Re-usable patterns to match list item bullets and number markers:
// Re-usable patterns to match list item bullets and number markers:
$marker_ul_re = '[*+-]';
$marker_ol_re = '\d+[\.]';
@ -805,7 +1008,7 @@ class Markdown implements MarkdownInterface {
);
foreach ($markers_relist as $marker_re => $other_marker_re) {
# Re-usable pattern to match any entirel ul or ol list:
// Re-usable pattern to match any entirel ul or ol list:
$whole_list_re = '
( # $1 = whole list
( # $2
@ -832,18 +1035,17 @@ class Markdown implements MarkdownInterface {
)
)
'; // mx
# We use a different prefix before nested lists than top-level lists.
# See extended comment in _ProcessListItems().
// We use a different prefix before nested lists than top-level lists.
//See extended comment in _ProcessListItems().
if ($this->list_level) {
$text = preg_replace_callback('{
^
'.$whole_list_re.'
}mx',
array($this, '_doLists_callback'), $text);
}
else {
} else {
$text = preg_replace_callback('{
(?:(?<=\n)\n|\A\n?) # Must eat the newline
'.$whole_list_re.'
@ -854,55 +1056,86 @@ class Markdown implements MarkdownInterface {
return $text;
}
/**
* List parsing callback
* @param array $matches
* @return string
*/
protected function _doLists_callback($matches) {
# Re-usable patterns to match list item bullets and number markers:
// Re-usable patterns to match list item bullets and number markers:
$marker_ul_re = '[*+-]';
$marker_ol_re = '\d+[\.]';
$marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
$marker_ol_start_re = '[0-9]+';
$list = $matches[1];
$list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol";
$marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
$list .= "\n";
$result = $this->processListItems($list, $marker_any_re);
$result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
$ol_start = 1;
if ($this->enhanced_ordered_list) {
// Get the start number for ordered list.
if ($list_type == 'ol') {
$ol_start_array = array();
$ol_start_check = preg_match("/$marker_ol_start_re/", $matches[4], $ol_start_array);
if ($ol_start_check){
$ol_start = $ol_start_array[0];
}
}
}
if ($ol_start > 1 && $list_type == 'ol'){
$result = $this->hashBlock("<$list_type start=\"$ol_start\">\n" . $result . "</$list_type>");
} else {
$result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
}
return "\n". $result ."\n\n";
}
/**
* Nesting tracker for list levels
* @var integer
*/
protected $list_level = 0;
/**
* Process the contents of a single ordered or unordered list, splitting it
* into individual list items.
* @param string $list_str
* @param string $marker_any_re
* @return string
*/
protected function processListItems($list_str, $marker_any_re) {
#
# Process the contents of a single ordered or unordered list, splitting it
# into individual list items.
#
# The $this->list_level global keeps track of when we're inside a list.
# Each time we enter a list, we increment it; when we leave a list,
# we decrement. If it's zero, we're not in a list anymore.
#
# We do this because when we're not inside a list, we want to treat
# something like this:
#
# I recommend upgrading to version
# 8. Oops, now this line is treated
# as a sub-list.
#
# As a single paragraph, despite the fact that the second line starts
# with a digit-period-space sequence.
#
# Whereas when we're inside a list (or sub-list), that line will be
# treated as the start of a sub-list. What a kludge, huh? This is
# an aspect of Markdown's syntax that's hard to parse perfectly
# without resorting to mind-reading. Perhaps the solution is to
# change the syntax rules such that sub-lists must start with a
# starting cardinal number; e.g. "1." or "a.".
/**
* The $this->list_level global keeps track of when we're inside a list.
* Each time we enter a list, we increment it; when we leave a list,
* we decrement. If it's zero, we're not in a list anymore.
*
* We do this because when we're not inside a list, we want to treat
* something like this:
*
* I recommend upgrading to version
* 8. Oops, now this line is treated
* as a sub-list.
*
* As a single paragraph, despite the fact that the second line starts
* with a digit-period-space sequence.
*
* Whereas when we're inside a list (or sub-list), that line will be
* treated as the start of a sub-list. What a kludge, huh? This is
* an aspect of Markdown's syntax that's hard to parse perfectly
* without resorting to mind-reading. Perhaps the solution is to
* change the syntax rules such that sub-lists must start with a
* starting cardinal number; e.g. "1." or "a.".
*/
$this->list_level++;
# trim trailing blank lines:
// Trim trailing blank lines:
$list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
$list_str = preg_replace_callback('{
@ -920,6 +1153,12 @@ class Markdown implements MarkdownInterface {
$this->list_level--;
return $list_str;
}
/**
* List item parsing callback
* @param array $matches
* @return string
*/
protected function _processListItems_callback($matches) {
$item = $matches[4];
$leading_line =& $matches[1];
@ -927,28 +1166,27 @@ class Markdown implements MarkdownInterface {
$marker_space = $matches[3];
$tailing_blank_line =& $matches[5];
if ($leading_line || $tailing_blank_line ||
if ($leading_line || $tailing_blank_line ||
preg_match('/\n{2,}/', $item))
{
# Replace marker with the appropriate whitespace indentation
// Replace marker with the appropriate whitespace indentation
$item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
$item = $this->runBlockGamut($this->outdent($item)."\n");
}
else {
# Recursion for sub-lists:
} else {
// Recursion for sub-lists:
$item = $this->doLists($this->outdent($item));
$item = preg_replace('/\n+$/', '', $item);
$item = $this->runSpanGamut($item);
$item = $this->formParagraphs($item, false);
}
return "<li>" . $item . "</li>\n";
}
/**
* Process Markdown `<pre><code>` blocks.
* @param string $text
* @return string
*/
protected function doCodeBlocks($text) {
#
# Process Markdown `<pre><code>` blocks.
#
$text = preg_replace_callback('{
(?:\n\n|\A\n?)
( # $1 = the code block -- one or more lines, starting with a space/tab
@ -963,106 +1201,141 @@ class Markdown implements MarkdownInterface {
return $text;
}
/**
* Code block parsing callback
* @param array $matches
* @return string
*/
protected function _doCodeBlocks_callback($matches) {
$codeblock = $matches[1];
$codeblock = $this->outdent($codeblock);
$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
if ($this->code_block_content_func) {
$codeblock = call_user_func($this->code_block_content_func, $codeblock, "");
} else {
$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
}
# trim leading newlines and trailing newlines
$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
$codeblock = "<pre><code>$codeblock\n</code></pre>";
return "\n\n".$this->hashBlock($codeblock)."\n\n";
return "\n\n" . $this->hashBlock($codeblock) . "\n\n";
}
/**
* Create a code span markup for $code. Called from handleSpanToken.
* @param string $code
* @return string
*/
protected function makeCodeSpan($code) {
#
# Create a code span markup for $code. Called from handleSpanToken.
#
$code = htmlspecialchars(trim($code), ENT_NOQUOTES);
if ($this->code_span_content_func) {
$code = call_user_func($this->code_span_content_func, $code);
} else {
$code = htmlspecialchars(trim($code), ENT_NOQUOTES);
}
return $this->hashPart("<code>$code</code>");
}
/**
* Define the emphasis operators with their regex matches
* @var array
*/
protected $em_relist = array(
'' => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?![\.,:;]?\s)',
'*' => '(?<![\s*])\*(?!\*)',
'_' => '(?<![\s_])_(?!_)',
);
);
/**
* Define the strong operators with their regex matches
* @var array
*/
protected $strong_relist = array(
'' => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?![\.,:;]?\s)',
'**' => '(?<![\s*])\*\*(?!\*)',
'__' => '(?<![\s_])__(?!_)',
);
);
/**
* Define the emphasis + strong operators with their regex matches
* @var array
*/
protected $em_strong_relist = array(
'' => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?![\.,:;]?\s)',
'***' => '(?<![\s*])\*\*\*(?!\*)',
'___' => '(?<![\s_])___(?!_)',
);
);
/**
* Container for prepared regular expressions
* @var array
*/
protected $em_strong_prepared_relist;
/**
* Prepare regular expressions for searching emphasis tokens in any
* context.
* @return void
*/
protected function prepareItalicsAndBold() {
#
# Prepare regular expressions for searching emphasis tokens in any
# context.
#
foreach ($this->em_relist as $em => $em_re) {
foreach ($this->strong_relist as $strong => $strong_re) {
# Construct list of allowed token expressions.
// Construct list of allowed token expressions.
$token_relist = array();
if (isset($this->em_strong_relist["$em$strong"])) {
$token_relist[] = $this->em_strong_relist["$em$strong"];
}
$token_relist[] = $em_re;
$token_relist[] = $strong_re;
# Construct master expression from list.
$token_re = '{('. implode('|', $token_relist) .')}';
// Construct master expression from list.
$token_re = '{(' . implode('|', $token_relist) . ')}';
$this->em_strong_prepared_relist["$em$strong"] = $token_re;
}
}
}
/**
* Convert Markdown italics (emphasis) and bold (strong) to HTML
* @param string $text
* @return string
*/
protected function doItalicsAndBold($text) {
$token_stack = array('');
$text_stack = array('');
$em = '';
$strong = '';
$tree_char_em = false;
while (1) {
#
# Get prepared regular expression for seraching emphasis tokens
# in current context.
#
// Get prepared regular expression for seraching emphasis tokens
// in current context.
$token_re = $this->em_strong_prepared_relist["$em$strong"];
#
# Each loop iteration search for the next emphasis token.
# Each token is then passed to handleSpanToken.
#
// Each loop iteration search for the next emphasis token.
// Each token is then passed to handleSpanToken.
$parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
$text_stack[0] .= $parts[0];
$token =& $parts[1];
$text =& $parts[2];
if (empty($token)) {
# Reached end of text span: empty stack without emitting.
# any more emphasis.
// Reached end of text span: empty stack without emitting.
// any more emphasis.
while ($token_stack[0]) {
$text_stack[1] .= array_shift($token_stack);
$text_stack[0] .= array_shift($text_stack);
}
break;
}
$token_len = strlen($token);
if ($tree_char_em) {
# Reached closing marker while inside a three-char emphasis.
// Reached closing marker while inside a three-char emphasis.
if ($token_len == 3) {
# Three-char closing marker, close em and strong.
// Three-char closing marker, close em and strong.
array_shift($token_stack);
$span = array_shift($text_stack);
$span = $this->runSpanGamut($span);
@ -1071,21 +1344,21 @@ class Markdown implements MarkdownInterface {
$em = '';
$strong = '';
} else {
# Other closing marker: close one em or strong and
# change current token state to match the other
// Other closing marker: close one em or strong and
// change current token state to match the other
$token_stack[0] = str_repeat($token{0}, 3-$token_len);
$tag = $token_len == 2 ? "strong" : "em";
$span = $text_stack[0];
$span = $this->runSpanGamut($span);
$span = "<$tag>$span</$tag>";
$text_stack[0] = $this->hashPart($span);
$$tag = ''; # $$tag stands for $em or $strong
$$tag = ''; // $$tag stands for $em or $strong
}
$tree_char_em = false;
} else if ($token_len == 3) {
if ($em) {
# Reached closing marker for both em and strong.
# Closing strong marker:
// Reached closing marker for both em and strong.
// Closing strong marker:
for ($i = 0; $i < 2; ++$i) {
$shifted_token = array_shift($token_stack);
$tag = strlen($shifted_token) == 2 ? "strong" : "em";
@ -1093,11 +1366,11 @@ class Markdown implements MarkdownInterface {
$span = $this->runSpanGamut($span);
$span = "<$tag>$span</$tag>";
$text_stack[0] .= $this->hashPart($span);
$$tag = ''; # $$tag stands for $em or $strong
$$tag = ''; // $$tag stands for $em or $strong
}
} else {
# Reached opening three-char emphasis marker. Push on token
# stack; will be handled by the special condition above.
// Reached opening three-char emphasis marker. Push on token
// stack; will be handled by the special condition above.
$em = $token{0};
$strong = "$em$em";
array_unshift($token_stack, $token);
@ -1106,12 +1379,12 @@ class Markdown implements MarkdownInterface {
}
} else if ($token_len == 2) {
if ($strong) {
# Unwind any dangling emphasis marker:
// Unwind any dangling emphasis marker:
if (strlen($token_stack[0]) == 1) {
$text_stack[1] .= array_shift($token_stack);
$text_stack[0] .= array_shift($text_stack);
}
# Closing strong marker:
// Closing strong marker:
array_shift($token_stack);
$span = array_shift($text_stack);
$span = $this->runSpanGamut($span);
@ -1124,10 +1397,10 @@ class Markdown implements MarkdownInterface {
$strong = $token;
}
} else {
# Here $token_len == 1
// Here $token_len == 1
if ($em) {
if (strlen($token_stack[0]) == 1) {
# Closing emphasis marker:
// Closing emphasis marker:
array_shift($token_stack);
$span = array_shift($text_stack);
$span = $this->runSpanGamut($span);
@ -1147,7 +1420,11 @@ class Markdown implements MarkdownInterface {
return $text_stack[0];
}
/**
* Parse Markdown blockquotes to HTML
* @param string $text
* @return string
*/
protected function doBlockQuotes($text) {
$text = preg_replace_callback('/
( # Wrap whole match in $1
@ -1163,51 +1440,64 @@ class Markdown implements MarkdownInterface {
return $text;
}
/**
* Blockquote parsing callback
* @param array $matches
* @return string
*/
protected function _doBlockQuotes_callback($matches) {
$bq = $matches[1];
# trim one level of quoting - trim whitespace-only lines
// trim one level of quoting - trim whitespace-only lines
$bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
$bq = $this->runBlockGamut($bq); # recurse
$bq = $this->runBlockGamut($bq); // recurse
$bq = preg_replace('/^/m', " ", $bq);
# These leading spaces cause problem with <pre> content,
# so we need to fix that:
$bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx',
// These leading spaces cause problem with <pre> content,
// so we need to fix that:
$bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx',
array($this, '_doBlockQuotes_callback2'), $bq);
return "\n". $this->hashBlock("<blockquote>\n$bq\n</blockquote>")."\n\n";
return "\n" . $this->hashBlock("<blockquote>\n$bq\n</blockquote>") . "\n\n";
}
/**
* Blockquote parsing callback
* @param array $matches
* @return string
*/
protected function _doBlockQuotes_callback2($matches) {
$pre = $matches[1];
$pre = preg_replace('/^ /m', '', $pre);
return $pre;
}
protected function formParagraphs($text) {
#
# Params:
# $text - string to process with html <p> tags
#
# Strip leading and trailing lines:
/**
* Parse paragraphs
*
* @param string $text String to process in paragraphs
* @param boolean $wrap_in_p Whether paragraphs should be wrapped in <p> tags
* @return string
*/
protected function formParagraphs($text, $wrap_in_p = true) {
// Strip leading and trailing lines:
$text = preg_replace('/\A\n+|\n+\z/', '', $text);
$grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
#
# Wrap <p> tags and unhashify HTML blocks
#
// Wrap <p> tags and unhashify HTML blocks
foreach ($grafs as $key => $value) {
if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
# Is a paragraph.
// Is a paragraph.
$value = $this->runSpanGamut($value);
$value = preg_replace('/^([ ]*)/', "<p>", $value);
$value .= "</p>";
if ($wrap_in_p) {
$value = preg_replace('/^([ ]*)/', "<p>", $value);
$value .= "</p>";
}
$grafs[$key] = $this->unhash($value);
}
else {
# Is a block.
# Modify elements of @grafs in-place...
} else {
// Is a block.
// Modify elements of @grafs in-place...
$graf = $value;
$block = $this->html_hashes[$graf];
$graf = $block;
@ -1232,11 +1522,11 @@ class Markdown implements MarkdownInterface {
// {
// list(, $div_open, , $div_content, $div_close) = $matches;
//
// # We can't call Markdown(), because that resets the hash;
// # that initialization code should be pulled into its own sub, though.
// // We can't call Markdown(), because that resets the hash;
// // that initialization code should be pulled into its own sub, though.
// $div_content = $this->hashHTMLBlocks($div_content);
//
// # Run document gamut methods on the content.
//
// // Run document gamut methods on the content.
// foreach ($this->document_gamut as $method => $priority) {
// $div_content = $this->$method($div_content);
// }
@ -1253,71 +1543,78 @@ class Markdown implements MarkdownInterface {
return implode("\n\n", $grafs);
}
/**
* Encode text for a double-quoted HTML attribute. This function
* is *not* suitable for attributes enclosed in single quotes.
* @param string $text
* @return string
*/
protected function encodeAttribute($text) {
#
# Encode text for a double-quoted HTML attribute. This function
# is *not* suitable for attributes enclosed in single quotes.
#
$text = $this->encodeAmpsAndAngles($text);
$text = str_replace('"', '&quot;', $text);
return $text;
}
/**
* Encode text for a double-quoted HTML attribute containing a URL,
* applying the URL filter if set. Also generates the textual
* representation for the URL (removing mailto: or tel:) storing it in $text.
* This function is *not* suitable for attributes enclosed in single quotes.
*
* @param string $url
* @param string &$text Passed by reference
* @return string URL
*/
protected function encodeURLAttribute($url, &$text = null) {
#
# Encode text for a double-quoted HTML attribute containing a URL,
# applying the URL filter if set. Also generates the textual
# representation for the URL (removing mailto: or tel:) storing it in $text.
# This function is *not* suitable for attributes enclosed in single quotes.
#
if ($this->url_filter_func)
if ($this->url_filter_func) {
$url = call_user_func($this->url_filter_func, $url);
}
if (preg_match('{^mailto:}i', $url))
if (preg_match('{^mailto:}i', $url)) {
$url = $this->encodeEntityObfuscatedAttribute($url, $text, 7);
else if (preg_match('{^tel:}i', $url))
{
} else if (preg_match('{^tel:}i', $url)) {
$url = $this->encodeAttribute($url);
$text = substr($url, 4);
}
else
{
} else {
$url = $this->encodeAttribute($url);
$text = $url;
}
return $url;
}
/**
* Smart processing for ampersands and angle brackets that need to
* be encoded. Valid character entities are left alone unless the
* no-entities mode is set.
* @param string $text
* @return string
*/
protected function encodeAmpsAndAngles($text) {
#
# Smart processing for ampersands and angle brackets that need to
# be encoded. Valid character entities are left alone unless the
# no-entities mode is set.
#
if ($this->no_entities) {
$text = str_replace('&', '&amp;', $text);
} else {
# Ampersand-encoding based entirely on Nat Irons's Amputator
# MT plugin: <http://bumppo.net/projects/amputator/>
$text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/',
// Ampersand-encoding based entirely on Nat Irons's Amputator
// MT plugin: <http://bumppo.net/projects/amputator/>
$text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/',
'&amp;', $text);
}
# Encode remaining <'s
// Encode remaining <'s
$text = str_replace('<', '&lt;', $text);
return $text;
}
/**
* Parse Markdown automatic links to anchor HTML tags
* @param string $text
* @return string
*/
protected function doAutoLinks($text) {
$text = preg_replace_callback('{<((https?|ftp|dict|tel):[^\'">\s]+)>}i',
array($this, '_doAutoLinks_url_callback'), $text);
# Email addresses: <address@domain.foo>
// Email addresses: <address@domain.foo>
$text = preg_replace_callback('{
<
(?:mailto:)?
@ -1340,11 +1637,23 @@ class Markdown implements MarkdownInterface {
return $text;
}
/**
* Parse URL callback
* @param array $matches
* @return string
*/
protected function _doAutoLinks_url_callback($matches) {
$url = $this->encodeURLAttribute($matches[1], $text);
$link = "<a href=\"$url\">$text</a>";
return $this->hashPart($link);
}
/**
* Parse email address callback
* @param array $matches
* @return string
*/
protected function _doAutoLinks_email_callback($matches) {
$addr = $matches[1];
$url = $this->encodeURLAttribute("mailto:$addr", $text);
@ -1352,42 +1661,52 @@ class Markdown implements MarkdownInterface {
return $this->hashPart($link);
}
/**
* Input: some text to obfuscate, e.g. "mailto:foo@example.com"
*
* Output: the same text but with most characters encoded as either a
* decimal or hex entity, in the hopes of foiling most address
* harvesting spam bots. E.g.:
*
* &#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x66;o&#111;
* &#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#111;
* &#x6d;
*
* Note: the additional output $tail is assigned the same value as the
* ouput, minus the number of characters specified by $head_length.
*
* Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
* With some optimizations by Milian Wolff. Forced encoding of HTML
* attribute special characters by Allan Odgaard.
*
* @param string $text
* @param string &$tail
* @param integer $head_length
* @return string
*/
protected function encodeEntityObfuscatedAttribute($text, &$tail = null, $head_length = 0) {
#
# Input: some text to obfuscate, e.g. "mailto:foo@example.com"
#
# Output: the same text but with most characters encoded as either a
# decimal or hex entity, in the hopes of foiling most address
# harvesting spam bots. E.g.:
#
# &#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x66;o&#111;
# &#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#111;
# &#x6d;
#
# Note: the additional output $tail is assigned the same value as the
# ouput, minus the number of characters specified by $head_length.
#
# Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
# With some optimizations by Milian Wolff. Forced encoding of HTML
# attribute special characters by Allan Odgaard.
#
if ($text == "") return $tail = "";
if ($text == "") {
return $tail = "";
}
$chars = preg_split('/(?<!^)(?!$)/', $text);
$seed = (int)abs(crc32($text) / strlen($text)); # Deterministic seed.
$seed = (int)abs(crc32($text) / strlen($text)); // Deterministic seed.
foreach ($chars as $key => $char) {
$ord = ord($char);
# Ignore non-ascii chars.
// Ignore non-ascii chars.
if ($ord < 128) {
$r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
# roughly 10% raw, 45% hex, 45% dec
# '@' *must* be encoded. I insist.
# '"' and '>' have to be encoded inside the attribute
if ($r > 90 && strpos('@"&>', $char) === false) /* do nothing */;
else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';';
else $chars[$key] = '&#'.$ord.';';
$r = ($seed * (1 + $key)) % 100; // Pseudo-random function.
// roughly 10% raw, 45% hex, 45% dec
// '@' *must* be encoded. I insist.
// '"' and '>' have to be encoded inside the attribute
if ($r > 90 && strpos('@"&>', $char) === false) {
/* do nothing */
} else if ($r < 45) {
$chars[$key] = '&#x'.dechex($ord).';';
} else {
$chars[$key] = '&#'.$ord.';';
}
}
}
@ -1397,14 +1716,15 @@ class Markdown implements MarkdownInterface {
return $text;
}
/**
* Take the string $str and parse it into tokens, hashing embeded HTML,
* escaped characters and handling code spans.
* @param string $str
* @return string
*/
protected function parseSpan($str) {
#
# Take the string $str and parse it into tokens, hashing embeded HTML,
# escaped characters and handling code spans.
#
$output = '';
$span_re = '{
(
\\\\'.$this->escape_chars_re.'
@ -1432,1720 +1752,145 @@ class Markdown implements MarkdownInterface {
}xs';
while (1) {
#
# Each loop iteration seach for either the next tag, the next
# openning code span marker, or the next escaped character.
# Each token is then passed to handleSpanToken.
#
// Each loop iteration seach for either the next tag, the next
// openning code span marker, or the next escaped character.
// Each token is then passed to handleSpanToken.
$parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
# Create token from text preceding tag.
// Create token from text preceding tag.
if ($parts[0] != "") {
$output .= $parts[0];
}
# Check if we reach the end.
// Check if we reach the end.
if (isset($parts[1])) {
$output .= $this->handleSpanToken($parts[1], $parts[2]);
$str = $parts[2];
}
else {
} else {
break;
}
}
return $output;
}
/**
* Handle $token provided by parseSpan by determining its nature and
* returning the corresponding value that should replace it.
* @param string $token
* @param string &$str
* @return string
*/
protected function handleSpanToken($token, &$str) {
#
# Handle $token provided by parseSpan by determining its nature and
# returning the corresponding value that should replace it.
#
switch ($token{0}) {
case "\\":
return $this->hashPart("&#". ord($token{1}). ";");
case "`":
# Search for end marker in remaining text.
if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm',
// Search for end marker in remaining text.
if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm',
$str, $matches))
{
$str = $matches[2];
$codespan = $this->makeCodeSpan($matches[1]);
return $this->hashPart($codespan);
}
return $token; // return as text since no ending marker found.
return $token; // Return as text since no ending marker found.
default:
return $this->hashPart($token);
}
}
/**
* Remove one level of line-leading tabs or spaces
* @param string $text
* @return string
*/
protected function outdent($text) {
#
# Remove one level of line-leading tabs or spaces
#
return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text);
return preg_replace('/^(\t|[ ]{1,' . $this->tab_width . '})/m', '', $text);
}
# String length function for detab. `_initDetab` will create a function to
# hanlde UTF-8 if the default function does not exist.
/**
* String length function for detab. `_initDetab` will create a function to
* handle UTF-8 if the default function does not exist.
* @var string
*/
protected $utf8_strlen = 'mb_strlen';
/**
* Replace tabs with the appropriate amount of spaces.
*
* For each line we separate the line in blocks delemited by tab characters.
* Then we reconstruct every line by adding the appropriate number of space
* between each blocks.
*
* @param string $text
* @return string
*/
protected function detab($text) {
#
# Replace tabs with the appropriate amount of space.
#
# For each line we separate the line in blocks delemited by
# tab characters. Then we reconstruct every line by adding the
# appropriate number of space between each blocks.
$text = preg_replace_callback('/^.*\t.*$/m',
array($this, '_detab_callback'), $text);
return $text;
}
/**
* Replace tabs callback
* @param string $matches
* @return string
*/
protected function _detab_callback($matches) {
$line = $matches[0];
$strlen = $this->utf8_strlen; # strlen function for UTF-8.
# Split in blocks.
$strlen = $this->utf8_strlen; // strlen function for UTF-8.
// Split in blocks.
$blocks = explode("\t", $line);
# Add each blocks to the line.
// Add each blocks to the line.
$line = $blocks[0];
unset($blocks[0]); # Do not add first block twice.
unset($blocks[0]); // Do not add first block twice.
foreach ($blocks as $block) {
# Calculate amount of space, insert spaces, insert block.
$amount = $this->tab_width -
// Calculate amount of space, insert spaces, insert block.
$amount = $this->tab_width -
$strlen($line, 'UTF-8') % $this->tab_width;
$line .= str_repeat(" ", $amount) . $block;
}
return $line;
}
/**
* Check for the availability of the function in the `utf8_strlen` property
* (initially `mb_strlen`). If the function is not available, create a
* function that will loosely count the number of UTF-8 characters with a
* regular expression.
* @return void
*/
protected function _initDetab() {
#
# Check for the availability of the function in the `utf8_strlen` property
# (initially `mb_strlen`). If the function is not available, create a
# function that will loosely count the number of UTF-8 characters with a
# regular expression.
#
if (function_exists($this->utf8_strlen)) return;
if (function_exists($this->utf8_strlen)) {
return;
}
$this->utf8_strlen = create_function('$text', 'return preg_match_all(
"/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/",
"/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/",
$text, $m);');
}
/**
* Swap back in all the tags hashed by _HashHTMLBlocks.
* @param string $text
* @return string
*/
protected function unhash($text) {
#
# Swap back in all the tags hashed by _HashHTMLBlocks.
#
return preg_replace_callback('/(.)\x1A[0-9]+\1/',
return preg_replace_callback('/(.)\x1A[0-9]+\1/',
array($this, '_unhash_callback'), $text);
}
/**
* Unhashing callback
* @param array $matches
* @return string
*/
protected function _unhash_callback($matches) {
return $this->html_hashes[$matches[0]];
}
}
#
# Temporary Markdown Extra Parser Implementation Class
#
# NOTE: DON'T USE THIS CLASS
# Currently the implementation of of Extra resides here in this temporary class.
# This makes it easier to propagate the changes between the three different
# packaging styles of PHP Markdown. When this issue is resolved, this
# MarkdownExtra_TmpImpl class here will disappear and \Michelf\MarkdownExtra
# will contain the code. So please use \Michelf\MarkdownExtra and ignore this
# one.
#
abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown {
### Configuration Variables ###
# Prefix for footnote ids.
public $fn_id_prefix = "";
# Optional title attribute for footnote links and backlinks.
public $fn_link_title = "";
public $fn_backlink_title = "";
# Optional class attribute for footnote links and backlinks.
public $fn_link_class = "footnote-ref";
public $fn_backlink_class = "footnote-backref";
# Class name for table cell alignment (%% replaced left/center/right)
# For instance: 'go-%%' becomes 'go-left' or 'go-right' or 'go-center'
# If empty, the align attribute is used instead of a class name.
public $table_align_class_tmpl = '';
# Optional class prefix for fenced code block.
public $code_class_prefix = "";
# Class attribute for code blocks goes on the `code` tag;
# setting this to true will put attributes on the `pre` tag instead.
public $code_attr_on_pre = false;
# Predefined abbreviations.
public $predef_abbr = array();
### Parser Implementation ###
public function __construct() {
#
# Constructor function. Initialize the parser object.
#
# Add extra escapable characters before parent constructor
# initialize the table.
$this->escape_chars .= ':|';
# Insert extra document, block, and span transformations.
# Parent constructor will do the sorting.
$this->document_gamut += array(
"doFencedCodeBlocks" => 5,
"stripFootnotes" => 15,
"stripAbbreviations" => 25,
"appendFootnotes" => 50,
);
$this->block_gamut += array(
"doFencedCodeBlocks" => 5,
"doTables" => 15,
"doDefLists" => 45,
);
$this->span_gamut += array(
"doFootnotes" => 5,
"doAbbreviations" => 70,
);
parent::__construct();
}
# Extra variables used during extra transformations.
protected $footnotes = array();
protected $footnotes_ordered = array();
protected $footnotes_ref_count = array();
protected $footnotes_numbers = array();
protected $abbr_desciptions = array();
protected $abbr_word_re = '';
# Give the current footnote number.
protected $footnote_counter = 1;
protected function setup() {
#
# Setting up Extra-specific variables.
#
parent::setup();
$this->footnotes = array();
$this->footnotes_ordered = array();
$this->footnotes_ref_count = array();
$this->footnotes_numbers = array();
$this->abbr_desciptions = array();
$this->abbr_word_re = '';
$this->footnote_counter = 1;
foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
if ($this->abbr_word_re)
$this->abbr_word_re .= '|';
$this->abbr_word_re .= preg_quote($abbr_word);
$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
}
}
protected function teardown() {
#
# Clearing Extra-specific variables.
#
$this->footnotes = array();
$this->footnotes_ordered = array();
$this->footnotes_ref_count = array();
$this->footnotes_numbers = array();
$this->abbr_desciptions = array();
$this->abbr_word_re = '';
parent::teardown();
}
### Extra Attribute Parser ###
# Expression to use to catch attributes (includes the braces)
protected $id_class_attr_catch_re = '\{((?:[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,})[ ]*\}';
# Expression to use when parsing in a context when no capture is desired
protected $id_class_attr_nocatch_re = '\{(?:[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}';
protected function doExtraAttributes($tag_name, $attr) {
#
# Parse attributes caught by the $this->id_class_attr_catch_re expression
# and return the HTML-formatted list of attributes.
#
# Currently supported attributes are .class and #id.
#
if (empty($attr)) return "";
# Split on components
preg_match_all('/[#.a-z][-_:a-zA-Z0-9=]+/', $attr, $matches);
$elements = $matches[0];
# handle classes and ids (only first id taken into account)
$classes = array();
$attributes = array();
$id = false;
foreach ($elements as $element) {
if ($element{0} == '.') {
$classes[] = substr($element, 1);
} else if ($element{0} == '#') {
if ($id === false) $id = substr($element, 1);
} else if (strpos($element, '=') > 0) {
$parts = explode('=', $element, 2);
$attributes[] = $parts[0] . '="' . $parts[1] . '"';
}
}
# compose attributes as string
$attr_str = "";
if (!empty($id)) {
$attr_str .= ' id="'.$id.'"';
}
if (!empty($classes)) {
$attr_str .= ' class="'.implode(" ", $classes).'"';
}
if (!$this->no_markup && !empty($attributes)) {
$attr_str .= ' '.implode(" ", $attributes);
}
return $attr_str;
}
protected function stripLinkDefinitions($text) {
#
# Strips link definitions from text, stores the URLs and titles in
# hash references.
#
$less_than_tab = $this->tab_width - 1;
# Link defs are in the form: ^[id]: url "optional title"
$text = preg_replace_callback('{
^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1
[ ]*
\n? # maybe *one* newline
[ ]*
(?:
<(.+?)> # url = $2
|
(\S+?) # url = $3
)
[ ]*
\n? # maybe one newline
[ ]*
(?:
(?<=\s) # lookbehind for whitespace
["(]
(.*?) # title = $4
[")]
[ ]*
)? # title is optional
(?:[ ]* '.$this->id_class_attr_catch_re.' )? # $5 = extra id & class attr
(?:\n+|\Z)
}xm',
array($this, '_stripLinkDefinitions_callback'),
$text);
return $text;
}
protected function _stripLinkDefinitions_callback($matches) {
$link_id = strtolower($matches[1]);
$url = $matches[2] == '' ? $matches[3] : $matches[2];
$this->urls[$link_id] = $url;
$this->titles[$link_id] =& $matches[4];
$this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]);
return ''; # String that will replace the block
}
### HTML Block Parser ###
# Tags that are always treated as block tags:
protected $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption|figure';
# Tags treated as block tags only if the opening tag is alone on its line:
protected $context_block_tags_re = 'script|noscript|style|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video';
# Tags where markdown="1" default to span mode:
protected $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
# Tags which must not have their contents modified, no matter where
# they appear:
protected $clean_tags_re = 'script|style|math|svg';
# Tags that do not need to be closed.
protected $auto_close_tags_re = 'hr|img|param|source|track';
protected function hashHTMLBlocks($text) {
#
# Hashify HTML Blocks and "clean tags".
#
# We only want to do this for block-level HTML tags, such as headers,
# lists, and tables. That's because we still want to wrap <p>s around
# "paragraphs" that are wrapped in non-block-level tags, such as anchors,
# phrase emphasis, and spans. The list of tags we're looking for is
# hard-coded.
#
# This works by calling _HashHTMLBlocks_InMarkdown, which then calls
# _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1"
# attribute is found within a tag, _HashHTMLBlocks_InHTML calls back
# _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
# These two functions are calling each other. It's recursive!
#
if ($this->no_markup) return $text;
#
# Call the HTML-in-Markdown hasher.
#
list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
return $text;
}
protected function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
$enclosing_tag_re = '', $span = false)
{
#
# Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
#
# * $indent is the number of space to be ignored when checking for code
# blocks. This is important because if we don't take the indent into
# account, something like this (which looks right) won't work as expected:
#
# <div>
# <div markdown="1">
# Hello World. <-- Is this a Markdown code block or text?
# </div> <-- Is this a Markdown code block or a real tag?
# <div>
#
# If you don't like this, just don't indent the tag on which
# you apply the markdown="1" attribute.
#
# * If $enclosing_tag_re is not empty, stops at the first unmatched closing
# tag with that name. Nested tags supported.
#
# * If $span is true, text inside must treated as span. So any double
# newline will be replaced by a single newline so that it does not create
# paragraphs.
#
# Returns an array of that form: ( processed text , remaining text )
#
if ($text === '') return array('', '');
# Regex to check for the presense of newlines around a block tag.
$newline_before_re = '/(?:^\n?|\n\n)*$/';
$newline_after_re =
'{
^ # Start of text following the tag.
(?>[ ]*<!--.*?-->)? # Optional comment.
[ ]*\n # Must be followed by newline.
}xs';
# Regex to match any tag.
$block_tag_re =
'{
( # $2: Capture whole tag.
</? # Any opening or closing tag.
(?> # Tag name.
'.$this->block_tags_re.' |
'.$this->context_block_tags_re.' |
'.$this->clean_tags_re.' |
(?!\s)'.$enclosing_tag_re.'
)
(?:
(?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name.
(?>
".*?" | # Double quotes (can contain `>`)
\'.*?\' | # Single quotes (can contain `>`)
.+? # Anything but quotes and `>`.
)*?
)?
> # End of tag.
|
<!-- .*? --> # HTML Comment
|
<\?.*?\?> | <%.*?%> # Processing instruction
|
<!\[CDATA\[.*?\]\]> # CData Block
'. ( !$span ? ' # If not in span.
|
# Indented code block
(?: ^[ ]*\n | ^ | \n[ ]*\n )
[ ]{'.($indent+4).'}[^\n]* \n
(?>
(?: [ ]{'.($indent+4).'}[^\n]* | [ ]* ) \n
)*
|
# Fenced code block marker
(?<= ^ | \n )
[ ]{0,'.($indent+3).'}(?:~{3,}|`{3,})
[ ]*
(?:
\.?[-_:a-zA-Z0-9]+ # standalone class name
|
'.$this->id_class_attr_nocatch_re.' # extra attributes
)?
[ ]*
(?= \n )
' : '' ). ' # End (if not is span).
|
# Code span marker
# Note, this regex needs to go after backtick fenced
# code blocks but it should also be kept outside of the
# "if not in span" condition adding backticks to the parser
`+
)
}xs';
$depth = 0; # Current depth inside the tag tree.
$parsed = ""; # Parsed text that will be returned.
#
# Loop through every tag until we find the closing tag of the parent
# or loop until reaching the end of text if no parent tag specified.
#
do {
#
# Split the text using the first $tag_match pattern found.
# Text before pattern will be first in the array, text after
# pattern will be at the end, and between will be any catches made
# by the pattern.
#
$parts = preg_split($block_tag_re, $text, 2,
PREG_SPLIT_DELIM_CAPTURE);
# If in Markdown span mode, add a empty-string span-level hash
# after each newline to prevent triggering any block element.
if ($span) {
$void = $this->hashPart("", ':');
$newline = "$void\n";
$parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
}
$parsed .= $parts[0]; # Text before current tag.
# If end of $text has been reached. Stop loop.
if (count($parts) < 3) {
$text = "";
break;
}
$tag = $parts[1]; # Tag to handle.
$text = $parts[2]; # Remaining text after current tag.
$tag_re = preg_quote($tag); # For use in a regular expression.
#
# Check for: Fenced code block marker.
# Note: need to recheck the whole tag to disambiguate backtick
# fences from code spans
#
if (preg_match('{^\n?([ ]{0,'.($indent+3).'})(~{3,}|`{3,})[ ]*(?:\.?[-_:a-zA-Z0-9]+|'.$this->id_class_attr_nocatch_re.')?[ ]*\n?$}', $tag, $capture)) {
# Fenced code block marker: find matching end marker.
$fence_indent = strlen($capture[1]); # use captured indent in re
$fence_re = $capture[2]; # use captured fence in re
if (preg_match('{^(?>.*\n)*?[ ]{'.($fence_indent).'}'.$fence_re.'[ ]*(?:\n|$)}', $text,
$matches))
{
# End marker found: pass text unchanged until marker.
$parsed .= $tag . $matches[0];
$text = substr($text, strlen($matches[0]));
}
else {
# No end marker: just skip it.
$parsed .= $tag;
}
}
#
# Check for: Indented code block.
#
else if ($tag{0} == "\n" || $tag{0} == " ") {
# Indented code block: pass it unchanged, will be handled
# later.
$parsed .= $tag;
}
#
# Check for: Code span marker
# Note: need to check this after backtick fenced code blocks
#
else if ($tag{0} == "`") {
# Find corresponding end marker.
$tag_re = preg_quote($tag);
if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)'.$tag_re.'(?!`)}',
$text, $matches))
{
# End marker found: pass text unchanged until marker.
$parsed .= $tag . $matches[0];
$text = substr($text, strlen($matches[0]));
}
else {
# Unmatched marker: just skip it.
$parsed .= $tag;
}
}
#
# Check for: Opening Block level tag or
# Opening Context Block tag (like ins and del)
# used as a block tag (tag is alone on it's line).
#
else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) ||
( preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) &&
preg_match($newline_before_re, $parsed) &&
preg_match($newline_after_re, $text) )
)
{
# Need to parse tag and following text using the HTML parser.
list($block_text, $text) =
$this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
# Make sure it stays outside of any paragraph by adding newlines.
$parsed .= "\n\n$block_text\n\n";
}
#
# Check for: Clean tag (like script, math)
# HTML Comments, processing instructions.
#
else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) ||
$tag{1} == '!' || $tag{1} == '?')
{
# Need to parse tag and following text using the HTML parser.
# (don't check for markdown attribute)
list($block_text, $text) =
$this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
$parsed .= $block_text;
}
#
# Check for: Tag with same name as enclosing tag.
#
else if ($enclosing_tag_re !== '' &&
# Same name as enclosing tag.
preg_match('{^</?(?:'.$enclosing_tag_re.')\b}', $tag))
{
#
# Increase/decrease nested tag count.
#
if ($tag{1} == '/') $depth--;
else if ($tag{strlen($tag)-2} != '/') $depth++;
if ($depth < 0) {
#
# Going out of parent element. Clean up and break so we
# return to the calling function.
#
$text = $tag . $text;
break;
}
$parsed .= $tag;
}
else {
$parsed .= $tag;
}
} while ($depth >= 0);
return array($parsed, $text);
}
protected function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
#
# Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
#
# * Calls $hash_method to convert any blocks.
# * Stops when the first opening tag closes.
# * $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
# (it is not inside clean tags)
#
# Returns an array of that form: ( processed text , remaining text )
#
if ($text === '') return array('', '');
# Regex to match `markdown` attribute inside of a tag.
$markdown_attr_re = '
{
\s* # Eat whitespace before the `markdown` attribute
markdown
\s*=\s*
(?>
(["\']) # $1: quote delimiter
(.*?) # $2: attribute value
\1 # matching delimiter
|
([^\s>]*) # $3: unquoted attribute value
)
() # $4: make $3 always defined (avoid warnings)
}xs';
# Regex to match any tag.
$tag_re = '{
( # $2: Capture whole tag.
</? # Any opening or closing tag.
[\w:$]+ # Tag name.
(?:
(?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name.
(?>
".*?" | # Double quotes (can contain `>`)
\'.*?\' | # Single quotes (can contain `>`)
.+? # Anything but quotes and `>`.
)*?
)?
> # End of tag.
|
<!-- .*? --> # HTML Comment
|
<\?.*?\?> | <%.*?%> # Processing instruction
|
<!\[CDATA\[.*?\]\]> # CData Block
)
}xs';
$original_text = $text; # Save original text in case of faliure.
$depth = 0; # Current depth inside the tag tree.
$block_text = ""; # Temporary text holder for current text.
$parsed = ""; # Parsed text that will be returned.
#
# Get the name of the starting tag.
# (This pattern makes $base_tag_name_re safe without quoting.)
#
if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
$base_tag_name_re = $matches[1];
#
# Loop through every tag until we find the corresponding closing tag.
#
do {
#
# Split the text using the first $tag_match pattern found.
# Text before pattern will be first in the array, text after
# pattern will be at the end, and between will be any catches made
# by the pattern.
#
$parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
if (count($parts) < 3) {
#
# End of $text reached with unbalenced tag(s).
# In that case, we return original text unchanged and pass the
# first character as filtered to prevent an infinite loop in the
# parent function.
#
return array($original_text{0}, substr($original_text, 1));
}
$block_text .= $parts[0]; # Text before current tag.
$tag = $parts[1]; # Tag to handle.
$text = $parts[2]; # Remaining text after current tag.
#
# Check for: Auto-close tag (like <hr/>)
# Comments and Processing Instructions.
#
if (preg_match('{^</?(?:'.$this->auto_close_tags_re.')\b}', $tag) ||
$tag{1} == '!' || $tag{1} == '?')
{
# Just add the tag to the block as if it was text.
$block_text .= $tag;
}
else {
#
# Increase/decrease nested tag count. Only do so if
# the tag's name match base tag's.
#
if (preg_match('{^</?'.$base_tag_name_re.'\b}', $tag)) {
if ($tag{1} == '/') $depth--;
else if ($tag{strlen($tag)-2} != '/') $depth++;
}
#
# Check for `markdown="1"` attribute and handle it.
#
if ($md_attr &&
preg_match($markdown_attr_re, $tag, $attr_m) &&
preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
{
# Remove `markdown` attribute from opening tag.
$tag = preg_replace($markdown_attr_re, '', $tag);
# Check if text inside this tag must be parsed in span mode.
$this->mode = $attr_m[2] . $attr_m[3];
$span_mode = $this->mode == 'span' || $this->mode != 'block' &&
preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag);
# Calculate indent before tag.
if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
$strlen = $this->utf8_strlen;
$indent = $strlen($matches[1], 'UTF-8');
} else {
$indent = 0;
}
# End preceding block with this tag.
$block_text .= $tag;
$parsed .= $this->$hash_method($block_text);
# Get enclosing tag name for the ParseMarkdown function.
# (This pattern makes $tag_name_re safe without quoting.)
preg_match('/^<([\w:$]*)\b/', $tag, $matches);
$tag_name_re = $matches[1];
# Parse the content using the HTML-in-Markdown parser.
list ($block_text, $text)
= $this->_hashHTMLBlocks_inMarkdown($text, $indent,
$tag_name_re, $span_mode);
# Outdent markdown text.
if ($indent > 0) {
$block_text = preg_replace("/^[ ]{1,$indent}/m", "",
$block_text);
}
# Append tag content to parsed text.
if (!$span_mode) $parsed .= "\n\n$block_text\n\n";
else $parsed .= "$block_text";
# Start over with a new block.
$block_text = "";
}
else $block_text .= $tag;
}
} while ($depth > 0);
#
# Hash last block text that wasn't processed inside the loop.
#
$parsed .= $this->$hash_method($block_text);
return array($parsed, $text);
}
protected function hashClean($text) {
#
# Called whenever a tag must be hashed when a function inserts a "clean" tag
# in $text, it passes through this function and is automaticaly escaped,
# blocking invalid nested overlap.
#
return $this->hashPart($text, 'C');
}
protected function doAnchors($text) {
#
# Turn Markdown link shortcuts into XHTML <a> tags.
#
if ($this->in_anchor) return $text;
$this->in_anchor = true;
#
# First, handle reference-style links: [link text] [id]
#
$text = preg_replace_callback('{
( # wrap whole match in $1
\[
('.$this->nested_brackets_re.') # link text = $2
\]
[ ]? # one optional space
(?:\n[ ]*)? # one optional newline followed by spaces
\[
(.*?) # id = $3
\]
)
}xs',
array($this, '_doAnchors_reference_callback'), $text);
#
# Next, inline-style links: [link text](url "optional title")
#
$text = preg_replace_callback('{
( # wrap whole match in $1
\[
('.$this->nested_brackets_re.') # link text = $2
\]
\( # literal paren
[ \n]*
(?:
<(.+?)> # href = $3
|
('.$this->nested_url_parenthesis_re.') # href = $4
)
[ \n]*
( # $5
([\'"]) # quote char = $6
(.*?) # Title = $7
\6 # matching quote
[ \n]* # ignore any spaces/tabs between closing quote and )
)? # title is optional
\)
(?:[ ]? '.$this->id_class_attr_catch_re.' )? # $8 = id/class attributes
)
}xs',
array($this, '_doAnchors_inline_callback'), $text);
#
# Last, handle reference-style shortcuts: [link text]
# These must come last in case you've also got [link text][1]
# or [link text](/foo)
#
$text = preg_replace_callback('{
( # wrap whole match in $1
\[
([^\[\]]+) # link text = $2; can\'t contain [ or ]
\]
)
}xs',
array($this, '_doAnchors_reference_callback'), $text);
$this->in_anchor = false;
return $text;
}
protected function _doAnchors_reference_callback($matches) {
$whole_match = $matches[1];
$link_text = $matches[2];
$link_id =& $matches[3];
if ($link_id == "") {
# for shortcut links like [this][] or [this].
$link_id = $link_text;
}
# lower-case and turn embedded newlines into spaces
$link_id = strtolower($link_id);
$link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
if (isset($this->urls[$link_id])) {
$url = $this->urls[$link_id];
$url = $this->encodeURLAttribute($url);
$result = "<a href=\"$url\"";
if ( isset( $this->titles[$link_id] ) ) {
$title = $this->titles[$link_id];
$title = $this->encodeAttribute($title);
$result .= " title=\"$title\"";
}
if (isset($this->ref_attr[$link_id]))
$result .= $this->ref_attr[$link_id];
$link_text = $this->runSpanGamut($link_text);
$result .= ">$link_text</a>";
$result = $this->hashPart($result);
}
else {
$result = $whole_match;
}
return $result;
}
protected function _doAnchors_inline_callback($matches) {
$whole_match = $matches[1];
$link_text = $this->runSpanGamut($matches[2]);
$url = $matches[3] == '' ? $matches[4] : $matches[3];
$title =& $matches[7];
$attr = $this->doExtraAttributes("a", $dummy =& $matches[8]);
// if the URL was of the form <s p a c e s> it got caught by the HTML
// tag parser and hashed. Need to reverse the process before using the URL.
$unhashed = $this->unhash($url);
if ($unhashed != $url)
$url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
$url = $this->encodeURLAttribute($url);
$result = "<a href=\"$url\"";
if (isset($title)) {
$title = $this->encodeAttribute($title);
$result .= " title=\"$title\"";
}
$result .= $attr;
$link_text = $this->runSpanGamut($link_text);
$result .= ">$link_text</a>";
return $this->hashPart($result);
}
protected function doImages($text) {
#
# Turn Markdown image shortcuts into <img> tags.
#
#
# First, handle reference-style labeled images: ![alt text][id]
#
$text = preg_replace_callback('{
( # wrap whole match in $1
!\[
('.$this->nested_brackets_re.') # alt text = $2
\]
[ ]? # one optional space
(?:\n[ ]*)? # one optional newline followed by spaces
\[
(.*?) # id = $3
\]
)
}xs',
array($this, '_doImages_reference_callback'), $text);
#
# Next, handle inline images: ![alt text](url "optional title")
# Don't forget: encode * and _
#
$text = preg_replace_callback('{
( # wrap whole match in $1
!\[
('.$this->nested_brackets_re.') # alt text = $2
\]
\s? # One optional whitespace character
\( # literal paren
[ \n]*
(?:
<(\S*)> # src url = $3
|
('.$this->nested_url_parenthesis_re.') # src url = $4
)
[ \n]*
( # $5
([\'"]) # quote char = $6
(.*?) # title = $7
\6 # matching quote
[ \n]*
)? # title is optional
\)
(?:[ ]? '.$this->id_class_attr_catch_re.' )? # $8 = id/class attributes
)
}xs',
array($this, '_doImages_inline_callback'), $text);
return $text;
}
protected function _doImages_reference_callback($matches) {
$whole_match = $matches[1];
$alt_text = $matches[2];
$link_id = strtolower($matches[3]);
if ($link_id == "") {
$link_id = strtolower($alt_text); # for shortcut links like ![this][].
}
$alt_text = $this->encodeAttribute($alt_text);
if (isset($this->urls[$link_id])) {
$url = $this->encodeURLAttribute($this->urls[$link_id]);
$result = "<img src=\"$url\" alt=\"$alt_text\"";
if (isset($this->titles[$link_id])) {
$title = $this->titles[$link_id];
$title = $this->encodeAttribute($title);
$result .= " title=\"$title\"";
}
if (isset($this->ref_attr[$link_id]))
$result .= $this->ref_attr[$link_id];
$result .= $this->empty_element_suffix;
$result = $this->hashPart($result);
}
else {
# If there's no such link ID, leave intact:
$result = $whole_match;
}
return $result;
}
protected function _doImages_inline_callback($matches) {
$whole_match = $matches[1];
$alt_text = $matches[2];
$url = $matches[3] == '' ? $matches[4] : $matches[3];
$title =& $matches[7];
$attr = $this->doExtraAttributes("img", $dummy =& $matches[8]);
$alt_text = $this->encodeAttribute($alt_text);
$url = $this->encodeURLAttribute($url);
$result = "<img src=\"$url\" alt=\"$alt_text\"";
if (isset($title)) {
$title = $this->encodeAttribute($title);
$result .= " title=\"$title\""; # $title already quoted
}
$result .= $attr;
$result .= $this->empty_element_suffix;
return $this->hashPart($result);
}
protected function doHeaders($text) {
#
# Redefined to add id and class attribute support.
#
# Setext-style headers:
# Header 1 {#header1}
# ========
#
# Header 2 {#header2 .class1 .class2}
# --------
#
$text = preg_replace_callback(
'{
(^.+?) # $1: Header text
(?:[ ]+ '.$this->id_class_attr_catch_re.' )? # $3 = id/class attributes
[ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer
}mx',
array($this, '_doHeaders_callback_setext'), $text);
# atx-style headers:
# # Header 1 {#header1}
# ## Header 2 {#header2}
# ## Header 2 with closing hashes ## {#header3.class1.class2}
# ...
# ###### Header 6 {.class2}
#
$text = preg_replace_callback('{
^(\#{1,6}) # $1 = string of #\'s
[ ]*
(.+?) # $2 = Header text
[ ]*
\#* # optional closing #\'s (not counted)
(?:[ ]+ '.$this->id_class_attr_catch_re.' )? # $3 = id/class attributes
[ ]*
\n+
}xm',
array($this, '_doHeaders_callback_atx'), $text);
return $text;
}
protected function _doHeaders_callback_setext($matches) {
if ($matches[3] == '-' && preg_match('{^- }', $matches[1]))
return $matches[0];
$level = $matches[3]{0} == '=' ? 1 : 2;
$attr = $this->doExtraAttributes("h$level", $dummy =& $matches[2]);
$block = "<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>";
return "\n" . $this->hashBlock($block) . "\n\n";
}
protected function _doHeaders_callback_atx($matches) {
$level = strlen($matches[1]);
$attr = $this->doExtraAttributes("h$level", $dummy =& $matches[3]);
$block = "<h$level$attr>".$this->runSpanGamut($matches[2])."</h$level>";
return "\n" . $this->hashBlock($block) . "\n\n";
}
protected function doTables($text) {
#
# Form HTML tables.
#
$less_than_tab = $this->tab_width - 1;
#
# Find tables with leading pipe.
#
# | Header 1 | Header 2
# | -------- | --------
# | Cell 1 | Cell 2
# | Cell 3 | Cell 4
#
$text = preg_replace_callback('
{
^ # Start of a line
[ ]{0,'.$less_than_tab.'} # Allowed whitespace.
[|] # Optional leading pipe (present)
(.+) \n # $1: Header row (at least one pipe)
[ ]{0,'.$less_than_tab.'} # Allowed whitespace.
[|] ([ ]*[-:]+[-| :]*) \n # $2: Header underline
( # $3: Cells
(?>
[ ]* # Allowed whitespace.
[|] .* \n # Row content.
)*
)
(?=\n|\Z) # Stop at final double newline.
}xm',
array($this, '_doTable_leadingPipe_callback'), $text);
#
# Find tables without leading pipe.
#
# Header 1 | Header 2
# -------- | --------
# Cell 1 | Cell 2
# Cell 3 | Cell 4
#
$text = preg_replace_callback('
{
^ # Start of a line
[ ]{0,'.$less_than_tab.'} # Allowed whitespace.
(\S.*[|].*) \n # $1: Header row (at least one pipe)
[ ]{0,'.$less_than_tab.'} # Allowed whitespace.
([-:]+[ ]*[|][-| :]*) \n # $2: Header underline
( # $3: Cells
(?>
.* [|] .* \n # Row content
)*
)
(?=\n|\Z) # Stop at final double newline.
}xm',
array($this, '_DoTable_callback'), $text);
return $text;
}
protected function _doTable_leadingPipe_callback($matches) {
$head = $matches[1];
$underline = $matches[2];
$content = $matches[3];
# Remove leading pipe for each row.
$content = preg_replace('/^ *[|]/m', '', $content);
return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
}
protected function _doTable_makeAlignAttr($alignname)
{
if (empty($this->table_align_class_tmpl))
return " align=\"$alignname\"";
$classname = str_replace('%%', $alignname, $this->table_align_class_tmpl);
return " class=\"$classname\"";
}
protected function _doTable_callback($matches) {
$head = $matches[1];
$underline = $matches[2];
$content = $matches[3];
# Remove any tailing pipes for each line.
$head = preg_replace('/[|] *$/m', '', $head);
$underline = preg_replace('/[|] *$/m', '', $underline);
$content = preg_replace('/[|] *$/m', '', $content);
# Reading alignement from header underline.
$separators = preg_split('/ *[|] */', $underline);
foreach ($separators as $n => $s) {
if (preg_match('/^ *-+: *$/', $s))
$attr[$n] = $this->_doTable_makeAlignAttr('right');
else if (preg_match('/^ *:-+: *$/', $s))
$attr[$n] = $this->_doTable_makeAlignAttr('center');
else if (preg_match('/^ *:-+ *$/', $s))
$attr[$n] = $this->_doTable_makeAlignAttr('left');
else
$attr[$n] = '';
}
# Parsing span elements, including code spans, character escapes,
# and inline HTML tags, so that pipes inside those gets ignored.
$head = $this->parseSpan($head);
$headers = preg_split('/ *[|] */', $head);
$col_count = count($headers);
$attr = array_pad($attr, $col_count, '');
# Write column headers.
$text = "<table>\n";
$text .= "<thead>\n";
$text .= "<tr>\n";
foreach ($headers as $n => $header)
$text .= " <th$attr[$n]>".$this->runSpanGamut(trim($header))."</th>\n";
$text .= "</tr>\n";
$text .= "</thead>\n";
# Split content by row.
$rows = explode("\n", trim($content, "\n"));
$text .= "<tbody>\n";
foreach ($rows as $row) {
# Parsing span elements, including code spans, character escapes,
# and inline HTML tags, so that pipes inside those gets ignored.
$row = $this->parseSpan($row);
# Split row by cell.
$row_cells = preg_split('/ *[|] */', $row, $col_count);
$row_cells = array_pad($row_cells, $col_count, '');
$text .= "<tr>\n";
foreach ($row_cells as $n => $cell)
$text .= " <td$attr[$n]>".$this->runSpanGamut(trim($cell))."</td>\n";
$text .= "</tr>\n";
}
$text .= "</tbody>\n";
$text .= "</table>";
return $this->hashBlock($text) . "\n";
}
protected function doDefLists($text) {
#
# Form HTML definition lists.
#
$less_than_tab = $this->tab_width - 1;
# Re-usable pattern to match any entire dl list:
$whole_list_re = '(?>
( # $1 = whole list
( # $2
[ ]{0,'.$less_than_tab.'}
((?>.*\S.*\n)+) # $3 = defined term
\n?
[ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
)
(?s:.+?)
( # $4
\z
|
\n{2,}
(?=\S)
(?! # Negative lookahead for another term
[ ]{0,'.$less_than_tab.'}
(?: \S.*\n )+? # defined term
\n?
[ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
)
(?! # Negative lookahead for another definition
[ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
)
)
)
)'; // mx
$text = preg_replace_callback('{
(?>\A\n?|(?<=\n\n))
'.$whole_list_re.'
}mx',
array($this, '_doDefLists_callback'), $text);
return $text;
}
protected function _doDefLists_callback($matches) {
# Re-usable patterns to match list item bullets and number markers:
$list = $matches[1];
# Turn double returns into triple returns, so that we can make a
# paragraph for the last item in a list, if necessary:
$result = trim($this->processDefListItems($list));
$result = "<dl>\n" . $result . "\n</dl>";
return $this->hashBlock($result) . "\n\n";
}
protected function processDefListItems($list_str) {
#
# Process the contents of a single definition list, splitting it
# into individual term and definition list items.
#
$less_than_tab = $this->tab_width - 1;
# trim trailing blank lines:
$list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
# Process definition terms.
$list_str = preg_replace_callback('{
(?>\A\n?|\n\n+) # leading line
( # definition terms = $1
[ ]{0,'.$less_than_tab.'} # leading whitespace
(?!\:[ ]|[ ]) # negative lookahead for a definition
# mark (colon) or more whitespace.
(?> \S.* \n)+? # actual term (not whitespace).
)
(?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed
# with a definition mark.
}xm',
array($this, '_processDefListItems_callback_dt'), $list_str);
# Process actual definitions.
$list_str = preg_replace_callback('{
\n(\n+)? # leading line = $1
( # marker space = $2
[ ]{0,'.$less_than_tab.'} # whitespace before colon
\:[ ]+ # definition mark (colon)
)
((?s:.+?)) # definition text = $3
(?= \n+ # stop at next definition mark,
(?: # next term or end of text
[ ]{0,'.$less_than_tab.'} \:[ ] |
<dt> | \z
)
)
}xm',
array($this, '_processDefListItems_callback_dd'), $list_str);
return $list_str;
}
protected function _processDefListItems_callback_dt($matches) {
$terms = explode("\n", trim($matches[1]));
$text = '';
foreach ($terms as $term) {
$term = $this->runSpanGamut(trim($term));
$text .= "\n<dt>" . $term . "</dt>";
}
return $text . "\n";
}
protected function _processDefListItems_callback_dd($matches) {
$leading_line = $matches[1];
$marker_space = $matches[2];
$def = $matches[3];
if ($leading_line || preg_match('/\n{2,}/', $def)) {
# Replace marker with the appropriate whitespace indentation
$def = str_repeat(' ', strlen($marker_space)) . $def;
$def = $this->runBlockGamut($this->outdent($def . "\n\n"));
$def = "\n". $def ."\n";
}
else {
$def = rtrim($def);
$def = $this->runSpanGamut($this->outdent($def));
}
return "\n<dd>" . $def . "</dd>\n";
}
protected function doFencedCodeBlocks($text) {
#
# Adding the fenced code block syntax to regular Markdown:
#
# ~~~
# Code block
# ~~~
#
$less_than_tab = $this->tab_width;
$text = preg_replace_callback('{
(?:\n|\A)
# 1: Opening marker
(
(?:~{3,}|`{3,}) # 3 or more tildes/backticks.
)
[ ]*
(?:
\.?([-_:a-zA-Z0-9]+) # 2: standalone class name
|
'.$this->id_class_attr_catch_re.' # 3: Extra attributes
)?
[ ]* \n # Whitespace and newline following marker.
# 4: Content
(
(?>
(?!\1 [ ]* \n) # Not a closing marker.
.*\n+
)+
)
# Closing marker.
\1 [ ]* (?= \n )
}xm',
array($this, '_doFencedCodeBlocks_callback'), $text);
return $text;
}
protected function _doFencedCodeBlocks_callback($matches) {
$classname =& $matches[2];
$attrs =& $matches[3];
$codeblock = $matches[4];
$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
$codeblock = preg_replace_callback('/^\n+/',
array($this, '_doFencedCodeBlocks_newlines'), $codeblock);
if ($classname != "") {
if ($classname{0} == '.')
$classname = substr($classname, 1);
$attr_str = ' class="'.$this->code_class_prefix.$classname.'"';
} else {
$attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs);
}
$pre_attr_str = $this->code_attr_on_pre ? $attr_str : '';
$code_attr_str = $this->code_attr_on_pre ? '' : $attr_str;
$codeblock = "<pre$pre_attr_str><code$code_attr_str>$codeblock</code></pre>";
return "\n\n".$this->hashBlock($codeblock)."\n\n";
}
protected function _doFencedCodeBlocks_newlines($matches) {
return str_repeat("<br$this->empty_element_suffix",
strlen($matches[0]));
}
#
# Redefining emphasis markers so that emphasis by underscore does not
# work in the middle of a word.
#
protected $em_relist = array(
'' => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?![\.,:;]?\s)',
'*' => '(?<![\s*])\*(?!\*)',
'_' => '(?<![\s_])_(?![a-zA-Z0-9_])',
);
protected $strong_relist = array(
'' => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?![\.,:;]?\s)',
'**' => '(?<![\s*])\*\*(?!\*)',
'__' => '(?<![\s_])__(?![a-zA-Z0-9_])',
);
protected $em_strong_relist = array(
'' => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?![\.,:;]?\s)',
'***' => '(?<![\s*])\*\*\*(?!\*)',
'___' => '(?<![\s_])___(?![a-zA-Z0-9_])',
);
protected function formParagraphs($text) {
#
# Params:
# $text - string to process with html <p> tags
#
# Strip leading and trailing lines:
$text = preg_replace('/\A\n+|\n+\z/', '', $text);
$grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
#
# Wrap <p> tags and unhashify HTML blocks
#
foreach ($grafs as $key => $value) {
$value = trim($this->runSpanGamut($value));
# Check if this should be enclosed in a paragraph.
# Clean tag hashes & block tag hashes are left alone.
$is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
if ($is_p) {
$value = "<p>$value</p>";
}
$grafs[$key] = $value;
}
# Join grafs in one text, then unhash HTML tags.
$text = implode("\n\n", $grafs);
# Finish by removing any tag hashes still present in $text.
$text = $this->unhash($text);
return $text;
}
### Footnotes
protected function stripFootnotes($text) {
#
# Strips link definitions from text, stores the URLs and titles in
# hash references.
#
$less_than_tab = $this->tab_width - 1;
# Link defs are in the form: [^id]: url "optional title"
$text = preg_replace_callback('{
^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?: # note_id = $1
[ ]*
\n? # maybe *one* newline
( # text = $2 (no blank lines allowed)
(?:
.+ # actual text
|
\n # newlines but
(?!\[.+?\][ ]?:\s)# negative lookahead for footnote or link definition marker.
(?!\n+[ ]{0,3}\S)# ensure line is not blank and followed
# by non-indented content
)*
)
}xm',
array($this, '_stripFootnotes_callback'),
$text);
return $text;
}
protected function _stripFootnotes_callback($matches) {
$note_id = $this->fn_id_prefix . $matches[1];
$this->footnotes[$note_id] = $this->outdent($matches[2]);
return ''; # String that will replace the block
}
protected function doFootnotes($text) {
#
# Replace footnote references in $text [^id] with a special text-token
# which will be replaced by the actual footnote marker in appendFootnotes.
#
if (!$this->in_anchor) {
$text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
}
return $text;
}
protected function appendFootnotes($text) {
#
# Append footnote list to text.
#
$text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
array($this, '_appendFootnotes_callback'), $text);
if (!empty($this->footnotes_ordered)) {
$text .= "\n\n";
$text .= "<div class=\"footnotes\">\n";
$text .= "<hr". $this->empty_element_suffix ."\n";
$text .= "<ol>\n\n";
$attr = "";
if ($this->fn_backlink_class != "") {
$class = $this->fn_backlink_class;
$class = $this->encodeAttribute($class);
$attr .= " class=\"$class\"";
}
if ($this->fn_backlink_title != "") {
$title = $this->fn_backlink_title;
$title = $this->encodeAttribute($title);
$attr .= " title=\"$title\"";
}
$num = 0;
while (!empty($this->footnotes_ordered)) {
$footnote = reset($this->footnotes_ordered);
$note_id = key($this->footnotes_ordered);
unset($this->footnotes_ordered[$note_id]);
$ref_count = $this->footnotes_ref_count[$note_id];
unset($this->footnotes_ref_count[$note_id]);
unset($this->footnotes[$note_id]);
$footnote .= "\n"; # Need to append newline before parsing.
$footnote = $this->runBlockGamut("$footnote\n");
$footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
array($this, '_appendFootnotes_callback'), $footnote);
$attr = str_replace("%%", ++$num, $attr);
$note_id = $this->encodeAttribute($note_id);
# Prepare backlink, multiple backlinks if multiple references
$backlink = "<a href=\"#fnref:$note_id\"$attr>&#8617;</a>";
for ($ref_num = 2; $ref_num <= $ref_count; ++$ref_num) {
$backlink .= " <a href=\"#fnref$ref_num:$note_id\"$attr>&#8617;</a>";
}
# Add backlink to last paragraph; create new paragraph if needed.
if (preg_match('{</p>$}', $footnote)) {
$footnote = substr($footnote, 0, -4) . "&#160;$backlink</p>";
} else {
$footnote .= "\n\n<p>$backlink</p>";
}
$text .= "<li id=\"fn:$note_id\">\n";
$text .= $footnote . "\n";
$text .= "</li>\n\n";
}
$text .= "</ol>\n";
$text .= "</div>";
}
return $text;
}
protected function _appendFootnotes_callback($matches) {
$node_id = $this->fn_id_prefix . $matches[1];
# Create footnote marker only if it has a corresponding footnote *and*
# the footnote hasn't been used by another marker.
if (isset($this->footnotes[$node_id])) {
$num =& $this->footnotes_numbers[$node_id];
if (!isset($num)) {
# Transfer footnote content to the ordered list and give it its
# number
$this->footnotes_ordered[$node_id] = $this->footnotes[$node_id];
$this->footnotes_ref_count[$node_id] = 1;
$num = $this->footnote_counter++;
$ref_count_mark = '';
} else {
$ref_count_mark = $this->footnotes_ref_count[$node_id] += 1;
}
$attr = "";
if ($this->fn_link_class != "") {
$class = $this->fn_link_class;
$class = $this->encodeAttribute($class);
$attr .= " class=\"$class\"";
}
if ($this->fn_link_title != "") {
$title = $this->fn_link_title;
$title = $this->encodeAttribute($title);
$attr .= " title=\"$title\"";
}
$attr = str_replace("%%", $num, $attr);
$node_id = $this->encodeAttribute($node_id);
return
"<sup id=\"fnref$ref_count_mark:$node_id\">".
"<a href=\"#fn:$node_id\"$attr>$num</a>".
"</sup>";
}
return "[^".$matches[1]."]";
}
### Abbreviations ###
protected function stripAbbreviations($text) {
#
# Strips abbreviations from text, stores titles in hash references.
#
$less_than_tab = $this->tab_width - 1;
# Link defs are in the form: [id]*: url "optional title"
$text = preg_replace_callback('{
^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?: # abbr_id = $1
(.*) # text = $2 (no blank lines allowed)
}xm',
array($this, '_stripAbbreviations_callback'),
$text);
return $text;
}
protected function _stripAbbreviations_callback($matches) {
$abbr_word = $matches[1];
$abbr_desc = $matches[2];
if ($this->abbr_word_re)
$this->abbr_word_re .= '|';
$this->abbr_word_re .= preg_quote($abbr_word);
$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
return ''; # String that will replace the block
}
protected function doAbbreviations($text) {
#
# Find defined abbreviations in text and wrap them in <abbr> elements.
#
if ($this->abbr_word_re) {
// cannot use the /x modifier because abbr_word_re may
// contain significant spaces:
$text = preg_replace_callback('{'.
'(?<![\w\x1A])'.
'(?:'.$this->abbr_word_re.')'.
'(?![\w\x1A])'.
'}',
array($this, '_doAbbreviations_callback'), $text);
}
return $text;
}
protected function _doAbbreviations_callback($matches) {
$abbr = $matches[0];
if (isset($this->abbr_desciptions[$abbr])) {
$desc = $this->abbr_desciptions[$abbr];
if (empty($desc)) {
return $this->hashPart("<abbr>$abbr</abbr>");
} else {
$desc = $this->encodeAttribute($desc);
return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>");
}
} else {
return $matches[0];
}
}
}

View file

@ -1,10 +1,10 @@
<?php
# Use this file if you cannot use class autoloading. It will include all the
# files needed for the MarkdownExtra parser.
#
# Take a look at the PSR-0-compatible class autoloading implementation
# in the Readme.php file if you want a simple autoloader setup.
// Use this file if you cannot use class autoloading. It will include all the
// files needed for the MarkdownExtra parser.
//
// Take a look at the PSR-0-compatible class autoloading implementation
// in the Readme.php file if you want a simple autoloader setup.
require_once dirname(__FILE__) . '/MarkdownInterface.php';
require_once dirname(__FILE__) . '/Markdown.php';

View file

@ -1,38 +1,1785 @@
<?php
#
# Markdown Extra - A text-to-HTML conversion tool for web writers
#
# PHP Markdown Extra
# Copyright (c) 2004-2014 Michel Fortin
# <http://michelf.com/projects/php-markdown/>
#
# Original Markdown
# Copyright (c) 2004-2006 John Gruber
# <http://daringfireball.net/projects/markdown/>
#
/**
* Markdown Extra - A text-to-HTML conversion tool for web writers
*
* @package php-markdown
* @author Michel Fortin <michel.fortin@michelf.com>
* @copyright 2004-2016 Michel Fortin <https://michelf.com/projects/php-markdown/>
* @copyright (Original Markdown) 2004-2006 John Gruber <https://daringfireball.net/projects/markdown/>
*/
namespace Michelf;
/**
* Markdown Extra Parser Class
*/
class MarkdownExtra extends \Michelf\Markdown {
/**
* Configuration variables
*/
# Just force Michelf/Markdown.php to load. This is needed to load
# the temporary implementation class. See below for details.
\Michelf\Markdown::MARKDOWNLIB_VERSION;
/**
* Prefix for footnote ids.
* @var string
*/
public $fn_id_prefix = "";
/**
* Optional title attribute for footnote links and backlinks.
* @var string
*/
public $fn_link_title = "";
public $fn_backlink_title = "";
/**
* Optional class attribute for footnote links and backlinks.
* @var string
*/
public $fn_link_class = "footnote-ref";
public $fn_backlink_class = "footnote-backref";
#
# Markdown Extra Parser Class
#
# Note: Currently the implementation resides in the temporary class
# \Michelf\MarkdownExtra_TmpImpl (in the same file as \Michelf\Markdown).
# This makes it easier to propagate the changes between the three different
# packaging styles of PHP Markdown. Once this issue is resolved, the
# _MarkdownExtra_TmpImpl will disappear and this one will contain the code.
#
/**
* Content to be displayed within footnote backlinks. The default is '↩';
* the U+FE0E on the end is a Unicode variant selector used to prevent iOS
* from displaying the arrow character as an emoji.
* @var string
*/
public $fn_backlink_html = '&#8617;&#xFE0E;';
class MarkdownExtra extends \Michelf\_MarkdownExtra_TmpImpl {
/**
* Class name for table cell alignment (%% replaced left/center/right)
* For instance: 'go-%%' becomes 'go-left' or 'go-right' or 'go-center'
* If empty, the align attribute is used instead of a class name.
* @var string
*/
public $table_align_class_tmpl = '';
### Parser Implementation ###
/**
* Optional class prefix for fenced code block.
* @var string
*/
public $code_class_prefix = "";
# Temporarily, the implemenation is in the _MarkdownExtra_TmpImpl class.
# See note above.
/**
* Class attribute for code blocks goes on the `code` tag;
* setting this to true will put attributes on the `pre` tag instead.
* @var boolean
*/
public $code_attr_on_pre = false;
/**
* Predefined abbreviations.
* @var array
*/
public $predef_abbr = array();
/**
* Parser implementation
*/
/**
* Constructor function. Initialize the parser object.
* @return void
*/
public function __construct() {
// Add extra escapable characters before parent constructor
// initialize the table.
$this->escape_chars .= ':|';
// Insert extra document, block, and span transformations.
// Parent constructor will do the sorting.
$this->document_gamut += array(
"doFencedCodeBlocks" => 5,
"stripFootnotes" => 15,
"stripAbbreviations" => 25,
"appendFootnotes" => 50,
);
$this->block_gamut += array(
"doFencedCodeBlocks" => 5,
"doTables" => 15,
"doDefLists" => 45,
);
$this->span_gamut += array(
"doFootnotes" => 5,
"doAbbreviations" => 70,
);
$this->enhanced_ordered_list = true;
parent::__construct();
}
/**
* Extra variables used during extra transformations.
* @var array
*/
protected $footnotes = array();
protected $footnotes_ordered = array();
protected $footnotes_ref_count = array();
protected $footnotes_numbers = array();
protected $abbr_desciptions = array();
/** @var string */
protected $abbr_word_re = '';
/**
* Give the current footnote number.
* @var integer
*/
protected $footnote_counter = 1;
/**
* Setting up Extra-specific variables.
*/
protected function setup() {
parent::setup();
$this->footnotes = array();
$this->footnotes_ordered = array();
$this->footnotes_ref_count = array();
$this->footnotes_numbers = array();
$this->abbr_desciptions = array();
$this->abbr_word_re = '';
$this->footnote_counter = 1;
foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
if ($this->abbr_word_re)
$this->abbr_word_re .= '|';
$this->abbr_word_re .= preg_quote($abbr_word);
$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
}
}
/**
* Clearing Extra-specific variables.
*/
protected function teardown() {
$this->footnotes = array();
$this->footnotes_ordered = array();
$this->footnotes_ref_count = array();
$this->footnotes_numbers = array();
$this->abbr_desciptions = array();
$this->abbr_word_re = '';
parent::teardown();
}
/**
* Extra attribute parser
*/
/**
* Expression to use to catch attributes (includes the braces)
* @var string
*/
protected $id_class_attr_catch_re = '\{((?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,})[ ]*\}';
/**
* Expression to use when parsing in a context when no capture is desired
* @var string
*/
protected $id_class_attr_nocatch_re = '\{(?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}';
/**
* Parse attributes caught by the $this->id_class_attr_catch_re expression
* and return the HTML-formatted list of attributes.
*
* Currently supported attributes are .class and #id.
*
* In addition, this method also supports supplying a default Id value,
* which will be used to populate the id attribute in case it was not
* overridden.
* @param string $tag_name
* @param string $attr
* @param mixed $defaultIdValue
* @param array $classes
* @return string
*/
protected function doExtraAttributes($tag_name, $attr, $defaultIdValue = null, $classes = array()) {
if (empty($attr) && !$defaultIdValue && empty($classes)) return "";
// Split on components
preg_match_all('/[#.a-z][-_:a-zA-Z0-9=]+/', $attr, $matches);
$elements = $matches[0];
// Handle classes and IDs (only first ID taken into account)
$attributes = array();
$id = false;
foreach ($elements as $element) {
if ($element{0} == '.') {
$classes[] = substr($element, 1);
} else if ($element{0} == '#') {
if ($id === false) $id = substr($element, 1);
} else if (strpos($element, '=') > 0) {
$parts = explode('=', $element, 2);
$attributes[] = $parts[0] . '="' . $parts[1] . '"';
}
}
if (!$id) $id = $defaultIdValue;
// Compose attributes as string
$attr_str = "";
if (!empty($id)) {
$attr_str .= ' id="'.$this->encodeAttribute($id) .'"';
}
if (!empty($classes)) {
$attr_str .= ' class="'. implode(" ", $classes) . '"';
}
if (!$this->no_markup && !empty($attributes)) {
$attr_str .= ' '.implode(" ", $attributes);
}
return $attr_str;
}
/**
* Strips link definitions from text, stores the URLs and titles in
* hash references.
* @param string $text
* @return string
*/
protected function stripLinkDefinitions($text) {
$less_than_tab = $this->tab_width - 1;
// Link defs are in the form: ^[id]: url "optional title"
$text = preg_replace_callback('{
^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1
[ ]*
\n? # maybe *one* newline
[ ]*
(?:
<(.+?)> # url = $2
|
(\S+?) # url = $3
)
[ ]*
\n? # maybe one newline
[ ]*
(?:
(?<=\s) # lookbehind for whitespace
["(]
(.*?) # title = $4
[")]
[ ]*
)? # title is optional
(?:[ ]* '.$this->id_class_attr_catch_re.' )? # $5 = extra id & class attr
(?:\n+|\Z)
}xm',
array($this, '_stripLinkDefinitions_callback'),
$text);
return $text;
}
/**
* Strip link definition callback
* @param array $matches
* @return string
*/
protected function _stripLinkDefinitions_callback($matches) {
$link_id = strtolower($matches[1]);
$url = $matches[2] == '' ? $matches[3] : $matches[2];
$this->urls[$link_id] = $url;
$this->titles[$link_id] =& $matches[4];
$this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]);
return ''; // String that will replace the block
}
/**
* HTML block parser
*/
/**
* Tags that are always treated as block tags
* @var string
*/
protected $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption|figure';
/**
* Tags treated as block tags only if the opening tag is alone on its line
* @var string
*/
protected $context_block_tags_re = 'script|noscript|style|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video';
/**
* Tags where markdown="1" default to span mode:
* @var string
*/
protected $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
/**
* Tags which must not have their contents modified, no matter where
* they appear
* @var string
*/
protected $clean_tags_re = 'script|style|math|svg';
/**
* Tags that do not need to be closed.
* @var string
*/
protected $auto_close_tags_re = 'hr|img|param|source|track';
/**
* Hashify HTML Blocks and "clean tags".
*
* We only want to do this for block-level HTML tags, such as headers,
* lists, and tables. That's because we still want to wrap <p>s around
* "paragraphs" that are wrapped in non-block-level tags, such as anchors,
* phrase emphasis, and spans. The list of tags we're looking for is
* hard-coded.
*
* This works by calling _HashHTMLBlocks_InMarkdown, which then calls
* _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1"
* attribute is found within a tag, _HashHTMLBlocks_InHTML calls back
* _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
* These two functions are calling each other. It's recursive!
* @param string $text
* @return string
*/
protected function hashHTMLBlocks($text) {
if ($this->no_markup) {
return $text;
}
// Call the HTML-in-Markdown hasher.
list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
return $text;
}
/**
* Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
*
* * $indent is the number of space to be ignored when checking for code
* blocks. This is important because if we don't take the indent into
* account, something like this (which looks right) won't work as expected:
*
* <div>
* <div markdown="1">
* Hello World. <-- Is this a Markdown code block or text?
* </div> <-- Is this a Markdown code block or a real tag?
* <div>
*
* If you don't like this, just don't indent the tag on which
* you apply the markdown="1" attribute.
*
* * If $enclosing_tag_re is not empty, stops at the first unmatched closing
* tag with that name. Nested tags supported.
*
* * If $span is true, text inside must treated as span. So any double
* newline will be replaced by a single newline so that it does not create
* paragraphs.
*
* Returns an array of that form: ( processed text , remaining text )
*
* @param string $text
* @param integer $indent
* @param string $enclosing_tag_re
* @param boolean $span
* @return array
*/
protected function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
$enclosing_tag_re = '', $span = false)
{
if ($text === '') return array('', '');
// Regex to check for the presense of newlines around a block tag.
$newline_before_re = '/(?:^\n?|\n\n)*$/';
$newline_after_re =
'{
^ # Start of text following the tag.
(?>[ ]*<!--.*?-->)? # Optional comment.
[ ]*\n # Must be followed by newline.
}xs';
// Regex to match any tag.
$block_tag_re =
'{
( # $2: Capture whole tag.
</? # Any opening or closing tag.
(?> # Tag name.
' . $this->block_tags_re . ' |
' . $this->context_block_tags_re . ' |
' . $this->clean_tags_re . ' |
(?!\s)'.$enclosing_tag_re . '
)
(?:
(?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name.
(?>
".*?" | # Double quotes (can contain `>`)
\'.*?\' | # Single quotes (can contain `>`)
.+? # Anything but quotes and `>`.
)*?
)?
> # End of tag.
|
<!-- .*? --> # HTML Comment
|
<\?.*?\?> | <%.*?%> # Processing instruction
|
<!\[CDATA\[.*?\]\]> # CData Block
' . ( !$span ? ' # If not in span.
|
# Indented code block
(?: ^[ ]*\n | ^ | \n[ ]*\n )
[ ]{' . ($indent + 4) . '}[^\n]* \n
(?>
(?: [ ]{' . ($indent + 4) . '}[^\n]* | [ ]* ) \n
)*
|
# Fenced code block marker
(?<= ^ | \n )
[ ]{0,' . ($indent + 3) . '}(?:~{3,}|`{3,})
[ ]*
(?: \.?[-_:a-zA-Z0-9]+ )? # standalone class name
[ ]*
(?: ' . $this->id_class_attr_nocatch_re . ' )? # extra attributes
[ ]*
(?= \n )
' : '' ) . ' # End (if not is span).
|
# Code span marker
# Note, this regex needs to go after backtick fenced
# code blocks but it should also be kept outside of the
# "if not in span" condition adding backticks to the parser
`+
)
}xs';
$depth = 0; // Current depth inside the tag tree.
$parsed = ""; // Parsed text that will be returned.
// Loop through every tag until we find the closing tag of the parent
// or loop until reaching the end of text if no parent tag specified.
do {
// Split the text using the first $tag_match pattern found.
// Text before pattern will be first in the array, text after
// pattern will be at the end, and between will be any catches made
// by the pattern.
$parts = preg_split($block_tag_re, $text, 2,
PREG_SPLIT_DELIM_CAPTURE);
// If in Markdown span mode, add a empty-string span-level hash
// after each newline to prevent triggering any block element.
if ($span) {
$void = $this->hashPart("", ':');
$newline = "\n$void";
$parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
}
$parsed .= $parts[0]; // Text before current tag.
// If end of $text has been reached. Stop loop.
if (count($parts) < 3) {
$text = "";
break;
}
$tag = $parts[1]; // Tag to handle.
$text = $parts[2]; // Remaining text after current tag.
$tag_re = preg_quote($tag); // For use in a regular expression.
// Check for: Fenced code block marker.
// Note: need to recheck the whole tag to disambiguate backtick
// fences from code spans
if (preg_match('{^\n?([ ]{0,' . ($indent + 3) . '})(~{3,}|`{3,})[ ]*(?:\.?[-_:a-zA-Z0-9]+)?[ ]*(?:' . $this->id_class_attr_nocatch_re . ')?[ ]*\n?$}', $tag, $capture)) {
// Fenced code block marker: find matching end marker.
$fence_indent = strlen($capture[1]); // use captured indent in re
$fence_re = $capture[2]; // use captured fence in re
if (preg_match('{^(?>.*\n)*?[ ]{' . ($fence_indent) . '}' . $fence_re . '[ ]*(?:\n|$)}', $text,
$matches))
{
// End marker found: pass text unchanged until marker.
$parsed .= $tag . $matches[0];
$text = substr($text, strlen($matches[0]));
}
else {
// No end marker: just skip it.
$parsed .= $tag;
}
}
// Check for: Indented code block.
else if ($tag{0} == "\n" || $tag{0} == " ") {
// Indented code block: pass it unchanged, will be handled
// later.
$parsed .= $tag;
}
// Check for: Code span marker
// Note: need to check this after backtick fenced code blocks
else if ($tag{0} == "`") {
// Find corresponding end marker.
$tag_re = preg_quote($tag);
if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)' . $tag_re . '(?!`)}',
$text, $matches))
{
// End marker found: pass text unchanged until marker.
$parsed .= $tag . $matches[0];
$text = substr($text, strlen($matches[0]));
}
else {
// Unmatched marker: just skip it.
$parsed .= $tag;
}
}
// Check for: Opening Block level tag or
// Opening Context Block tag (like ins and del)
// used as a block tag (tag is alone on it's line).
else if (preg_match('{^<(?:' . $this->block_tags_re . ')\b}', $tag) ||
( preg_match('{^<(?:' . $this->context_block_tags_re . ')\b}', $tag) &&
preg_match($newline_before_re, $parsed) &&
preg_match($newline_after_re, $text) )
)
{
// Need to parse tag and following text using the HTML parser.
list($block_text, $text) =
$this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
// Make sure it stays outside of any paragraph by adding newlines.
$parsed .= "\n\n$block_text\n\n";
}
// Check for: Clean tag (like script, math)
// HTML Comments, processing instructions.
else if (preg_match('{^<(?:' . $this->clean_tags_re . ')\b}', $tag) ||
$tag{1} == '!' || $tag{1} == '?')
{
// Need to parse tag and following text using the HTML parser.
// (don't check for markdown attribute)
list($block_text, $text) =
$this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
$parsed .= $block_text;
}
// Check for: Tag with same name as enclosing tag.
else if ($enclosing_tag_re !== '' &&
// Same name as enclosing tag.
preg_match('{^</?(?:' . $enclosing_tag_re . ')\b}', $tag))
{
// Increase/decrease nested tag count.
if ($tag{1} == '/') $depth--;
else if ($tag{strlen($tag)-2} != '/') $depth++;
if ($depth < 0) {
// Going out of parent element. Clean up and break so we
// return to the calling function.
$text = $tag . $text;
break;
}
$parsed .= $tag;
}
else {
$parsed .= $tag;
}
} while ($depth >= 0);
return array($parsed, $text);
}
/**
* Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
*
* * Calls $hash_method to convert any blocks.
* * Stops when the first opening tag closes.
* * $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
* (it is not inside clean tags)
*
* Returns an array of that form: ( processed text , remaining text )
* @param string $text
* @param string $hash_method
* @param string $md_attr
* @return array
*/
protected function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
if ($text === '') return array('', '');
// Regex to match `markdown` attribute inside of a tag.
$markdown_attr_re = '
{
\s* # Eat whitespace before the `markdown` attribute
markdown
\s*=\s*
(?>
(["\']) # $1: quote delimiter
(.*?) # $2: attribute value
\1 # matching delimiter
|
([^\s>]*) # $3: unquoted attribute value
)
() # $4: make $3 always defined (avoid warnings)
}xs';
// Regex to match any tag.
$tag_re = '{
( # $2: Capture whole tag.
</? # Any opening or closing tag.
[\w:$]+ # Tag name.
(?:
(?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name.
(?>
".*?" | # Double quotes (can contain `>`)
\'.*?\' | # Single quotes (can contain `>`)
.+? # Anything but quotes and `>`.
)*?
)?
> # End of tag.
|
<!-- .*? --> # HTML Comment
|
<\?.*?\?> | <%.*?%> # Processing instruction
|
<!\[CDATA\[.*?\]\]> # CData Block
)
}xs';
$original_text = $text; // Save original text in case of faliure.
$depth = 0; // Current depth inside the tag tree.
$block_text = ""; // Temporary text holder for current text.
$parsed = ""; // Parsed text that will be returned.
// Get the name of the starting tag.
// (This pattern makes $base_tag_name_re safe without quoting.)
if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
$base_tag_name_re = $matches[1];
// Loop through every tag until we find the corresponding closing tag.
do {
// Split the text using the first $tag_match pattern found.
// Text before pattern will be first in the array, text after
// pattern will be at the end, and between will be any catches made
// by the pattern.
$parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
if (count($parts) < 3) {
// End of $text reached with unbalenced tag(s).
// In that case, we return original text unchanged and pass the
// first character as filtered to prevent an infinite loop in the
// parent function.
return array($original_text{0}, substr($original_text, 1));
}
$block_text .= $parts[0]; // Text before current tag.
$tag = $parts[1]; // Tag to handle.
$text = $parts[2]; // Remaining text after current tag.
// Check for: Auto-close tag (like <hr/>)
// Comments and Processing Instructions.
if (preg_match('{^</?(?:' . $this->auto_close_tags_re . ')\b}', $tag) ||
$tag{1} == '!' || $tag{1} == '?')
{
// Just add the tag to the block as if it was text.
$block_text .= $tag;
}
else {
// Increase/decrease nested tag count. Only do so if
// the tag's name match base tag's.
if (preg_match('{^</?' . $base_tag_name_re . '\b}', $tag)) {
if ($tag{1} == '/') $depth--;
else if ($tag{strlen($tag)-2} != '/') $depth++;
}
// Check for `markdown="1"` attribute and handle it.
if ($md_attr &&
preg_match($markdown_attr_re, $tag, $attr_m) &&
preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
{
// Remove `markdown` attribute from opening tag.
$tag = preg_replace($markdown_attr_re, '', $tag);
// Check if text inside this tag must be parsed in span mode.
$this->mode = $attr_m[2] . $attr_m[3];
$span_mode = $this->mode == 'span' || $this->mode != 'block' &&
preg_match('{^<(?:' . $this->contain_span_tags_re . ')\b}', $tag);
// Calculate indent before tag.
if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
$strlen = $this->utf8_strlen;
$indent = $strlen($matches[1], 'UTF-8');
} else {
$indent = 0;
}
// End preceding block with this tag.
$block_text .= $tag;
$parsed .= $this->$hash_method($block_text);
// Get enclosing tag name for the ParseMarkdown function.
// (This pattern makes $tag_name_re safe without quoting.)
preg_match('/^<([\w:$]*)\b/', $tag, $matches);
$tag_name_re = $matches[1];
// Parse the content using the HTML-in-Markdown parser.
list ($block_text, $text)
= $this->_hashHTMLBlocks_inMarkdown($text, $indent,
$tag_name_re, $span_mode);
// Outdent markdown text.
if ($indent > 0) {
$block_text = preg_replace("/^[ ]{1,$indent}/m", "",
$block_text);
}
// Append tag content to parsed text.
if (!$span_mode) $parsed .= "\n\n$block_text\n\n";
else $parsed .= "$block_text";
// Start over with a new block.
$block_text = "";
}
else $block_text .= $tag;
}
} while ($depth > 0);
// Hash last block text that wasn't processed inside the loop.
$parsed .= $this->$hash_method($block_text);
return array($parsed, $text);
}
/**
* Called whenever a tag must be hashed when a function inserts a "clean" tag
* in $text, it passes through this function and is automaticaly escaped,
* blocking invalid nested overlap.
* @param string $text
* @return string
*/
protected function hashClean($text) {
return $this->hashPart($text, 'C');
}
/**
* Turn Markdown link shortcuts into XHTML <a> tags.
* @param string $text
* @return string
*/
protected function doAnchors($text) {
if ($this->in_anchor) {
return $text;
}
$this->in_anchor = true;
// First, handle reference-style links: [link text] [id]
$text = preg_replace_callback('{
( # wrap whole match in $1
\[
(' . $this->nested_brackets_re . ') # link text = $2
\]
[ ]? # one optional space
(?:\n[ ]*)? # one optional newline followed by spaces
\[
(.*?) # id = $3
\]
)
}xs',
array($this, '_doAnchors_reference_callback'), $text);
// Next, inline-style links: [link text](url "optional title")
$text = preg_replace_callback('{
( # wrap whole match in $1
\[
(' . $this->nested_brackets_re . ') # link text = $2
\]
\( # literal paren
[ \n]*
(?:
<(.+?)> # href = $3
|
(' . $this->nested_url_parenthesis_re . ') # href = $4
)
[ \n]*
( # $5
([\'"]) # quote char = $6
(.*?) # Title = $7
\6 # matching quote
[ \n]* # ignore any spaces/tabs between closing quote and )
)? # title is optional
\)
(?:[ ]? ' . $this->id_class_attr_catch_re . ' )? # $8 = id/class attributes
)
}xs',
array($this, '_doAnchors_inline_callback'), $text);
// Last, handle reference-style shortcuts: [link text]
// These must come last in case you've also got [link text][1]
// or [link text](/foo)
$text = preg_replace_callback('{
( # wrap whole match in $1
\[
([^\[\]]+) # link text = $2; can\'t contain [ or ]
\]
)
}xs',
array($this, '_doAnchors_reference_callback'), $text);
$this->in_anchor = false;
return $text;
}
/**
* Callback for reference anchors
* @param array $matches
* @return string
*/
protected function _doAnchors_reference_callback($matches) {
$whole_match = $matches[1];
$link_text = $matches[2];
$link_id =& $matches[3];
if ($link_id == "") {
// for shortcut links like [this][] or [this].
$link_id = $link_text;
}
// lower-case and turn embedded newlines into spaces
$link_id = strtolower($link_id);
$link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
if (isset($this->urls[$link_id])) {
$url = $this->urls[$link_id];
$url = $this->encodeURLAttribute($url);
$result = "<a href=\"$url\"";
if ( isset( $this->titles[$link_id] ) ) {
$title = $this->titles[$link_id];
$title = $this->encodeAttribute($title);
$result .= " title=\"$title\"";
}
if (isset($this->ref_attr[$link_id]))
$result .= $this->ref_attr[$link_id];
$link_text = $this->runSpanGamut($link_text);
$result .= ">$link_text</a>";
$result = $this->hashPart($result);
}
else {
$result = $whole_match;
}
return $result;
}
/**
* Callback for inline anchors
* @param array $matches
* @return string
*/
protected function _doAnchors_inline_callback($matches) {
$whole_match = $matches[1];
$link_text = $this->runSpanGamut($matches[2]);
$url = $matches[3] == '' ? $matches[4] : $matches[3];
$title =& $matches[7];
$attr = $this->doExtraAttributes("a", $dummy =& $matches[8]);
// if the URL was of the form <s p a c e s> it got caught by the HTML
// tag parser and hashed. Need to reverse the process before using the URL.
$unhashed = $this->unhash($url);
if ($unhashed != $url)
$url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
$url = $this->encodeURLAttribute($url);
$result = "<a href=\"$url\"";
if (isset($title)) {
$title = $this->encodeAttribute($title);
$result .= " title=\"$title\"";
}
$result .= $attr;
$link_text = $this->runSpanGamut($link_text);
$result .= ">$link_text</a>";
return $this->hashPart($result);
}
/**
* Turn Markdown image shortcuts into <img> tags.
* @param string $text
* @return string
*/
protected function doImages($text) {
// First, handle reference-style labeled images: ![alt text][id]
$text = preg_replace_callback('{
( # wrap whole match in $1
!\[
(' . $this->nested_brackets_re . ') # alt text = $2
\]
[ ]? # one optional space
(?:\n[ ]*)? # one optional newline followed by spaces
\[
(.*?) # id = $3
\]
)
}xs',
array($this, '_doImages_reference_callback'), $text);
// Next, handle inline images: ![alt text](url "optional title")
// Don't forget: encode * and _
$text = preg_replace_callback('{
( # wrap whole match in $1
!\[
(' . $this->nested_brackets_re . ') # alt text = $2
\]
\s? # One optional whitespace character
\( # literal paren
[ \n]*
(?:
<(\S*)> # src url = $3
|
(' . $this->nested_url_parenthesis_re . ') # src url = $4
)
[ \n]*
( # $5
([\'"]) # quote char = $6
(.*?) # title = $7
\6 # matching quote
[ \n]*
)? # title is optional
\)
(?:[ ]? ' . $this->id_class_attr_catch_re . ' )? # $8 = id/class attributes
)
}xs',
array($this, '_doImages_inline_callback'), $text);
return $text;
}
/**
* Callback for referenced images
* @param array $matches
* @return string
*/
protected function _doImages_reference_callback($matches) {
$whole_match = $matches[1];
$alt_text = $matches[2];
$link_id = strtolower($matches[3]);
if ($link_id == "") {
$link_id = strtolower($alt_text); // for shortcut links like ![this][].
}
$alt_text = $this->encodeAttribute($alt_text);
if (isset($this->urls[$link_id])) {
$url = $this->encodeURLAttribute($this->urls[$link_id]);
$result = "<img src=\"$url\" alt=\"$alt_text\"";
if (isset($this->titles[$link_id])) {
$title = $this->titles[$link_id];
$title = $this->encodeAttribute($title);
$result .= " title=\"$title\"";
}
if (isset($this->ref_attr[$link_id]))
$result .= $this->ref_attr[$link_id];
$result .= $this->empty_element_suffix;
$result = $this->hashPart($result);
}
else {
// If there's no such link ID, leave intact:
$result = $whole_match;
}
return $result;
}
/**
* Callback for inline images
* @param array $matches
* @return string
*/
protected function _doImages_inline_callback($matches) {
$whole_match = $matches[1];
$alt_text = $matches[2];
$url = $matches[3] == '' ? $matches[4] : $matches[3];
$title =& $matches[7];
$attr = $this->doExtraAttributes("img", $dummy =& $matches[8]);
$alt_text = $this->encodeAttribute($alt_text);
$url = $this->encodeURLAttribute($url);
$result = "<img src=\"$url\" alt=\"$alt_text\"";
if (isset($title)) {
$title = $this->encodeAttribute($title);
$result .= " title=\"$title\""; // $title already quoted
}
$result .= $attr;
$result .= $this->empty_element_suffix;
return $this->hashPart($result);
}
/**
* Process markdown headers. Redefined to add ID and class attribute support.
* @param string $text
* @return string
*/
protected function doHeaders($text) {
// Setext-style headers:
// Header 1 {#header1}
// ========
//
// Header 2 {#header2 .class1 .class2}
// --------
//
$text = preg_replace_callback(
'{
(^.+?) # $1: Header text
(?:[ ]+ ' . $this->id_class_attr_catch_re . ' )? # $3 = id/class attributes
[ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer
}mx',
array($this, '_doHeaders_callback_setext'), $text);
// atx-style headers:
// # Header 1 {#header1}
// ## Header 2 {#header2}
// ## Header 2 with closing hashes ## {#header3.class1.class2}
// ...
// ###### Header 6 {.class2}
//
$text = preg_replace_callback('{
^(\#{1,6}) # $1 = string of #\'s
[ ]*
(.+?) # $2 = Header text
[ ]*
\#* # optional closing #\'s (not counted)
(?:[ ]+ ' . $this->id_class_attr_catch_re . ' )? # $3 = id/class attributes
[ ]*
\n+
}xm',
array($this, '_doHeaders_callback_atx'), $text);
return $text;
}
/**
* Callback for setext headers
* @param array $matches
* @return string
*/
protected function _doHeaders_callback_setext($matches) {
if ($matches[3] == '-' && preg_match('{^- }', $matches[1])) {
return $matches[0];
}
$level = $matches[3]{0} == '=' ? 1 : 2;
$defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[1]) : null;
$attr = $this->doExtraAttributes("h$level", $dummy =& $matches[2], $defaultId);
$block = "<h$level$attr>" . $this->runSpanGamut($matches[1]) . "</h$level>";
return "\n" . $this->hashBlock($block) . "\n\n";
}
/**
* Callback for atx headers
* @param array $matches
* @return string
*/
protected function _doHeaders_callback_atx($matches) {
$level = strlen($matches[1]);
$defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[2]) : null;
$attr = $this->doExtraAttributes("h$level", $dummy =& $matches[3], $defaultId);
$block = "<h$level$attr>" . $this->runSpanGamut($matches[2]) . "</h$level>";
return "\n" . $this->hashBlock($block) . "\n\n";
}
/**
* Form HTML tables.
* @param string $text
* @return string
*/
protected function doTables($text) {
$less_than_tab = $this->tab_width - 1;
// Find tables with leading pipe.
//
// | Header 1 | Header 2
// | -------- | --------
// | Cell 1 | Cell 2
// | Cell 3 | Cell 4
$text = preg_replace_callback('
{
^ # Start of a line
[ ]{0,' . $less_than_tab . '} # Allowed whitespace.
[|] # Optional leading pipe (present)
(.+) \n # $1: Header row (at least one pipe)
[ ]{0,' . $less_than_tab . '} # Allowed whitespace.
[|] ([ ]*[-:]+[-| :]*) \n # $2: Header underline
( # $3: Cells
(?>
[ ]* # Allowed whitespace.
[|] .* \n # Row content.
)*
)
(?=\n|\Z) # Stop at final double newline.
}xm',
array($this, '_doTable_leadingPipe_callback'), $text);
// Find tables without leading pipe.
//
// Header 1 | Header 2
// -------- | --------
// Cell 1 | Cell 2
// Cell 3 | Cell 4
$text = preg_replace_callback('
{
^ # Start of a line
[ ]{0,' . $less_than_tab . '} # Allowed whitespace.
(\S.*[|].*) \n # $1: Header row (at least one pipe)
[ ]{0,' . $less_than_tab . '} # Allowed whitespace.
([-:]+[ ]*[|][-| :]*) \n # $2: Header underline
( # $3: Cells
(?>
.* [|] .* \n # Row content
)*
)
(?=\n|\Z) # Stop at final double newline.
}xm',
array($this, '_DoTable_callback'), $text);
return $text;
}
/**
* Callback for removing the leading pipe for each row
* @param array $matches
* @return string
*/
protected function _doTable_leadingPipe_callback($matches) {
$head = $matches[1];
$underline = $matches[2];
$content = $matches[3];
$content = preg_replace('/^ *[|]/m', '', $content);
return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
}
/**
* Make the align attribute in a table
* @param string $alignname
* @return string
*/
protected function _doTable_makeAlignAttr($alignname)
{
if (empty($this->table_align_class_tmpl)) {
return " align=\"$alignname\"";
}
$classname = str_replace('%%', $alignname, $this->table_align_class_tmpl);
return " class=\"$classname\"";
}
/**
* Calback for processing tables
* @param array $matches
* @return string
*/
protected function _doTable_callback($matches) {
$head = $matches[1];
$underline = $matches[2];
$content = $matches[3];
// Remove any tailing pipes for each line.
$head = preg_replace('/[|] *$/m', '', $head);
$underline = preg_replace('/[|] *$/m', '', $underline);
$content = preg_replace('/[|] *$/m', '', $content);
// Reading alignement from header underline.
$separators = preg_split('/ *[|] */', $underline);
foreach ($separators as $n => $s) {
if (preg_match('/^ *-+: *$/', $s))
$attr[$n] = $this->_doTable_makeAlignAttr('right');
else if (preg_match('/^ *:-+: *$/', $s))
$attr[$n] = $this->_doTable_makeAlignAttr('center');
else if (preg_match('/^ *:-+ *$/', $s))
$attr[$n] = $this->_doTable_makeAlignAttr('left');
else
$attr[$n] = '';
}
// Parsing span elements, including code spans, character escapes,
// and inline HTML tags, so that pipes inside those gets ignored.
$head = $this->parseSpan($head);
$headers = preg_split('/ *[|] */', $head);
$col_count = count($headers);
$attr = array_pad($attr, $col_count, '');
// Write column headers.
$text = "<table>\n";
$text .= "<thead>\n";
$text .= "<tr>\n";
foreach ($headers as $n => $header)
$text .= " <th$attr[$n]>" . $this->runSpanGamut(trim($header)) . "</th>\n";
$text .= "</tr>\n";
$text .= "</thead>\n";
// Split content by row.
$rows = explode("\n", trim($content, "\n"));
$text .= "<tbody>\n";
foreach ($rows as $row) {
// Parsing span elements, including code spans, character escapes,
// and inline HTML tags, so that pipes inside those gets ignored.
$row = $this->parseSpan($row);
// Split row by cell.
$row_cells = preg_split('/ *[|] */', $row, $col_count);
$row_cells = array_pad($row_cells, $col_count, '');
$text .= "<tr>\n";
foreach ($row_cells as $n => $cell)
$text .= " <td$attr[$n]>" . $this->runSpanGamut(trim($cell)) . "</td>\n";
$text .= "</tr>\n";
}
$text .= "</tbody>\n";
$text .= "</table>";
return $this->hashBlock($text) . "\n";
}
/**
* Form HTML definition lists.
* @param string $text
* @return string
*/
protected function doDefLists($text) {
$less_than_tab = $this->tab_width - 1;
// Re-usable pattern to match any entire dl list:
$whole_list_re = '(?>
( # $1 = whole list
( # $2
[ ]{0,' . $less_than_tab . '}
((?>.*\S.*\n)+) # $3 = defined term
\n?
[ ]{0,' . $less_than_tab . '}:[ ]+ # colon starting definition
)
(?s:.+?)
( # $4
\z
|
\n{2,}
(?=\S)
(?! # Negative lookahead for another term
[ ]{0,' . $less_than_tab . '}
(?: \S.*\n )+? # defined term
\n?
[ ]{0,' . $less_than_tab . '}:[ ]+ # colon starting definition
)
(?! # Negative lookahead for another definition
[ ]{0,' . $less_than_tab . '}:[ ]+ # colon starting definition
)
)
)
)'; // mx
$text = preg_replace_callback('{
(?>\A\n?|(?<=\n\n))
' . $whole_list_re . '
}mx',
array($this, '_doDefLists_callback'), $text);
return $text;
}
/**
* Callback for processing definition lists
* @param array $matches
* @return string
*/
protected function _doDefLists_callback($matches) {
// Re-usable patterns to match list item bullets and number markers:
$list = $matches[1];
// Turn double returns into triple returns, so that we can make a
// paragraph for the last item in a list, if necessary:
$result = trim($this->processDefListItems($list));
$result = "<dl>\n" . $result . "\n</dl>";
return $this->hashBlock($result) . "\n\n";
}
/**
* Process the contents of a single definition list, splitting it
* into individual term and definition list items.
* @param string $list_str
* @return string
*/
protected function processDefListItems($list_str) {
$less_than_tab = $this->tab_width - 1;
// Trim trailing blank lines:
$list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
// Process definition terms.
$list_str = preg_replace_callback('{
(?>\A\n?|\n\n+) # leading line
( # definition terms = $1
[ ]{0,' . $less_than_tab . '} # leading whitespace
(?!\:[ ]|[ ]) # negative lookahead for a definition
# mark (colon) or more whitespace.
(?> \S.* \n)+? # actual term (not whitespace).
)
(?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed
# with a definition mark.
}xm',
array($this, '_processDefListItems_callback_dt'), $list_str);
// Process actual definitions.
$list_str = preg_replace_callback('{
\n(\n+)? # leading line = $1
( # marker space = $2
[ ]{0,' . $less_than_tab . '} # whitespace before colon
\:[ ]+ # definition mark (colon)
)
((?s:.+?)) # definition text = $3
(?= \n+ # stop at next definition mark,
(?: # next term or end of text
[ ]{0,' . $less_than_tab . '} \:[ ] |
<dt> | \z
)
)
}xm',
array($this, '_processDefListItems_callback_dd'), $list_str);
return $list_str;
}
/**
* Callback for <dt> elements in definition lists
* @param array $matches
* @return string
*/
protected function _processDefListItems_callback_dt($matches) {
$terms = explode("\n", trim($matches[1]));
$text = '';
foreach ($terms as $term) {
$term = $this->runSpanGamut(trim($term));
$text .= "\n<dt>" . $term . "</dt>";
}
return $text . "\n";
}
/**
* Callback for <dd> elements in definition lists
* @param array $matches
* @return string
*/
protected function _processDefListItems_callback_dd($matches) {
$leading_line = $matches[1];
$marker_space = $matches[2];
$def = $matches[3];
if ($leading_line || preg_match('/\n{2,}/', $def)) {
// Replace marker with the appropriate whitespace indentation
$def = str_repeat(' ', strlen($marker_space)) . $def;
$def = $this->runBlockGamut($this->outdent($def . "\n\n"));
$def = "\n". $def ."\n";
}
else {
$def = rtrim($def);
$def = $this->runSpanGamut($this->outdent($def));
}
return "\n<dd>" . $def . "</dd>\n";
}
/**
* Adding the fenced code block syntax to regular Markdown:
*
* ~~~
* Code block
* ~~~
*
* @param string $text
* @return string
*/
protected function doFencedCodeBlocks($text) {
$less_than_tab = $this->tab_width;
$text = preg_replace_callback('{
(?:\n|\A)
# 1: Opening marker
(
(?:~{3,}|`{3,}) # 3 or more tildes/backticks.
)
[ ]*
(?:
\.?([-_:a-zA-Z0-9]+) # 2: standalone class name
)?
[ ]*
(?:
' . $this->id_class_attr_catch_re . ' # 3: Extra attributes
)?
[ ]* \n # Whitespace and newline following marker.
# 4: Content
(
(?>
(?!\1 [ ]* \n) # Not a closing marker.
.*\n+
)+
)
# Closing marker.
\1 [ ]* (?= \n )
}xm',
array($this, '_doFencedCodeBlocks_callback'), $text);
return $text;
}
/**
* Callback to process fenced code blocks
* @param array $matches
* @return string
*/
protected function _doFencedCodeBlocks_callback($matches) {
$classname =& $matches[2];
$attrs =& $matches[3];
$codeblock = $matches[4];
if ($this->code_block_content_func) {
$codeblock = call_user_func($this->code_block_content_func, $codeblock, $classname);
} else {
$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
}
$codeblock = preg_replace_callback('/^\n+/',
array($this, '_doFencedCodeBlocks_newlines'), $codeblock);
$classes = array();
if ($classname != "") {
if ($classname{0} == '.')
$classname = substr($classname, 1);
$classes[] = $this->code_class_prefix . $classname;
}
$attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs, null, $classes);
$pre_attr_str = $this->code_attr_on_pre ? $attr_str : '';
$code_attr_str = $this->code_attr_on_pre ? '' : $attr_str;
$codeblock = "<pre$pre_attr_str><code$code_attr_str>$codeblock</code></pre>";
return "\n\n".$this->hashBlock($codeblock)."\n\n";
}
/**
* Replace new lines in fenced code blocks
* @param array $matches
* @return string
*/
protected function _doFencedCodeBlocks_newlines($matches) {
return str_repeat("<br$this->empty_element_suffix",
strlen($matches[0]));
}
/**
* Redefining emphasis markers so that emphasis by underscore does not
* work in the middle of a word.
* @var array
*/
protected $em_relist = array(
'' => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?![\.,:;]?\s)',
'*' => '(?<![\s*])\*(?!\*)',
'_' => '(?<![\s_])_(?![a-zA-Z0-9_])',
);
protected $strong_relist = array(
'' => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?![\.,:;]?\s)',
'**' => '(?<![\s*])\*\*(?!\*)',
'__' => '(?<![\s_])__(?![a-zA-Z0-9_])',
);
protected $em_strong_relist = array(
'' => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?![\.,:;]?\s)',
'***' => '(?<![\s*])\*\*\*(?!\*)',
'___' => '(?<![\s_])___(?![a-zA-Z0-9_])',
);
/**
* Parse text into paragraphs
* @param string $text String to process in paragraphs
* @param boolean $wrap_in_p Whether paragraphs should be wrapped in <p> tags
* @return string HTML output
*/
protected function formParagraphs($text, $wrap_in_p = true) {
// Strip leading and trailing lines:
$text = preg_replace('/\A\n+|\n+\z/', '', $text);
$grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
// Wrap <p> tags and unhashify HTML blocks
foreach ($grafs as $key => $value) {
$value = trim($this->runSpanGamut($value));
// Check if this should be enclosed in a paragraph.
// Clean tag hashes & block tag hashes are left alone.
$is_p = $wrap_in_p && !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
if ($is_p) {
$value = "<p>$value</p>";
}
$grafs[$key] = $value;
}
// Join grafs in one text, then unhash HTML tags.
$text = implode("\n\n", $grafs);
// Finish by removing any tag hashes still present in $text.
$text = $this->unhash($text);
return $text;
}
/**
* Footnotes - Strips link definitions from text, stores the URLs and
* titles in hash references.
* @param string $text
* @return string
*/
protected function stripFootnotes($text) {
$less_than_tab = $this->tab_width - 1;
// Link defs are in the form: [^id]: url "optional title"
$text = preg_replace_callback('{
^[ ]{0,' . $less_than_tab . '}\[\^(.+?)\][ ]?: # note_id = $1
[ ]*
\n? # maybe *one* newline
( # text = $2 (no blank lines allowed)
(?:
.+ # actual text
|
\n # newlines but
(?!\[.+?\][ ]?:\s)# negative lookahead for footnote or link definition marker.
(?!\n+[ ]{0,3}\S)# ensure line is not blank and followed
# by non-indented content
)*
)
}xm',
array($this, '_stripFootnotes_callback'),
$text);
return $text;
}
/**
* Callback for stripping footnotes
* @param array $matches
* @return string
*/
protected function _stripFootnotes_callback($matches) {
$note_id = $this->fn_id_prefix . $matches[1];
$this->footnotes[$note_id] = $this->outdent($matches[2]);
return ''; // String that will replace the block
}
/**
* Replace footnote references in $text [^id] with a special text-token
* which will be replaced by the actual footnote marker in appendFootnotes.
* @param string $text
* @return string
*/
protected function doFootnotes($text) {
if (!$this->in_anchor) {
$text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
}
return $text;
}
/**
* Append footnote list to text
* @param string $text
* @return string
*/
protected function appendFootnotes($text) {
$text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
array($this, '_appendFootnotes_callback'), $text);
if (!empty($this->footnotes_ordered)) {
$text .= "\n\n";
$text .= "<div class=\"footnotes\">\n";
$text .= "<hr" . $this->empty_element_suffix . "\n";
$text .= "<ol>\n\n";
$attr = "";
if ($this->fn_backlink_class != "") {
$class = $this->fn_backlink_class;
$class = $this->encodeAttribute($class);
$attr .= " class=\"$class\"";
}
if ($this->fn_backlink_title != "") {
$title = $this->fn_backlink_title;
$title = $this->encodeAttribute($title);
$attr .= " title=\"$title\"";
}
$backlink_text = $this->fn_backlink_html;
$num = 0;
while (!empty($this->footnotes_ordered)) {
$footnote = reset($this->footnotes_ordered);
$note_id = key($this->footnotes_ordered);
unset($this->footnotes_ordered[$note_id]);
$ref_count = $this->footnotes_ref_count[$note_id];
unset($this->footnotes_ref_count[$note_id]);
unset($this->footnotes[$note_id]);
$footnote .= "\n"; // Need to append newline before parsing.
$footnote = $this->runBlockGamut("$footnote\n");
$footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
array($this, '_appendFootnotes_callback'), $footnote);
$attr = str_replace("%%", ++$num, $attr);
$note_id = $this->encodeAttribute($note_id);
// Prepare backlink, multiple backlinks if multiple references
$backlink = "<a href=\"#fnref:$note_id\"$attr>$backlink_text</a>";
for ($ref_num = 2; $ref_num <= $ref_count; ++$ref_num) {
$backlink .= " <a href=\"#fnref$ref_num:$note_id\"$attr>$backlink_text</a>";
}
// Add backlink to last paragraph; create new paragraph if needed.
if (preg_match('{</p>$}', $footnote)) {
$footnote = substr($footnote, 0, -4) . "&#160;$backlink</p>";
} else {
$footnote .= "\n\n<p>$backlink</p>";
}
$text .= "<li id=\"fn:$note_id\">\n";
$text .= $footnote . "\n";
$text .= "</li>\n\n";
}
$text .= "</ol>\n";
$text .= "</div>";
}
return $text;
}
/**
* Callback for appending footnotes
* @param array $matches
* @return string
*/
protected function _appendFootnotes_callback($matches) {
$node_id = $this->fn_id_prefix . $matches[1];
// Create footnote marker only if it has a corresponding footnote *and*
// the footnote hasn't been used by another marker.
if (isset($this->footnotes[$node_id])) {
$num =& $this->footnotes_numbers[$node_id];
if (!isset($num)) {
// Transfer footnote content to the ordered list and give it its
// number
$this->footnotes_ordered[$node_id] = $this->footnotes[$node_id];
$this->footnotes_ref_count[$node_id] = 1;
$num = $this->footnote_counter++;
$ref_count_mark = '';
} else {
$ref_count_mark = $this->footnotes_ref_count[$node_id] += 1;
}
$attr = "";
if ($this->fn_link_class != "") {
$class = $this->fn_link_class;
$class = $this->encodeAttribute($class);
$attr .= " class=\"$class\"";
}
if ($this->fn_link_title != "") {
$title = $this->fn_link_title;
$title = $this->encodeAttribute($title);
$attr .= " title=\"$title\"";
}
$attr = str_replace("%%", $num, $attr);
$node_id = $this->encodeAttribute($node_id);
return
"<sup id=\"fnref$ref_count_mark:$node_id\">".
"<a href=\"#fn:$node_id\"$attr>$num</a>".
"</sup>";
}
return "[^" . $matches[1] . "]";
}
/**
* Abbreviations - strips abbreviations from text, stores titles in hash
* references.
* @param string $text
* @return string
*/
protected function stripAbbreviations($text) {
$less_than_tab = $this->tab_width - 1;
// Link defs are in the form: [id]*: url "optional title"
$text = preg_replace_callback('{
^[ ]{0,' . $less_than_tab . '}\*\[(.+?)\][ ]?: # abbr_id = $1
(.*) # text = $2 (no blank lines allowed)
}xm',
array($this, '_stripAbbreviations_callback'),
$text);
return $text;
}
/**
* Callback for stripping abbreviations
* @param array $matches
* @return string
*/
protected function _stripAbbreviations_callback($matches) {
$abbr_word = $matches[1];
$abbr_desc = $matches[2];
if ($this->abbr_word_re) {
$this->abbr_word_re .= '|';
}
$this->abbr_word_re .= preg_quote($abbr_word);
$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
return ''; // String that will replace the block
}
/**
* Find defined abbreviations in text and wrap them in <abbr> elements.
* @param string $text
* @return string
*/
protected function doAbbreviations($text) {
if ($this->abbr_word_re) {
// cannot use the /x modifier because abbr_word_re may
// contain significant spaces:
$text = preg_replace_callback('{' .
'(?<![\w\x1A])' .
'(?:' . $this->abbr_word_re . ')' .
'(?![\w\x1A])' .
'}',
array($this, '_doAbbreviations_callback'), $text);
}
return $text;
}
/**
* Callback for processing abbreviations
* @param array $matches
* @return string
*/
protected function _doAbbreviations_callback($matches) {
$abbr = $matches[0];
if (isset($this->abbr_desciptions[$abbr])) {
$desc = $this->abbr_desciptions[$abbr];
if (empty($desc)) {
return $this->hashPart("<abbr>$abbr</abbr>");
} else {
$desc = $this->encodeAttribute($desc);
return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>");
}
} else {
return $matches[0];
}
}
}

View file

@ -1,9 +1,9 @@
<?php
# Use this file if you cannot use class autoloading. It will include all the
# files needed for the MarkdownInterface interface.
#
# Take a look at the PSR-0-compatible class autoloading implementation
# in the Readme.php file if you want a simple autoloader setup.
// Use this file if you cannot use class autoloading. It will include all the
// files needed for the MarkdownInterface interface.
//
// Take a look at the PSR-0-compatible class autoloading implementation
// in the Readme.php file if you want a simple autoloader setup.
require_once dirname(__FILE__) . '/MarkdownInterface.php';

View file

@ -1,34 +1,38 @@
<?php
#
# Markdown - A text-to-HTML conversion tool for web writers
#
# PHP Markdown
# Copyright (c) 2004-2014 Michel Fortin
# <http://michelf.com/projects/php-markdown/>
#
# Original Markdown
# Copyright (c) 2004-2006 John Gruber
# <http://daringfireball.net/projects/markdown/>
#
/**
* Markdown - A text-to-HTML conversion tool for web writers
*
* @package php-markdown
* @author Michel Fortin <michel.fortin@michelf.com>
* @copyright 2004-2016 Michel Fortin <https://michelf.com/projects/php-markdown/>
* @copyright (Original Markdown) 2004-2006 John Gruber <https://daringfireball.net/projects/markdown/>
*/
namespace Michelf;
#
# Markdown Parser Interface
#
/**
* Markdown Parser Interface
*/
interface MarkdownInterface {
/**
* Initialize the parser and return the result of its transform method.
* This will work fine for derived classes too.
*
* @api
*
* @param string $text
* @return string
*/
public static function defaultTransform($text);
#
# Initialize the parser and return the result of its transform method.
# This will work fine for derived classes too.
#
public static function defaultTransform($text);
#
# Main function. Performs some preprocessing on the input text
# and pass it through the document gamut.
#
public function transform($text);
/**
* Main function. Performs some preprocessing on the input text
* and pass it through the document gamut.
*
* @api
*
* @param string $text
* @return string
*/
public function transform($text);
}

View file

@ -1,13 +1,13 @@
PHP Markdown
============
PHP Markdown Lib 1.4.1 - 4 May 2013
PHP Markdown Lib 1.7.0 - 29 Oct 2016
by Michel Fortin
<http://michelf.ca/>
<https://michelf.ca/>
based on Markdown by John Gruber
<http://daringfireball.net/>
<https://daringfireball.net/>
Introduction
@ -25,10 +25,10 @@ software tool, originally written in Perl, that converts the plain text
markup to HTML. PHP Markdown is a port to PHP of the original Markdown
program by John Gruber.
* [Full documentation of the Markdown syntax](<http://daringfireball.net/projects/markdown/>)
- Daring Fireball (John Gruber)
* [Markdown Extra syntax additions](<http://michelf.ca/projects/php-markdown/extra/>)
- Michel Fortin
* [Full documentation of the Markdown syntax](<https://daringfireball.net/projects/markdown/>)
Daring Fireball (John Gruber)
* [Markdown Extra syntax additions](<https://michelf.ca/projects/php-markdown/extra/>)
Michel Fortin
Requirement
@ -83,7 +83,7 @@ configuration variables:
To learn more, see the full list of [configuration variables].
[configuration variables]: http://michelf.ca/projects/php-markdown/configuration/
[configuration variables]: https://michelf.ca/projects/php-markdown/configuration/
### Usage without an autoloader
@ -149,7 +149,7 @@ Development and Testing
-----------------------
Pull requests for fixing bugs are welcome. Proposed new features are
going meticulously reviewed -- taking into account backward compatibility,
going to be meticulously reviewed -- taking into account backward compatibility,
potential side effects, and future extensibility -- before deciding on
acceptance or rejection.
@ -174,11 +174,80 @@ PHP Markdown, please visit [michelf.ca/donate] or send Bitcoin to
Version History
---------------
Unreleased
PHP Markdown Lib 1.7.0 (29 Oct 2016)
* Added the ability to insert custom HTML attributes everywhere an extra
attribute block is allowed (links, images, headers). Credits to
Peter Droogmans for providing the implementation.
* Added a `hard_wrap` configuration variable to make all newline characters
in the text become `<br>` tags in the HTML output. By default, according
to the standard Markdown syntax these newlines are ignored unless they a
preceded by two spaces. Thanks to Jonathan Cohlmeyer for the implementation.
* Improved the parsing of list items to fix problematic cases that came to
light with the addition of `hard_wrap`. This should have no effect on the
output except span-level list items that ended with two spaces (and thus
ended with a line break).
* Added a `code_span_content_func` configuration variable which takes a
function that will convert the content of the code span to HTML. This can
be useful to implement syntax highlighting. Although contrary to its
code block equivalent, there is no syntax for specifying a language.
Credits to styxit for the implementation.
* Fixed a Markdown Extra issue where two-space-at-end-of-line hard breaks
wouldn't work inside of HTML block elements such as `<p markdown="1">`
where the element expects only span-level content.
* In the parser code, switched to PHPDoc comment format. Thanks to
Robbie Averill for the help.
PHP Markdown Lib 1.6.0 (23 Dec 2015)
Note: this version was incorrectly released as 1.5.1 on Dec 22, a number
that contradicted the versioning policy.
* For fenced code blocks in Markdown Extra, can now set a class name for the
code block's language before the special attribute block. Previously, this
class name was only allowed in the absence of the special attribute block.
* Added a `code_block_content_func` configuration variable which takes a
function that will convert the content of the code block to HTML. This is
most useful for syntax highlighting. For fenced code blocks in Markdown
Extra, the function has access to the language class name (the one outside
of the special attribute block). Credits to Mario Konrad for providing the
implementation.
* The curled arrow character for the backlink in footnotes is now followed
by a Unicode variant selector to prevent it from being displayed in emoji
form on iOS.
Note that in older browsers the variant selector is often interpreted as a
separate character, making it visible after the arrow. So there is now a
also a `fn_backlink_html` configuration variable that can be used to set
the link text to something else. Credits to Dana for providing the
implementation.
* Fixed an issue in MarkdownExtra where long header lines followed by a
special attribute block would hit the backtrack limit an cause an empty
string to be returned.
PHP Markdown Lib 1.5.0 (1 Mar 2015)
* Added the ability start ordered lists with a number different from 1 and
and have that reflected in the HTML output. This can be enabled with
the `enhanced_ordered_lists` configuration variable for the Markdown
parser; it is enabled by default for Markdown Extra.
Credits to Matt Gorle for providing the implementation.
* Added the ability to insert custom HTML attributes with simple values
everywhere an extra attribute block is allowed (links, images, headers).
The value must be unquoted, cannot contains spaces and is limited to
alphanumeric ASCII characters.
Credits to Peter Droogmans for providing the implementation.
* Added a `header_id_func` configuration variable which takes a function
that can generate an `id` attribute value from the header text.
Credits to Evert Pot for providing the implementation.
* Added a `url_filter_func` configuration variable which takes a function
that can rewrite any link or image URL to something different.
@ -239,7 +308,7 @@ PHP Markdown Extra 1.2.6:
* Plugin interface for WordPress and other systems is no longer present in
the Lib package. The classic package is still available if you need it:
<http://michelf.ca/projects/php-markdown/classic/>
<https://michelf.ca/projects/php-markdown/classic/>
* Added `public` and `protected` protection attributes, plus a section about
what is "public API" and what isn't in the Readme file.
@ -277,13 +346,13 @@ Copyright and License
---------------------
PHP Markdown Lib
Copyright (c) 2004-2014 Michel Fortin
<http://michelf.ca/>
Copyright (c) 2004-2016 Michel Fortin
<https://michelf.ca/>
All rights reserved.
Based on Markdown
Copyright (c) 2003-2005 John Gruber
<http://daringfireball.net/>
<https://daringfireball.net/>
All rights reserved.
Redistribution and use in source and binary forms, with or without

View file

@ -1,18 +1,18 @@
<?php
# This file passes the content of the Readme.md file in the same directory
# through the Markdown filter. You can adapt this sample code in any way
# you like.
// This file passes the content of the Readme.md file in the same directory
// through the Markdown filter. You can adapt this sample code in any way
// you like.
# Install PSR-0-compatible class autoloader
// Install PSR-0-compatible class autoloader
spl_autoload_register(function($class){
require preg_replace('{\\\\|_(?!.*\\\\)}', DIRECTORY_SEPARATOR, ltrim($class, '\\')).'.php';
});
# Get Markdown class
// Get Markdown class
use \Michelf\Markdown;
# Read file and pass content through the Markdown parser
// Read file and pass content through the Markdown parser
$text = file_get_contents('Readme.md');
$html = Markdown::defaultTransform($text);
@ -24,7 +24,7 @@ $html = Markdown::defaultTransform($text);
</head>
<body>
<?php
# Put HTML content in the document
// Put HTML content in the document
echo $html;
?>
</body>

View file

@ -2,19 +2,19 @@
"name": "michelf/php-markdown",
"type": "library",
"description": "PHP Markdown",
"homepage": "http://michelf.ca/projects/php-markdown/",
"homepage": "https://michelf.ca/projects/php-markdown/",
"keywords": ["markdown"],
"license": "BSD-3-Clause",
"authors": [
{
"name": "Michel Fortin",
"email": "michel.fortin@michelf.ca",
"homepage": "http://michelf.ca/",
"homepage": "https://michelf.ca/",
"role": "Developer"
},
{
"name": "John Gruber",
"homepage": "http://daringfireball.net/"
"homepage": "https://daringfireball.net/"
}
],
"require": {
@ -22,10 +22,5 @@
},
"autoload": {
"psr-0": { "Michelf": "" }
},
"extra": {
"branch-alias": {
"dev-lib": "1.4.x-dev"
}
}
}

View file

@ -27,7 +27,7 @@ require_once("include/text.php");
function admin_post(App $a) {
if(!is_site_admin()) {
if (!is_site_admin()) {
return;
}
@ -39,7 +39,7 @@ function admin_post(App $a) {
// urls
if ($a->argc > 1) {
switch ($a->argv[1]){
switch ($a->argv[1]) {
case 'site':
admin_page_site_post($a);
break;
@ -47,10 +47,10 @@ function admin_post(App $a) {
admin_page_users_post($a);
break;
case 'plugins':
if($a->argc > 2 &&
if ($a->argc > 2 &&
is_file("addon/".$a->argv[2]."/".$a->argv[2].".php")) {
@include_once("addon/".$a->argv[2]."/".$a->argv[2].".php");
if(function_exists($a->argv[2].'_plugin_admin_post')) {
if (function_exists($a->argv[2].'_plugin_admin_post')) {
$func = $a->argv[2].'_plugin_admin_post';
$func($a);
}
@ -59,14 +59,16 @@ function admin_post(App $a) {
return; // NOTREACHED
break;
case 'themes':
if($a->argc < 2) {
if(is_ajax()) return;
if ($a->argc < 2) {
if (is_ajax()) {
return;
}
goaway('admin/');
return;
}
$theme = $a->argv[2];
if(is_file("view/theme/$theme/config.php")){
if (is_file("view/theme/$theme/config.php")) {
function __call_theme_admin_post(App $a, $theme) {
$orig_theme = $a->theme;
$orig_page = $a->page;
@ -77,8 +79,10 @@ function admin_post(App $a) {
$init = $theme."_init";
if(function_exists($init)) $init($a);
if(function_exists("theme_admin_post")) {
if (function_exists($init)) {
$init($a);
}
if (function_exists("theme_admin_post")) {
$admin_form = theme_admin_post($a);
}
@ -90,8 +94,9 @@ function admin_post(App $a) {
__call_theme_admin_post($a, $theme);
}
info(t('Theme settings updated.'));
if(is_ajax()) return;
if (is_ajax()) {
return;
}
goaway('admin/themes/'.$theme);
return;
break;
@ -130,7 +135,7 @@ function admin_post(App $a) {
*/
function admin_content(App $a) {
if(!is_site_admin()) {
if (!is_site_admin()) {
return login(false);
}
@ -168,7 +173,7 @@ function admin_content(App $a) {
$r = q("SELECT `name` FROM `addon` WHERE `plugin_admin` = 1 ORDER BY `name`");
$aside_tools['plugins_admin']=array();
foreach ($r as $h){
foreach ($r as $h) {
$plugin =$h['name'];
$aside_tools['plugins_admin'][] = array("admin/plugins/".$plugin, $plugin, "plugin");
// temp plugins with admin
@ -199,8 +204,8 @@ function admin_content(App $a) {
*/
$o = '';
// urls
if($a->argc > 1) {
switch ($a->argv[1]){
if ($a->argc > 1) {
switch ($a->argv[1]) {
case 'site':
$o = admin_page_site($a);
break;
@ -238,7 +243,7 @@ function admin_content(App $a) {
$o = admin_page_summary($a);
}
if(is_ajax()) {
if (is_ajax()) {
echo $o;
killme();
return '';
@ -270,8 +275,8 @@ function admin_page_federation(App $a) {
// off one % two of them are needed in the query
// Add more platforms if you like, when one returns 0 known nodes it is not
// displayed on the stats page.
$platforms = array('Friendica', 'Diaspora', '%%red%%', 'Hubzilla', 'BlaBlaNet', 'GNU Social', 'StatusNet', 'Mastodon');
$colors = array('Friendica' => '#ffc018', // orange from the logo
$platforms = array('Friendi%%a', 'Diaspora', '%%red%%', 'Hubzilla', 'BlaBlaNet', 'GNU Social', 'StatusNet', 'Mastodon');
$colors = array('Friendi%%a' => '#ffc018', // orange from the logo
'Diaspora' => '#a1a1a1', // logo is black and white, makes a gray
'%%red%%' => '#c50001', // fire red from the logo
'Hubzilla' => '#43488a', // blue from the logo
@ -310,19 +315,21 @@ function admin_page_federation(App $a) {
// in the DB the Diaspora versions have the format x.x.x.x-xx the last
// part (-xx) should be removed to clean up the versions from the "head
// commit" information and combined into a single entry for x.x.x.x
if($p=='Diaspora') {
if ($p == 'Diaspora') {
$newV = array();
$newVv = array();
foreach($v as $vv) {
foreach ($v as $vv) {
$newVC = $vv['total'];
$newVV = $vv['version'];
$posDash = strpos($newVV, '-');
if($posDash)
if ($posDash) {
$newVV = substr($newVV, 0, $posDash);
if(isset($newV[$newVV]))
}
if (isset($newV[$newVV])) {
$newV[$newVV] += $newVC;
else
} else {
$newV[$newVV] = $newVC;
}
}
foreach ($newV as $key => $value) {
array_push($newVv, array('total'=>$value, 'version'=>$key));
@ -333,7 +340,7 @@ function admin_page_federation(App $a) {
// early friendica versions have the format x.x.xxxx where xxxx is the
// DB version stamp; those should be operated out and versions be
// conbined
if($p=='Friendica') {
if ($p == 'Friendi%%a') {
$newV = array();
$newVv = array();
foreach ($v as $vv) {
@ -341,12 +348,14 @@ function admin_page_federation(App $a) {
$newVV = $vv['version'];
$lastDot = strrpos($newVV,'.');
$len = strlen($newVV)-1;
if(($lastDot == $len-4) && (!strrpos($newVV,'-rc')==$len-3))
if (($lastDot == $len-4) && (!strrpos($newVV,'-rc') == $len-3)) {
$newVV = substr($newVV, 0, $lastDot);
if(isset($newV[$newVV]))
}
if (isset($newV[$newVV])) {
$newV[$newVV] += $newVC;
else
} else {
$newV[$newVV] = $newVC;
}
}
foreach ($newV as $key => $value) {
array_push($newVv, array('total'=>$value, 'version'=>$key));
@ -455,7 +464,10 @@ function admin_page_summary(App $a) {
);
$users=0;
foreach ($r as $u){ $accounts[$u['page-flags']][1] = $u['count']; $users+= $u['count']; }
foreach ($r as $u) {
$accounts[$u['page-flags']][1] = $u['count'];
$users+= $u['count'];
}
logger('accounts: '.print_r($accounts,true),LOGGER_DATA);
@ -468,12 +480,8 @@ function admin_page_summary(App $a) {
$r = qu("SELECT COUNT(*) AS `total` FROM `queue` WHERE 1");
$queue = (($r) ? $r[0]['total'] : 0);
if (get_config('system','worker')) {
$r = qu("SELECT COUNT(*) AS `total` FROM `workerqueue` WHERE 1");
$workerqueue = (($r) ? $r[0]['total'] : 0);
} else {
$workerqueue = 0;
}
$r = qu("SELECT COUNT(*) AS `total` FROM `workerqueue` WHERE 1");
$workerqueue = (($r) ? $r[0]['total'] : 0);
// We can do better, but this is a quick queue status
@ -485,7 +493,6 @@ function admin_page_summary(App $a) {
'$title' => t('Administration'),
'$page' => t('Summary'),
'$queues' => $queues,
'$workeractive' => get_config('system','worker'),
'$users' => array(t('Registered users'), $users),
'$accounts' => $accounts,
'$pending' => array(t('Pending registrations'), $pending),
@ -506,19 +513,19 @@ function admin_page_summary(App $a) {
* @param App $a
*/
function admin_page_site_post(App $a) {
if(!x($_POST,"page_site")) {
if (!x($_POST,"page_site")) {
return;
}
check_form_security_token_redirectOnErr('/admin/site', 'admin_site');
// relocate
if(x($_POST,'relocate') && x($_POST,'relocate_url') && $_POST['relocate_url']!="") {
if (x($_POST,'relocate') && x($_POST,'relocate_url') && $_POST['relocate_url'] != "") {
$new_url = $_POST['relocate_url'];
$new_url = rtrim($new_url,"/");
$parsed = @parse_url($new_url);
if(!$parsed || (!x($parsed,'host') || !x($parsed,'scheme'))) {
if (!$parsed || (!x($parsed,'host') || !x($parsed,'scheme'))) {
notice(t("Can not parse base url. Must have at least <scheme>://<domain>"));
goaway('admin/site');
}
@ -551,7 +558,7 @@ function admin_page_site_post(App $a) {
$q = sprintf("UPDATE %s SET %s;", $table_name, $upds);
$r = q($q);
if(!$r) {
if (!$r) {
notice("Failed updating '$table_name': ".$db->error);
goaway('admin/site');
}
@ -622,7 +629,6 @@ function admin_page_site_post(App $a) {
$no_multi_reg = ((x($_POST,'no_multi_reg')) ? True : False);
$no_openid = !((x($_POST,'no_openid')) ? True : False);
$no_regfullname = !((x($_POST,'no_regfullname')) ? True : False);
$no_utf = !((x($_POST,'no_utf')) ? True : False);
$community_page_style = ((x($_POST,'community_page_style')) ? intval(trim($_POST['community_page_style'])) : 0);
$max_author_posts_community_page = ((x($_POST,'max_author_posts_community_page')) ? intval(trim($_POST['max_author_posts_community_page'])) : 0);
@ -630,8 +636,6 @@ function admin_page_site_post(App $a) {
$proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['proxyuser'])) : '');
$proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['proxy'])) : '');
$timeout = ((x($_POST,'timeout')) ? intval(trim($_POST['timeout'])) : 60);
$delivery_interval = ((x($_POST,'delivery_interval')) ? intval(trim($_POST['delivery_interval'])) : 0);
$poll_interval = ((x($_POST,'poll_interval')) ? intval(trim($_POST['poll_interval'])) : 0);
$maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50);
$maxloadavg_frontend = ((x($_POST,'maxloadavg_frontend')) ? intval(trim($_POST['maxloadavg_frontend'])) : 50);
$optimize_max_tablesize = ((x($_POST,'optimize_max_tablesize')) ? intval(trim($_POST['optimize_max_tablesize'])): 100);
@ -655,28 +659,25 @@ function admin_page_site_post(App $a) {
$itemcache = ((x($_POST,'itemcache')) ? notags(trim($_POST['itemcache'])) : '');
$itemcache_duration = ((x($_POST,'itemcache_duration')) ? intval($_POST['itemcache_duration']) : 0);
$max_comments = ((x($_POST,'max_comments')) ? intval($_POST['max_comments']) : 0);
$lockpath = ((x($_POST,'lockpath')) ? notags(trim($_POST['lockpath'])) : '');
$temppath = ((x($_POST,'temppath')) ? notags(trim($_POST['temppath'])) : '');
$basepath = ((x($_POST,'basepath')) ? notags(trim($_POST['basepath'])) : '');
$singleuser = ((x($_POST,'singleuser')) ? notags(trim($_POST['singleuser'])) : '');
$proxy_disabled = ((x($_POST,'proxy_disabled')) ? True : False);
$only_tag_search = ((x($_POST,'only_tag_search')) ? True : False);
$rino = ((x($_POST,'rino')) ? intval($_POST['rino']) : 0);
$embedly = ((x($_POST,'embedly')) ? notags(trim($_POST['embedly'])) : '');
$worker = ((x($_POST,'worker')) ? True : False);
$worker_queues = ((x($_POST,'worker_queues')) ? intval($_POST['worker_queues']) : 4);
$worker_dont_fork = ((x($_POST,'worker_dont_fork')) ? True : False);
$worker_fastlane = ((x($_POST,'worker_fastlane')) ? True : False);
$worker_frontend = ((x($_POST,'worker_frontend')) ? True : False);
if($a->get_path() != "")
if ($a->get_path() != "") {
$diaspora_enabled = false;
if(!$thread_allow)
}
if (!$thread_allow) {
$ostatus_disabled = true;
if($ssl_policy != intval(get_config('system','ssl_policy'))) {
if($ssl_policy == SSL_POLICY_FULL) {
}
if ($ssl_policy != intval(get_config('system','ssl_policy'))) {
if ($ssl_policy == SSL_POLICY_FULL) {
q("UPDATE `contact` SET
`url` = REPLACE(`url` , 'http:' , 'https:'),
`photo` = REPLACE(`photo` , 'http:' , 'https:'),
@ -694,8 +695,7 @@ function admin_page_site_post(App $a) {
`thumb` = REPLACE(`thumb` , 'http:' , 'https:')
WHERE 1 "
);
}
elseif($ssl_policy == SSL_POLICY_SELFSIGN) {
} elseif ($ssl_policy == SSL_POLICY_SELFSIGN) {
q("UPDATE `contact` SET
`url` = REPLACE(`url` , 'https:' , 'http:'),
`photo` = REPLACE(`photo` , 'https:' , 'http:'),
@ -716,8 +716,6 @@ function admin_page_site_post(App $a) {
}
}
set_config('system','ssl_policy',$ssl_policy);
set_config('system','delivery_interval',$delivery_interval);
set_config('system','poll_interval',$poll_interval);
set_config('system','maxloadavg',$maxloadavg);
set_config('system','maxloadavg_frontend',$maxloadavg_frontend);
set_config('system','optimize_max_tablesize',$optimize_max_tablesize);
@ -735,7 +733,7 @@ function admin_page_site_post(App $a) {
set_config('system','shortcut_icon',$shortcut_icon);
set_config('system','touch_icon',$touch_icon);
if($banner=="") {
if ($banner == "") {
// don't know why, but del_config doesn't work...
q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
dbesc("system"),
@ -745,7 +743,7 @@ function admin_page_site_post(App $a) {
set_config('system','banner', $banner);
}
if($info=="") {
if ($info == "") {
del_config('config','info');
} else {
set_config('config','info',$info);
@ -753,12 +751,12 @@ function admin_page_site_post(App $a) {
set_config('system','language', $language);
set_config('system','theme', $theme);
if($theme_mobile === '---') {
if ($theme_mobile === '---') {
del_config('system','mobile-theme');
} else {
set_config('system','mobile-theme', $theme_mobile);
}
if($singleuser === '---') {
if ($singleuser === '---') {
del_config('system','singleuser');
} else {
set_config('system','singleuser', $singleuser);
@ -787,7 +785,6 @@ function admin_page_site_post(App $a) {
set_config('system','no_regfullname', $no_regfullname);
set_config('system','community_page_style', $community_page_style);
set_config('system','max_author_posts_community_page', $max_author_posts_community_page);
set_config('system','no_utf', $no_utf);
set_config('system','verifyssl', $verifyssl);
set_config('system','proxyuser', $proxyuser);
set_config('system','proxy', $proxy);
@ -806,26 +803,21 @@ function admin_page_site_post(App $a) {
set_config('system','itemcache', $itemcache);
set_config('system','itemcache_duration', $itemcache_duration);
set_config('system','max_comments', $max_comments);
set_config('system','lockpath', $lockpath);
set_config('system','temppath', $temppath);
set_config('system','basepath', $basepath);
set_config('system','proxy_disabled', $proxy_disabled);
set_config('system','only_tag_search', $only_tag_search);
set_config('system','worker', $worker);
set_config('system','worker_queues', $worker_queues);
set_config('system','worker_dont_fork', $worker_dont_fork);
set_config('system','worker_fastlane', $worker_fastlane);
set_config('system','frontend_worker', $worker_frontend);
if($rino==2 and !function_exists('mcrypt_create_iv')) {
if (($rino == 2) and !function_exists('mcrypt_create_iv')) {
notice(t("RINO2 needs mcrypt php extension to work."));
} else {
set_config('system','rino_encrypt', $rino);
}
set_config('system','embedly', $embedly);
info(t('Site settings updated.').EOL);
goaway('admin/site');
return; // NOTREACHED
@ -845,7 +837,7 @@ function admin_page_site(App $a) {
/* Installed langs */
$lang_choices = get_available_languages();
if(strlen(get_config('system','directory_submit_url')) AND
if (strlen(get_config('system','directory_submit_url')) AND
!strlen(get_config('system','directory'))) {
set_config('system','directory', dirname(get_config('system','directory_submit_url')));
del_config('system','directory_submit_url');
@ -856,12 +848,12 @@ function admin_page_site(App $a) {
$theme_choices_mobile = array();
$theme_choices_mobile["---"] = t("No special theme for mobile devices");
$files = glob('view/theme/*');
if($files) {
if ($files) {
$allowed_theme_list = Config::get('system', 'allowed_themes');
foreach($files as $file) {
if(intval(file_exists($file.'/unsupported')))
foreach ($files as $file) {
if (intval(file_exists($file.'/unsupported')))
continue;
$f = basename($file);
@ -873,7 +865,7 @@ function admin_page_site(App $a) {
$theme_name = ((file_exists($file.'/experimental')) ? sprintf("%s - \x28Experimental\x29", $f) : $f);
if(file_exists($file.'/mobile')) {
if (file_exists($file.'/mobile')) {
$theme_choices_mobile[$f] = $theme_name;
} else {
$theme_choices[$f] = $theme_name;
@ -922,15 +914,15 @@ function admin_page_site(App $a) {
/* Banner */
$banner = get_config('system','banner');
if($banner == false)
if ($banner == false) {
$banner = '<a href="http://friendica.com"><img id="logo-img" src="images/friendica-32.png" alt="logo" /></a><span id="logo-text"><a href="http://friendica.com">Friendica</a></span>';
}
$banner = htmlspecialchars($banner);
$info = get_config('config','info');
$info = htmlspecialchars($info);
// Automatically create temporary paths
get_temppath();
get_lockpath();
get_itemcachepath();
//echo "<pre>"; var_dump($lang_choices); die("</pre>");
@ -948,9 +940,9 @@ function admin_page_site(App $a) {
SSL_POLICY_SELFSIGN => t("Self-signed certificate, use SSL for local links only (discouraged)")
);
if($a->config['hostname'] == "")
if ($a->config['hostname'] == "") {
$a->config['hostname'] = $a->get_hostname();
}
$diaspora_able = ($a->get_path() == "");
$optimize_max_tablesize = Config::get('system','optimize_max_tablesize', 100);
@ -1014,7 +1006,6 @@ function admin_page_site(App $a) {
'$no_multi_reg' => array('no_multi_reg', t("Block multiple registrations"), get_config('system','block_extended_register'), t("Disallow users to register additional accounts for use as pages.")),
'$no_openid' => array('no_openid', t("OpenID support"), !get_config('system','no_openid'), t("OpenID support for registration and logins.")),
'$no_regfullname' => array('no_regfullname', t("Fullname check"), !get_config('system','no_regfullname'), t("Force users to register with a space between firstname and lastname in Full name, as an antispam measure")),
'$no_utf' => array('no_utf', t("UTF-8 Regular expressions"), !get_config('system','no_utf'), t("Use PHP UTF8 regular expressions")),
'$community_page_style' => array('community_page_style', t("Community Page Style"), get_config('system','community_page_style'), t("Type of community page to show. 'Global community' shows every public posting from an open distributed network that arrived on this server."), $community_page_style_choices),
'$max_author_posts_community_page' => array('max_author_posts_community_page', t("Posts per user on community page"), get_config('system','max_author_posts_community_page'), t("The maximum number of posts per user on the community page. (Not valid for 'Global Community')")),
'$ostatus_disabled' => array('ostatus_disabled', t("Enable OStatus support"), !get_config('system','ostatus_disabled'), t("Provide built-in OStatus \x28StatusNet, GNU Social etc.\x29 compatibility. All communications in OStatus are public, so privacy warnings will be occasionally displayed.")),
@ -1029,8 +1020,6 @@ function admin_page_site(App $a) {
'$proxyuser' => array('proxyuser', t("Proxy user"), get_config('system','proxyuser'), ""),
'$proxy' => array('proxy', t("Proxy URL"), get_config('system','proxy'), ""),
'$timeout' => array('timeout', t("Network timeout"), (x(get_config('system','curl_timeout'))?get_config('system','curl_timeout'):60), t("Value is in seconds. Set to 0 for unlimited (not recommended).")),
'$delivery_interval' => array('delivery_interval', t("Delivery interval"), (x(get_config('system','delivery_interval'))?get_config('system','delivery_interval'):2), t("Delay background delivery processes by this many seconds to reduce system load. Recommend: 4-5 for shared hosts, 2-3 for virtual private servers. 0-1 for large dedicated servers.")),
'$poll_interval' => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")),
'$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
'$maxloadavg_frontend' => array('maxloadavg_frontend', t("Maximum Load Average (Frontend)"), ((intval(get_config('system','maxloadavg_frontend')) > 0)?get_config('system','maxloadavg_frontend'):50), t("Maximum system load before the frontend quits service - default 50.")),
'$optimize_max_tablesize'=> array('optimize_max_tablesize', t("Maximum table size for optimization"), $optimize_max_tablesize, t("Maximum table size (in MB) for the automatic optimization - default 100 MB. Enter -1 to disable it.")),
@ -1049,7 +1038,6 @@ function admin_page_site(App $a) {
'$itemcache' => array('itemcache', t("Path to item cache"), get_config('system','itemcache'), t("The item caches buffers generated bbcode and external images.")),
'$itemcache_duration' => array('itemcache_duration', t("Cache duration in seconds"), get_config('system','itemcache_duration'), t("How long should the cache files be hold? Default value is 86400 seconds (One day). To disable the item cache, set the value to -1.")),
'$max_comments' => array('max_comments', t("Maximum numbers of comments per post"), get_config('system','max_comments'), t("How much comments should be shown for each post? Default value is 100.")),
'$lockpath' => array('lockpath', t("Path for lock file"), get_config('system','lockpath'), t("The lock file is used to avoid multiple pollers at one time. Only define a folder here.")),
'$temppath' => array('temppath', t("Temp path"), get_config('system','temppath'), t("If you have a restricted system where the webserver can't access the system temp path, enter another path here.")),
'$basepath' => array('basepath', t("Base path to installation"), get_config('system','basepath'), t("If the system cannot detect the correct path to your installation, enter the correct path here. This setting should only be set if you are using a restricted system and symbolic links to your webroot.")),
'$proxy_disabled' => array('proxy_disabled', t("Disable picture proxy"), get_config('system','proxy_disabled'), t("The picture proxy increases performance and privacy. It shouldn't be used on systems with very low bandwith.")),
@ -1058,9 +1046,7 @@ function admin_page_site(App $a) {
'$relocate_url' => array('relocate_url', t("New base url"), App::get_baseurl(), t("Change base url for this server. Sends relocate message to all DFRN contacts of all users.")),
'$rino' => array('rino', t("RINO Encryption"), intval(get_config('system','rino_encrypt')), t("Encryption layer between nodes."), array("Disabled", "RINO1 (deprecated)", "RINO2")),
'$embedly' => array('embedly', t("Embedly API key"), get_config('system','embedly'), t("<a href='http://embed.ly'>Embedly</a> is used to fetch additional data for web pages. This is an optional parameter.")),
'$worker' => array('worker', t("Enable 'worker' background processing"), get_config('system','worker'), t("The worker background processing limits the number of parallel background jobs to a maximum number and respects the system load.")),
'$worker_queues' => array('worker_queues', t("Maximum number of parallel workers"), get_config('system','worker_queues'), t("On shared hosters set this to 2. On larger systems, values of 10 are great. Default value is 4.")),
'$worker_dont_fork' => array('worker_dont_fork', t("Don't use 'proc_open' with the worker"), get_config('system','worker_dont_fork'), t("Enable this if your system doesn't allow the use of 'proc_open'. This can happen on shared hosters. If this is enabled you should increase the frequency of poller calls in your crontab.")),
'$worker_fastlane' => array('worker_fastlane', t("Enable fastlane"), get_config('system','worker_fastlane'), t("When enabed, the fastlane mechanism starts an additional worker if processes with higher priority are blocked by processes of lower priority.")),
@ -1088,42 +1074,45 @@ function admin_page_dbsync(App $a) {
$o = '';
if($a->argc > 3 && intval($a->argv[3]) && $a->argv[2] === 'mark') {
if ($a->argc > 3 && intval($a->argv[3]) && $a->argv[2] === 'mark') {
set_config('database', 'update_'.intval($a->argv[3]), 'success');
$curr = get_config('system','build');
if(intval($curr) == intval($a->argv[3]))
if (intval($curr) == intval($a->argv[3])) {
set_config('system','build',intval($curr) + 1);
}
info(t('Update has been marked successful').EOL);
goaway('admin/dbsync');
}
if(($a->argc > 2) AND (intval($a->argv[2]) OR ($a->argv[2] === 'check'))) {
if (($a->argc > 2) AND (intval($a->argv[2]) OR ($a->argv[2] === 'check'))) {
require_once("include/dbstructure.php");
$retval = update_structure(false, true);
if(!$retval) {
if (!$retval) {
$o .= sprintf(t("Database structure update %s was successfully applied."), DB_UPDATE_VERSION)."<br />";
set_config('database', 'dbupdate_'.DB_UPDATE_VERSION, 'success');
} else
} else {
$o .= sprintf(t("Executing of database structure update %s failed with error: %s"),
DB_UPDATE_VERSION, $retval)."<br />";
if($a->argv[2] === 'check')
}
if ($a->argv[2] === 'check') {
return $o;
}
}
if($a->argc > 2 && intval($a->argv[2])) {
if ($a->argc > 2 && intval($a->argv[2])) {
require_once('update.php');
$func = 'update_'.intval($a->argv[2]);
if(function_exists($func)) {
if (function_exists($func)) {
$retval = $func();
if($retval === UPDATE_FAILED) {
if ($retval === UPDATE_FAILED) {
$o .= sprintf(t("Executing %s failed with error: %s"), $func, $retval);
}
elseif($retval === UPDATE_SUCCESS) {
elseif ($retval === UPDATE_SUCCESS) {
$o .= sprintf(t('Update %s was successfully applied.', $func));
set_config('database',$func, 'success');
}
else
} else {
$o .= sprintf(t('Update %s did not return a status. Unknown if it succeeded.'), $func);
}
} else {
$o .= sprintf(t('There was no additional update function %s that needed to be called.'), $func)."<br />";
set_config('database',$func, 'success');
@ -1136,8 +1125,9 @@ function admin_page_dbsync(App $a) {
if (dbm::is_result($r)) {
foreach ($r as $rr) {
$upd = intval(substr($rr['k'],7));
if($upd < 1139 || $rr['v'] === 'success')
if ($upd < 1139 || $rr['v'] === 'success') {
continue;
}
$failed[] = $upd;
}
}
@ -1177,7 +1167,7 @@ function admin_page_users_post(App $a) {
check_form_security_token_redirectOnErr('/admin/users', 'admin_users');
if (!($nu_name==="") && !($nu_email==="") && !($nu_nickname==="")) {
if (!($nu_name === "") && !($nu_email === "") && !($nu_nickname === "")) {
require_once('include/user.php');
$result = create_user(array('username'=>$nu_name, 'email'=>$nu_email,
@ -1228,31 +1218,31 @@ function admin_page_users_post(App $a) {
}
if(x($_POST,'page_users_block')) {
foreach($users as $uid){
if (x($_POST,'page_users_block')) {
foreach ($users as $uid) {
q("UPDATE `user` SET `blocked` = 1-`blocked` WHERE `uid` = %s",
intval($uid)
);
}
notice(sprintf(tt("%s user blocked/unblocked", "%s users blocked/unblocked", count($users)), count($users)));
}
if(x($_POST,'page_users_delete')) {
if (x($_POST,'page_users_delete')) {
require_once("include/Contact.php");
foreach($users as $uid){
foreach ($users as $uid) {
user_remove($uid);
}
notice(sprintf(tt("%s user deleted", "%s users deleted", count($users)), count($users)));
}
if(x($_POST,'page_users_approve')) {
if (x($_POST,'page_users_approve')) {
require_once("mod/regmod.php");
foreach($pending as $hash){
foreach ($pending as $hash) {
user_allow($hash);
}
}
if(x($_POST,'page_users_deny')) {
if (x($_POST,'page_users_deny')) {
require_once("mod/regmod.php");
foreach($pending as $hash){
foreach ($pending as $hash) {
user_deny($hash);
}
}
@ -1273,31 +1263,31 @@ function admin_page_users_post(App $a) {
* @return string
*/
function admin_page_users(App $a) {
if($a->argc>2) {
if ($a->argc>2) {
$uid = $a->argv[3];
$user = q("SELECT `username`, `blocked` FROM `user` WHERE `uid` = %d", intval($uid));
if(count($user)==0) {
if (count($user) == 0) {
notice('User not found'.EOL);
goaway('admin/users');
return ''; // NOTREACHED
}
switch($a->argv[2]){
case "delete":{
switch($a->argv[2]) {
case "delete":
check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't');
// delete user
require_once("include/Contact.php");
user_remove($uid);
notice(sprintf(t("User '%s' deleted"), $user[0]['username']).EOL);
}; break;
case "block":{
break;
case "block":
check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't');
q("UPDATE `user` SET `blocked` = %d WHERE `uid` = %s",
intval(1-$user[0]['blocked']),
intval($uid)
);
notice(sprintf(($user[0]['blocked']?t("User '%s' unblocked"):t("User '%s' blocked")) , $user[0]['username']).EOL);
}; break;
break;
}
goaway('admin/users');
return ''; // NOTREACHED
@ -1313,7 +1303,7 @@ function admin_page_users(App $a) {
/* get users */
$total = qu("SELECT COUNT(*) AS `total` FROM `user` WHERE 1");
if(count($total)) {
if (count($total)) {
$a->set_pager_total($total[0]['total']);
$a->set_pager_itemspage(100);
}
@ -1330,22 +1320,22 @@ function admin_page_users(App $a) {
$order = "contact.name";
$order_direction = "+";
if (x($_GET,'o')){
if (x($_GET,'o')) {
$new_order = $_GET['o'];
if ($new_order[0]==="-") {
if ($new_order[0] === "-") {
$order_direction = "-";
$new_order = substr($new_order,1);
}
if (in_array($new_order, $valid_orders)){
if (in_array($new_order, $valid_orders)) {
$order = $new_order;
}
if (x($_GET,'d')){
if (x($_GET,'d')) {
$new_direction = $_GET['d'];
}
}
$sql_order = "`".str_replace('.','`.`',$order)."`";
$sql_order_direction = ($order_direction==="+")?"ASC":"DESC";
$sql_order_direction = ($order_direction === "+")?"ASC":"DESC";
$users = qu("SELECT `user`.*, `contact`.`name`, `contact`.`url`, `contact`.`micro`, `user`.`account_expired`, `contact`.`last-item` AS `lastitem_date`
FROM `user`
@ -1359,7 +1349,7 @@ function admin_page_users(App $a) {
//echo "<pre>$users"; killme();
$adminlist = explode(",", str_replace(" ", "", $a->config['admin_email']));
$_setup_users = function ($e) use ($adminlist){
$_setup_users = function ($e) use ($adminlist) {
$accounts = array(
t('Normal Account'),
t('Soapbox Account'),
@ -1385,22 +1375,21 @@ function admin_page_users(App $a) {
$tmp_users = array();
$deleted = array();
while(count($users)) {
while (count($users)) {
$new_user = array();
foreach(array_pop($users) as $k => $v) {
foreach (array_pop($users) as $k => $v) {
$k = str_replace('-','_',$k);
$new_user[$k] = $v;
}
if($new_user['deleted']) {
if ($new_user['deleted']) {
array_push($deleted, $new_user);
}
else {
} else {
array_push($tmp_users, $new_user);
}
}
//Reversing the two array, and moving $tmp_users to $users
array_reverse($deleted);
while(count($tmp_users)) {
while (count($tmp_users)) {
array_push($users, array_pop($tmp_users));
}
@ -1477,19 +1466,19 @@ function admin_page_plugins(App $a) {
/*
* Single plugin
*/
if($a->argc == 3) {
if ($a->argc == 3) {
$plugin = $a->argv[2];
if(!is_file("addon/$plugin/$plugin.php")) {
if (!is_file("addon/$plugin/$plugin.php")) {
notice(t("Item not found."));
return '';
}
if(x($_GET,"a") && $_GET['a']=="t") {
if (x($_GET,"a") && $_GET['a']=="t") {
check_form_security_token_redirectOnErr('/admin/plugins', 'admin_themes', 't');
// Toggle plugin status
$idx = array_search($plugin, $a->plugins);
if($idx !== false) {
if ($idx !== false) {
unset($a->plugins[$idx]);
uninstall_plugin($plugin);
info(sprintf(t("Plugin %s disabled."), $plugin));
@ -1506,22 +1495,22 @@ function admin_page_plugins(App $a) {
// display plugin details
require_once('library/markdown.php');
if(in_array($plugin, $a->plugins)) {
if (in_array($plugin, $a->plugins)) {
$status="on"; $action= t("Disable");
} else {
$status="off"; $action= t("Enable");
}
$readme=Null;
if(is_file("addon/$plugin/README.md")) {
if (is_file("addon/$plugin/README.md")) {
$readme = file_get_contents("addon/$plugin/README.md");
$readme = Markdown($readme);
} elseif(is_file("addon/$plugin/README")) {
} elseif (is_file("addon/$plugin/README")) {
$readme = "<pre>". file_get_contents("addon/$plugin/README") ."</pre>";
}
$admin_form="";
if(is_array($a->plugins_admin) && in_array($plugin, $a->plugins_admin)) {
if (is_array($a->plugins_admin) && in_array($plugin, $a->plugins_admin)) {
@require_once("addon/$plugin/$plugin.php");
$func = $plugin.'_plugin_admin';
$func($a, $admin_form);
@ -1613,8 +1602,8 @@ function admin_page_plugins(App $a) {
*/
function toggle_theme(&$themes,$th,&$result) {
for($x = 0; $x < count($themes); $x ++) {
if($themes[$x]['name'] === $th) {
if($themes[$x]['allowed']) {
if ($themes[$x]['name'] === $th) {
if ($themes[$x]['allowed']) {
$themes[$x]['allowed'] = 0;
$result = 0;
}
@ -1633,8 +1622,8 @@ function toggle_theme(&$themes,$th,&$result) {
*/
function theme_status($themes,$th) {
for($x = 0; $x < count($themes); $x ++) {
if($themes[$x]['name'] === $th) {
if($themes[$x]['allowed']) {
if ($themes[$x]['name'] === $th) {
if ($themes[$x]['allowed']) {
return 1;
}
else {
@ -1652,11 +1641,12 @@ function theme_status($themes,$th) {
*/
function rebuild_theme_table($themes) {
$o = '';
if(count($themes)) {
foreach($themes as $th) {
if($th['allowed']) {
if(strlen($o))
if (count($themes)) {
foreach ($themes as $th) {
if ($th['allowed']) {
if (strlen($o)) {
$o .= ',';
}
$o .= $th['name'];
}
}
@ -1686,15 +1676,18 @@ function admin_page_themes(App $a) {
$allowed_themes_str = get_config('system','allowed_themes');
$allowed_themes_raw = explode(',',$allowed_themes_str);
$allowed_themes = array();
if(count($allowed_themes_raw))
foreach($allowed_themes_raw as $x)
if(strlen(trim($x)))
if (count($allowed_themes_raw)) {
foreach ($allowed_themes_raw as $x) {
if (strlen(trim($x))) {
$allowed_themes[] = trim($x);
}
}
}
$themes = array();
$files = glob('view/theme/*');
if($files) {
foreach($files as $file) {
if ($files) {
foreach ($files as $file) {
$f = basename($file);
// Is there a style file?
@ -1709,12 +1702,13 @@ function admin_page_themes(App $a) {
$is_supported = 1-(intval(file_exists($file.'/unsupported')));
$is_allowed = intval(in_array($f,$allowed_themes));
if($is_allowed OR $is_supported OR get_config("system", "show_unsupported_themes"))
if ($is_allowed OR $is_supported OR get_config("system", "show_unsupported_themes")) {
$themes[] = array('name' => $f, 'experimental' => $is_experimental, 'supported' => $is_supported, 'allowed' => $is_allowed);
}
}
}
if(! count($themes)) {
if (! count($themes)) {
notice(t('No themes found.'));
return '';
}
@ -1723,25 +1717,24 @@ function admin_page_themes(App $a) {
* Single theme
*/
if($a->argc == 3) {
if ($a->argc == 3) {
$theme = $a->argv[2];
if(! is_dir("view/theme/$theme")) {
if (! is_dir("view/theme/$theme")) {
notice(t("Item not found."));
return '';
}
if(x($_GET,"a") && $_GET['a']=="t") {
if (x($_GET,"a") && $_GET['a']=="t") {
check_form_security_token_redirectOnErr('/admin/themes', 'admin_themes', 't');
// Toggle theme status
toggle_theme($themes,$theme,$result);
$s = rebuild_theme_table($themes);
if($result) {
if ($result) {
install_theme($theme);
info(sprintf('Theme %s enabled.',$theme));
}
else {
} else {
uninstall_theme($theme);
info(sprintf('Theme %s disabled.',$theme));
}
@ -1754,22 +1747,22 @@ function admin_page_themes(App $a) {
// display theme details
require_once('library/markdown.php');
if(theme_status($themes,$theme)) {
if (theme_status($themes,$theme)) {
$status="on"; $action= t("Disable");
} else {
$status="off"; $action= t("Enable");
}
$readme=Null;
if(is_file("view/theme/$theme/README.md")) {
$readme = Null;
if (is_file("view/theme/$theme/README.md")) {
$readme = file_get_contents("view/theme/$theme/README.md");
$readme = Markdown($readme);
} elseif(is_file("view/theme/$theme/README")) {
} elseif (is_file("view/theme/$theme/README")) {
$readme = "<pre>". file_get_contents("view/theme/$theme/README") ."</pre>";
}
$admin_form="";
if(is_file("view/theme/$theme/config.php")) {
$admin_form = "";
if (is_file("view/theme/$theme/config.php")) {
function __get_theme_admin_form(App $a, $theme) {
$orig_theme = $a->theme;
$orig_page = $a->page;
@ -1780,8 +1773,10 @@ function admin_page_themes(App $a) {
$init = $theme."_init";
if(function_exists($init)) $init($a);
if(function_exists("theme_admin")) {
if (function_exists($init)) {
$init($a);
}
if (function_exists("theme_admin")) {
$admin_form = theme_admin($a);
}
@ -1794,9 +1789,9 @@ function admin_page_themes(App $a) {
}
$screenshot = array(get_theme_screenshot($theme), t('Screenshot'));
if(! stristr($screenshot[0],$theme))
if (! stristr($screenshot[0],$theme)) {
$screenshot = null;
}
$t = get_markup_template("admin_plugins_details.tpl");
return replace_macros($t, array(
@ -1842,7 +1837,7 @@ function admin_page_themes(App $a) {
$xthemes = array();
if ($themes) {
foreach($themes as $th) {
foreach ($themes as $th) {
$xthemes[] = array($th['name'],(($th['allowed']) ? "on" : "off"), get_theme_info($th['name']));
}
}
@ -1967,25 +1962,25 @@ function admin_page_viewlogs(App $a) {
$f = get_config('system','logfile');
$data = '';
if(!file_exists($f)) {
if (!file_exists($f)) {
$data = t("Error trying to open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f exist and is readable.");
}
else {
} else {
$fp = fopen($f, 'r');
if(!$fp) {
if (!$fp) {
$data = t("Couldn't open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f is readable.");
}
else {
} else {
$fstat = fstat($fp);
$size = $fstat['size'];
if($size != 0) {
if($size > 5000000 || $size < 0)
if ($size != 0) {
if ($size > 5000000 || $size < 0) {
$size = 5000000;
}
$seek = fseek($fp,0-$size,SEEK_END);
if($seek === 0) {
if ($seek === 0) {
$data = escape_tags(fread($fp,$size));
while(! feof($fp))
while (! feof($fp)) {
$data .= escape_tags(fread($fp,4096));
}
}
}
fclose($fp);
@ -2013,22 +2008,24 @@ function admin_page_features_post(App $a) {
$arr = array();
$features = get_features(false);
foreach($features as $fname => $fdata) {
foreach(array_slice($fdata,1) as $f) {
foreach ($features as $fname => $fdata) {
foreach (array_slice($fdata,1) as $f) {
$feature = $f[0];
$feature_state = 'feature_'.$feature;
$featurelock = 'featurelock_'.$feature;
if(x($_POST[$feature_state]))
if (x($_POST[$feature_state])) {
$val = intval($_POST['feature_'.$feature]);
else
} else {
$val = 0;
}
set_config('feature',$feature,$val);
if(x($_POST[$featurelock]))
if (x($_POST[$featurelock])) {
set_config('feature_lock',$feature,$val);
else
} else {
del_config('feature_lock',$feature);
}
}
}
@ -2052,18 +2049,19 @@ function admin_page_features_post(App $a) {
*/
function admin_page_features(App $a) {
if((argc() > 1) && (argv(1) === 'features')) {
if ((argc() > 1) && (argv(1) === 'features')) {
$arr = array();
$features = get_features(false);
foreach($features as $fname => $fdata) {
foreach ($features as $fname => $fdata) {
$arr[$fname] = array();
$arr[$fname][0] = $fdata[0];
foreach(array_slice($fdata,1) as $f) {
foreach (array_slice($fdata,1) as $f) {
$set = get_config('feature',$f[0]);
if($set === false)
if ($set === false) {
$set = $f[3];
}
$arr[$fname][1][] = array(
array('feature_' .$f[0],$f[1],$set,$f[2],array(t('Off'),t('On'))),
array('featurelock_' .$f[0],sprintf(t('Lock feature %s'),$f[1]),(($f[4] !== false) ? "1" : ''),'',array(t('Off'),t('On')))

View file

@ -534,13 +534,13 @@ function contacts_content(App $a) {
$insecure = t('Private communications are not available for this contact.');
$last_update = (($contact['last-update'] == '0000-00-00 00:00:00')
$last_update = (($contact['last-update'] <= NULL_DATE)
? t('Never')
: datetime_convert('UTC',date_default_timezone_get(),$contact['last-update'],'D, j M Y, g:i A'));
if($contact['last-update'] !== '0000-00-00 00:00:00')
if ($contact['last-update'] > NULL_DATE) {
$last_update .= ' ' . (($contact['last-update'] <= $contact['success_update']) ? t("\x28Update was successful\x29") : t("\x28Update was not successful\x29"));
}
$lblsuggest = (($contact['network'] === NETWORK_DFRN) ? t('Suggest friends') : '');
$poll_enabled = in_array($contact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_FEED, NETWORK_MAIL, NETWORK_MAIL2));
@ -558,12 +558,12 @@ function contacts_content(App $a) {
// tabs
$tab_str = contacts_tab($a, $contact_id, 2);
$lost_contact = (($contact['archive'] && $contact['term-date'] != '0000-00-00 00:00:00' && $contact['term-date'] < datetime_convert('','','now')) ? t('Communications lost with this contact!') : '');
$lost_contact = (($contact['archive'] && $contact['term-date'] > NULL_DATE && $contact['term-date'] < datetime_convert('','','now')) ? t('Communications lost with this contact!') : '');
if ($contact['network'] == NETWORK_FEED)
if ($contact['network'] == NETWORK_FEED) {
$fetch_further_information = array('fetch_further_information', t('Fetch further information for feeds'), $contact['fetch_further_information'], t('Fetch further information for feeds'),
array('0'=>t('Disabled'), '1'=>t('Fetch information'), '2'=>t('Fetch information and keywords')));
}
if (in_array($contact['network'], array(NETWORK_FEED, NETWORK_MAIL, NETWORK_MAIL2)))
$poll_interval = contact_poll_interval($contact['priority'],(! $poll_enabled));

View file

@ -1,12 +1,12 @@
<?php
/**
* @fiel mod/events.php
* @file mod/events.php
* @brief The events module
*/
require_once('include/bbcode.php');
require_once('include/datetime.php');
require_once('include/event.php');
require_once('include/items.php');
require_once 'include/bbcode.php';
require_once 'include/datetime.php';
require_once 'include/event.php';
require_once 'include/items.php';
function events_init(App $a) {
if (! local_user()) {
@ -14,10 +14,11 @@ function events_init(App $a) {
}
if ($a->argc == 1) {
// if it's a json request abort here becaus we don't
// If it's a json request abort here because we don't
// need the widget data
if ($a->argv[1] === 'json')
if ($a->argv[1] === 'json') {
return;
}
$cal_widget = widget_events();
@ -33,17 +34,17 @@ function events_init(App $a) {
function events_post(App $a) {
logger('post: ' . print_r($_REQUEST,true));
logger('post: ' . print_r($_REQUEST, true), LOGGER_DATA);
if (! local_user()) {
return;
}
$event_id = ((x($_POST,'event_id')) ? intval($_POST['event_id']) : 0);
$cid = ((x($_POST,'cid')) ? intval($_POST['cid']) : 0);
$uid = local_user();
$event_id = ((x($_POST, 'event_id')) ? intval($_POST['event_id']) : 0);
$cid = ((x($_POST, 'cid')) ? intval($_POST['cid']) : 0);
$uid = local_user();
$start_text = escape_tags($_REQUEST['start_text']);
$start_text = escape_tags($_REQUEST['start_text']);
$finish_text = escape_tags($_REQUEST['finish_text']);
$adjust = intval($_POST['adjust']);
@ -52,34 +53,26 @@ function events_post(App $a) {
// The default setting for the `private` field in event_store() is false, so mirror that
$private_event = false;
$start = NULL_DATE;
$finish = NULL_DATE;
if ($start_text) {
$start = $start_text;
}
else {
$start = sprintf('%d-%d-%d %d:%d:0',$startyear,$startmonth,$startday,$starthour,$startminute);
}
if ($nofinish) {
$finish = '0000-00-00 00:00:00';
}
if ($finish_text) {
$finish = $finish_text;
}
else {
$finish = sprintf('%d-%d-%d %d:%d:0',$finishyear,$finishmonth,$finishday,$finishhour,$finishminute);
}
if ($adjust) {
$start = datetime_convert(date_default_timezone_get(),'UTC',$start);
$start = datetime_convert(date_default_timezone_get(), 'UTC', $start);
if (! $nofinish) {
$finish = datetime_convert(date_default_timezone_get(),'UTC',$finish);
$finish = datetime_convert(date_default_timezone_get(), 'UTC', $finish);
}
}
else {
$start = datetime_convert('UTC','UTC',$start);
} else {
$start = datetime_convert('UTC', 'UTC', $start);
if (! $nofinish) {
$finish = datetime_convert('UTC','UTC',$finish);
$finish = datetime_convert('UTC', 'UTC', $finish);
}
}
@ -96,19 +89,19 @@ function events_post(App $a) {
$action = ($event_id == '') ? 'new' : "event/" . $event_id;
$onerror_url = App::get_baseurl() . "/events/" . $action . "?summary=$summary&description=$desc&location=$location&start=$start_text&finish=$finish_text&adjust=$adjust&nofinish=$nofinish";
if (strcmp($finish,$start) < 0 && !$nofinish) {
notice( t('Event can not end before it has started.') . EOL);
if (strcmp($finish, $start) < 0 && !$nofinish) {
notice(t('Event can not end before it has started.') . EOL);
if (intval($_REQUEST['preview'])) {
echo( t('Event can not end before it has started.'));
echo t('Event can not end before it has started.');
killme();
}
goaway($onerror_url);
}
if((! $summary) || (! $start)) {
notice( t('Event title and start time are required.') . EOL);
if(intval($_REQUEST['preview'])) {
echo( t('Event title and start time are required.'));
if ((! $summary) || ($start === NULL_DATE)) {
notice(t('Event title and start time are required.') . EOL);
if (intval($_REQUEST['preview'])) {
echo t('Event title and start time are required.');
killme();
}
goaway($onerror_url);
@ -116,35 +109,33 @@ function events_post(App $a) {
$share = ((intval($_POST['share'])) ? intval($_POST['share']) : 0);
$c = q("select id from contact where uid = %d and self = 1 limit 1",
$c = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1",
intval(local_user())
);
if(count($c))
if (count($c)) {
$self = $c[0]['id'];
else
} else {
$self = 0;
}
if($share) {
if ($share) {
$str_group_allow = perms2str($_POST['group_allow']);
$str_contact_allow = perms2str($_POST['contact_allow']);
$str_group_deny = perms2str($_POST['group_deny']);
$str_contact_deny = perms2str($_POST['contact_deny']);
// Undo the pseudo-contact of self, since there are real contacts now
if( strpos($str_contact_allow, '<' . $self . '>') !== false )
{
if (strpos($str_contact_allow, '<' . $self . '>') !== false ) {
$str_contact_allow = str_replace('<' . $self . '>', '', $str_contact_allow);
}
// Make sure to set the `private` field as true. This is necessary to
// have the posts show up correctly in Diaspora if an event is created
// as visible only to self at first, but then edited to display to others.
if( strlen($str_group_allow) or strlen($str_contact_allow) or strlen($str_group_deny) or strlen($str_contact_deny) )
{
if (strlen($str_group_allow) || strlen($str_contact_allow) || strlen($str_group_deny) || strlen($str_contact_deny)) {
$private_event = true;
}
}
else {
} else {
// Note: do not set `private` field for self-only events. It will
// keep even you from seeing them!
$str_contact_allow = '<' . $self . '>';
@ -153,46 +144,45 @@ function events_post(App $a) {
$datarray = array();
$datarray['guid'] = get_guid(32);
$datarray['start'] = $start;
$datarray['finish'] = $finish;
$datarray['summary'] = $summary;
$datarray['desc'] = $desc;
$datarray['location'] = $location;
$datarray['type'] = $type;
$datarray['adjust'] = $adjust;
$datarray['nofinish'] = $nofinish;
$datarray['uid'] = $uid;
$datarray['cid'] = $cid;
$datarray['guid'] = get_guid(32);
$datarray['start'] = $start;
$datarray['finish'] = $finish;
$datarray['summary'] = $summary;
$datarray['desc'] = $desc;
$datarray['location'] = $location;
$datarray['type'] = $type;
$datarray['adjust'] = $adjust;
$datarray['nofinish'] = $nofinish;
$datarray['uid'] = $uid;
$datarray['cid'] = $cid;
$datarray['allow_cid'] = $str_contact_allow;
$datarray['allow_gid'] = $str_group_allow;
$datarray['deny_cid'] = $str_contact_deny;
$datarray['deny_gid'] = $str_group_deny;
$datarray['private'] = (($private_event) ? 1 : 0);
$datarray['id'] = $event_id;
$datarray['created'] = $created;
$datarray['edited'] = $edited;
$datarray['deny_cid'] = $str_contact_deny;
$datarray['deny_gid'] = $str_group_deny;
$datarray['private'] = (($private_event) ? 1 : 0);
$datarray['id'] = $event_id;
$datarray['created'] = $created;
$datarray['edited'] = $edited;
if(intval($_REQUEST['preview'])) {
if (intval($_REQUEST['preview'])) {
$html = format_event_html($datarray);
echo $html;
killme();
killme();
}
$item_id = event_store($datarray);
if(! $cid)
if (! $cid) {
proc_run(PRIORITY_HIGH, "include/notifier.php", "event", $item_id);
}
goaway($_SESSION['return_url']);
}
function events_content(App $a) {
if (! local_user()) {
notice( t('Permission denied.') . EOL);
notice(t('Permission denied.') . EOL);
return;
}
@ -201,14 +191,14 @@ function events_content(App $a) {
}
if (($a->argc > 2) && ($a->argv[1] === 'ignore') && intval($a->argv[2])) {
$r = q("update event set ignore = 1 where id = %d and uid = %d",
$r = q("UPDATE `event` SET `ignore` = 1 WHERE `id` = %d AND `uid` = %d",
intval($a->argv[2]),
intval(local_user())
);
}
if (($a->argc > 2) && ($a->argv[1] === 'unignore') && intval($a->argv[2])) {
$r = q("update event set ignore = 0 where id = %d and uid = %d",
$r = q("UPDATE `event` SET `ignore` = 0 WHERE `id` = %d AND `uid` = %d",
intval($a->argv[2]),
intval(local_user())
);
@ -224,7 +214,7 @@ function events_content(App $a) {
$i18n = get_event_strings();
$htpl = get_markup_template('event_head.tpl');
$a->page['htmlhead'] .= replace_macros($htpl,array(
$a->page['htmlhead'] .= replace_macros($htpl, array(
'$baseurl' => App::get_baseurl(),
'$module_url' => '/events',
'$modparams' => 1,
@ -232,27 +222,30 @@ function events_content(App $a) {
));
$etpl = get_markup_template('event_end.tpl');
$a->page['end'] .= replace_macros($etpl,array(
$a->page['end'] .= replace_macros($etpl, array(
'$baseurl' => App::get_baseurl(),
));
$o ="";
$o = '';
// tabs
if ($a->theme_events_in_profile)
$tabs = profile_tabs($a, True);
if ($a->theme_events_in_profile) {
$tabs = profile_tabs($a, true);
}
$mode = 'view';
$y = 0;
$m = 0;
$ignored = ((x($_REQUEST,'ignored')) ? intval($_REQUEST['ignored']) : 0);
$ignored = ((x($_REQUEST, 'ignored')) ? intval($_REQUEST['ignored']) : 0);
if($a->argc > 1) {
if ($a->argc > 1) {
if ($a->argc > 2 && $a->argv[1] == 'event') {
$mode = 'edit';
$event_id = intval($a->argv[2]);
}
if ($a->argc > 2 && $a->argv[1] == 'drop') {
$mode = 'drop';
$event_id = intval($a->argv[2]);
}
if ($a->argv[1] === 'new') {
$mode = 'new';
$event_id = 0;
@ -267,9 +260,8 @@ function events_content(App $a) {
// The view mode part is similiar to /mod/cal.php
if ($mode == 'view') {
$thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
$thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m');
$thisyear = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y');
$thismonth = datetime_convert('UTC', date_default_timezone_get(), 'now', 'm');
if (! $y) {
$y = intval($thisyear);
}
@ -289,47 +281,47 @@ function events_content(App $a) {
$nextyear = $y;
$nextmonth = $m + 1;
if($nextmonth > 12) {
$nextmonth = 1;
if ($nextmonth > 12) {
$nextmonth = 1;
$nextyear ++;
}
$prevyear = $y;
if($m > 1)
if ($m > 1) {
$prevmonth = $m - 1;
else {
} else {
$prevmonth = 12;
$prevyear --;
}
$dim = get_dim($y,$m);
$start = sprintf('%d-%d-%d %d:%d:%d',$y,$m,1,0,0,0);
$finish = sprintf('%d-%d-%d %d:%d:%d',$y,$m,$dim,23,59,59);
$dim = get_dim($y, $m);
$start = sprintf('%d-%d-%d %d:%d:%d', $y, $m, 1, 0, 0, 0);
$finish = sprintf('%d-%d-%d %d:%d:%d', $y, $m, $dim, 23, 59, 59);
if ($a->argv[1] === 'json'){
if (x($_GET,'start')) $start = $_GET['start'];
if (x($_GET,'end')) $finish = $_GET['end'];
if ($a->argv[1] === 'json') {
if (x($_GET, 'start')) {$start = $_GET['start'];}
if (x($_GET, 'end')) {$finish = $_GET['end'];}
}
$start = datetime_convert('UTC','UTC',$start);
$finish = datetime_convert('UTC','UTC',$finish);
$start = datetime_convert('UTC', 'UTC', $start);
$finish = datetime_convert('UTC', 'UTC', $finish);
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
$adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish);
// put the event parametes in an array so we can better transmit them
$event_params = array(
'event_id' => (x($_GET,'id') ? $_GET["id"] : 0),
'start' => $start,
'finish' => $finish,
'adjust_start' => $adjust_start,
'event_id' => (x($_GET, 'id') ? $_GET['id'] : 0),
'start' => $start,
'finish' => $finish,
'adjust_start' => $adjust_start,
'adjust_finish' => $adjust_finish,
'ignored' => $ignored,
'ignored' => $ignored,
);
// get events by id or by date
if (x($_GET,'id')){
if (x($_GET, 'id')) {
$r = event_by_id(local_user(), $event_params);
} else {
$r = events_by_date(local_user(), $event_params);
@ -340,7 +332,7 @@ function events_content(App $a) {
if (dbm::is_result($r)) {
$r = sort_by_date($r);
foreach ($r as $rr) {
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'j') : datetime_convert('UTC','UTC',$rr['start'],'j'));
$j = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['start'], 'j') : datetime_convert('UTC', 'UTC', $rr['start'], 'j'));
if (! x($links,$j)) {
$links[$j] = App::get_baseurl() . '/' . $a->cmd . '#link-' . $j;
}
@ -356,127 +348,127 @@ function events_content(App $a) {
}
if ($a->argv[1] === 'json'){
echo json_encode($events); killme();
echo json_encode($events);
killme();
}
// links: array('href', 'text', 'extra css classes', 'title')
if (x($_GET,'id')){
if (x($_GET, 'id')) {
$tpl = get_markup_template("event.tpl");
} else {
// if (get_config('experimentals','new_calendar')==1){
$tpl = get_markup_template("events_js.tpl");
// } else {
// $tpl = get_markup_template("events.tpl");
// }
$tpl = get_markup_template("events_js.tpl");
}
// Get rid of dashes in key names, Smarty3 can't handle them
foreach($events as $key => $event) {
foreach ($events as $key => $event) {
$event_item = array();
foreach($event['item'] as $k => $v) {
$k = str_replace('-','_',$k);
foreach ($event['item'] as $k => $v) {
$k = str_replace('-' ,'_', $k);
$event_item[$k] = $v;
}
$events[$key]['item'] = $event_item;
}
$o = replace_macros($tpl, array(
'$baseurl' => App::get_baseurl(),
'$tabs' => $tabs,
'$title' => t('Events'),
'$view' => t('View'),
'$new_event' => array(App::get_baseurl().'/events/new',t('Create New Event'),'',''),
'$previous' => array(App::get_baseurl()."/events/$prevyear/$prevmonth",t('Previous'),'',''),
'$next' => array(App::get_baseurl()."/events/$nextyear/$nextmonth",t('Next'),'',''),
'$calendar' => cal($y,$m,$links, ' eventcal'),
'$baseurl' => App::get_baseurl(),
'$tabs' => $tabs,
'$title' => t('Events'),
'$view' => t('View'),
'$new_event' => array(App::get_baseurl() . '/events/new', t('Create New Event'), '', ''),
'$previous' => array(App::get_baseurl() . '/events/$prevyear/$prevmonth', t('Previous'), '', ''),
'$next' => array(App::get_baseurl() . '/events/$nextyear/$nextmonth', t('Next'), '', ''),
'$calendar' => cal($y, $m, $links, ' eventcal'),
'$events' => $events,
'$events' => $events,
"today" => t("today"),
"month" => t("month"),
"week" => t("week"),
"day" => t("day"),
"list" => t("list"),
'$today' => t('today'),
'$month' => t('month'),
'$week' => t('week'),
'$day' => t('day'),
'$list' => t('list'),
));
if (x($_GET,'id')){ echo $o; killme(); }
if (x($_GET, 'id')) {
echo $o;
killme();
}
return $o;
}
if($mode === 'edit' && $event_id) {
if ($mode === 'edit' && $event_id) {
$r = q("SELECT * FROM `event` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($event_id),
intval(local_user())
);
if (dbm::is_result($r))
if (dbm::is_result($r)) {
$orig_event = $r[0];
}
}
// Passed parameters overrides anything found in the DB
if($mode === 'edit' || $mode === 'new') {
if(!x($orig_event)) $orig_event = array();
if ($mode === 'edit' || $mode === 'new') {
if (!x($orig_event)) {$orig_event = array();}
// In case of an error the browser is redirected back here, with these parameters filled in with the previous values
if(x($_REQUEST,'nofinish')) $orig_event['nofinish'] = $_REQUEST['nofinish'];
if(x($_REQUEST,'adjust')) $orig_event['adjust'] = $_REQUEST['adjust'];
if(x($_REQUEST,'summary')) $orig_event['summary'] = $_REQUEST['summary'];
if(x($_REQUEST,'description')) $orig_event['description'] = $_REQUEST['description'];
if(x($_REQUEST,'location')) $orig_event['location'] = $_REQUEST['location'];
if(x($_REQUEST,'start')) $orig_event['start'] = $_REQUEST['start'];
if(x($_REQUEST,'finish')) $orig_event['finish'] = $_REQUEST['finish'];
}
if($mode === 'edit' || $mode === 'new') {
if (x($_REQUEST, 'nofinish')) {$orig_event['nofinish'] = $_REQUEST['nofinish'];}
if (x($_REQUEST, 'adjust')) {$orig_event['adjust'] = $_REQUEST['adjust'];}
if (x($_REQUEST, 'summary')) {$orig_event['summary'] = $_REQUEST['summary'];}
if (x($_REQUEST, 'description')) {$orig_event['description'] = $_REQUEST['description'];}
if (x($_REQUEST, 'location')) {$orig_event['location'] = $_REQUEST['location'];}
if (x($_REQUEST, 'start')) {$orig_event['start'] = $_REQUEST['start'];}
if (x($_REQUEST, 'finish')) {$orig_event['finish'] = $_REQUEST['finish'];}
$n_checked = ((x($orig_event) && $orig_event['nofinish']) ? ' checked="checked" ' : '');
$a_checked = ((x($orig_event) && $orig_event['adjust']) ? ' checked="checked" ' : '');
$t_orig = ((x($orig_event)) ? $orig_event['summary'] : '');
$d_orig = ((x($orig_event)) ? $orig_event['desc'] : '');
$a_checked = ((x($orig_event) && $orig_event['adjust']) ? ' checked="checked" ' : '');
$t_orig = ((x($orig_event)) ? $orig_event['summary'] : '');
$d_orig = ((x($orig_event)) ? $orig_event['desc'] : '');
$l_orig = ((x($orig_event)) ? $orig_event['location'] : '');
$eid = ((x($orig_event)) ? $orig_event['id'] : 0);
$cid = ((x($orig_event)) ? $orig_event['cid'] : 0);
$uri = ((x($orig_event)) ? $orig_event['uri'] : '');
$eid = ((x($orig_event)) ? $orig_event['id'] : 0);
$cid = ((x($orig_event)) ? $orig_event['cid'] : 0);
$uri = ((x($orig_event)) ? $orig_event['uri'] : '');
if(! x($orig_event))
if (! x($orig_event)) {
$sh_checked = '';
else
$sh_checked = (($orig_event['allow_cid'] === '<' . local_user() . '>' && (! $orig_event['allow_gid']) && (! $orig_event['deny_cid']) && (! $orig_event['deny_gid'])) ? '' : ' checked="checked" ' );
} else {
$sh_checked = (($orig_event['allow_cid'] === '<' . local_user() . '>' && (! $orig_event['allow_gid']) && (! $orig_event['deny_cid']) && (! $orig_event['deny_gid'])) ? '' : ' checked="checked" ');
}
if($cid OR ($mode !== 'new'))
if ($cid OR ($mode !== 'new')) {
$sh_checked .= ' disabled="disabled" ';
}
$sdt = ((x($orig_event)) ? $orig_event['start'] : 'now');
$fdt = ((x($orig_event)) ? $orig_event['finish'] : 'now');
$tz = date_default_timezone_get();
if(x($orig_event))
if (x($orig_event)) {
$tz = (($orig_event['adjust']) ? date_default_timezone_get() : 'UTC');
}
$syear = datetime_convert('UTC', $tz, $sdt, 'Y');
$syear = datetime_convert('UTC', $tz, $sdt, 'Y');
$smonth = datetime_convert('UTC', $tz, $sdt, 'm');
$sday = datetime_convert('UTC', $tz, $sdt, 'd');
$sday = datetime_convert('UTC', $tz, $sdt, 'd');
$shour = ((x($orig_event)) ? datetime_convert('UTC', $tz, $sdt, 'H') : 0);
$shour = ((x($orig_event)) ? datetime_convert('UTC', $tz, $sdt, 'H') : 0);
$sminute = ((x($orig_event)) ? datetime_convert('UTC', $tz, $sdt, 'i') : 0);
$fyear = datetime_convert('UTC', $tz, $fdt, 'Y');
$fyear = datetime_convert('UTC', $tz, $fdt, 'Y');
$fmonth = datetime_convert('UTC', $tz, $fdt, 'm');
$fday = datetime_convert('UTC', $tz, $fdt, 'd');
$fday = datetime_convert('UTC', $tz, $fdt, 'd');
$fhour = ((x($orig_event)) ? datetime_convert('UTC', $tz, $fdt, 'H') : 0);
$fhour = ((x($orig_event)) ? datetime_convert('UTC', $tz, $fdt, 'H') : 0);
$fminute = ((x($orig_event)) ? datetime_convert('UTC', $tz, $fdt, 'i') : 0);
$f = get_config('system','event_input_format');
if(! $f)
if (! $f) {
$f = 'ymd';
}
require_once('include/acl_selectors.php');
require_once 'include/acl_selectors.php' ;
if ($mode === 'new')
if ($mode === 'new') {
$acl = (($cid) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $a->user)));
}
$tpl = get_markup_template('event_form.tpl');
@ -489,11 +481,11 @@ function events_content(App $a) {
'$title' => t('Event details'),
'$desc' => t('Starting date and Title are required.'),
'$s_text' => t('Event Starts:') . ' <span class="required" title="' . t('Required') . '">*</span>',
'$s_dsel' => datetimesel($f,new DateTime(),DateTime::createFromFormat('Y',$syear+5),DateTime::createFromFormat('Y-m-d H:i',"$syear-$smonth-$sday $shour:$sminute"),t('Event Starts:'),'start_text',true,true,'','',true),
'$s_dsel' => datetimesel($f, new DateTime(), DateTime::createFromFormat('Y', $syear+5), DateTime::createFromFormat('Y-m-d H:i', "$syear-$smonth-$sday $shour:$sminute"), t('Event Starts:'), 'start_text', true, true, '', '', true),
'$n_text' => t('Finish date/time is not known or not relevant'),
'$n_checked' => $n_checked,
'$f_text' => t('Event Finishes:'),
'$f_dsel' => datetimesel($f,new DateTime(),DateTime::createFromFormat('Y',$fyear+5),DateTime::createFromFormat('Y-m-d H:i',"$fyear-$fmonth-$fday $fhour:$fminute"),t('Event Finishes:'),'finish_text',true,true,'start_text'),
'$f_dsel' => datetimesel($f, new DateTime(), DateTime::createFromFormat('Y', $fyear+5), DateTime::createFromFormat('Y-m-d H:i', "$fyear-$fmonth-$fday $fhour:$fminute"), t('Event Finishes:'), 'finish_text', true, true, 'start_text'),
'$a_text' => t('Adjust for viewer timezone'),
'$a_checked' => $a_checked,
'$d_text' => t('Description:'),
@ -511,12 +503,33 @@ function events_content(App $a) {
'$preview' => t('Preview'),
'$acl' => $acl,
'$submit' => t('Submit'),
'$basic' => t("Basic"),
'$advanced' => t("Advanced"),
'$basic' => t('Basic'),
'$advanced' => t('Advanced'),
'$permissions' => t('Permissions'),
));
return $o;
}
// Remove an event from the calendar and its related items
if ($mode === 'drop' && $event_id) {
$del = 0;
$params = array('event_id' => ($event_id));
$ev = event_by_id(local_user(), $params);
// Delete only real events (no birthdays)
if (dbm::is_result($ev) && $ev[0]['type'] == 'event') {
$del = drop_item($ev[0]['itemid'], false);
}
if ($del == 0) {
notice(t('Failed to remove event' ) . EOL);
} else {
info(t('Event removed') . EOL);
}
goaway(App::get_baseurl() . '/events');
}
}

View file

@ -1,11 +1,23 @@
<?php
use \Friendica\Core\Config;
function maintenance_content(App $a) {
$reason = Config::get('system', 'maintenance_reason');
if (substr(normalise_link($reason), 0, 7) == 'http://') {
header("HTTP/1.1 307 Temporary Redirect");
header("Location:".$reason);
return;
}
header('HTTP/1.1 503 Service Temporarily Unavailable');
header('Status: 503 Service Temporarily Unavailable');
header('Retry-After: 600');
return replace_macros(get_markup_template('maintenance.tpl'), array(
'$sysdown' => t('System down for maintenance')
'$sysdown' => t('System down for maintenance'),
'$reason' => $reason
));
}

View file

@ -7,14 +7,14 @@ function poco_init(App $a) {
$system_mode = false;
if(intval(get_config('system','block_public')) || (get_config('system','block_local_dir')))
if (intval(get_config('system','block_public')) || (get_config('system','block_local_dir'))) {
http_status_exit(401);
}
if($a->argc > 1) {
if ($a->argc > 1) {
$user = notags(trim($a->argv[1]));
}
if(! x($user)) {
if (! x($user)) {
$c = q("SELECT * FROM `pconfig` WHERE `cat` = 'system' AND `k` = 'suggestme' AND `v` = 1");
if (! dbm::is_result($c)) {
http_status_exit(401);
@ -27,42 +27,55 @@ function poco_init(App $a) {
$justme = false;
$global = false;
if($a->argc > 1 && $a->argv[1] === '@global') {
if ($a->argc > 1 && $a->argv[1] === '@server') {
// List of all servers that this server knows
$ret = poco_serverlist();
header('Content-type: application/json');
echo json_encode($ret);
killme();
}
if ($a->argc > 1 && $a->argv[1] === '@global') {
// List of all profiles that this server recently had data from
$global = true;
$update_limit = date("Y-m-d H:i:s", time() - 30 * 86400);
}
if($a->argc > 2 && $a->argv[2] === '@me')
if ($a->argc > 2 && $a->argv[2] === '@me') {
$justme = true;
if($a->argc > 3 && $a->argv[3] === '@all')
}
if ($a->argc > 3 && $a->argv[3] === '@all') {
$justme = false;
if($a->argc > 3 && $a->argv[3] === '@self')
}
if ($a->argc > 3 && $a->argv[3] === '@self') {
$justme = true;
if($a->argc > 4 && intval($a->argv[4]) && $justme == false)
}
if ($a->argc > 4 && intval($a->argv[4]) && $justme == false) {
$cid = intval($a->argv[4]);
}
if(!$system_mode AND !$global) {
if (!$system_mode AND !$global) {
$r = q("SELECT `user`.*,`profile`.`hide-friends` from user left join profile on `user`.`uid` = `profile`.`uid`
where `user`.`nickname` = '%s' and `profile`.`is-default` = 1 limit 1",
dbesc($user)
);
if(! dbm::is_result($r) || $r[0]['hidewall'] || $r[0]['hide-friends'])
if (! dbm::is_result($r) || $r[0]['hidewall'] || $r[0]['hide-friends']) {
http_status_exit(404);
}
$user = $r[0];
}
if($justme)
if ($justme) {
$sql_extra = " AND `contact`.`self` = 1 ";
}
// else
// $sql_extra = " AND `contact`.`self` = 0 ";
if($cid)
if ($cid) {
$sql_extra = sprintf(" AND `contact`.`id` = %d ",intval($cid));
if(x($_GET,'updatedSince'))
}
if (x($_GET,'updatedSince')) {
$update_limit = date("Y-m-d H:i:s",strtotime($_GET['updatedSince']));
}
if ($global) {
$r = q("SELECT count(*) AS `total` FROM `gcontact` WHERE `updated` >= '%s' AND `updated` >= `last_failure` AND NOT `hide` AND `network` IN ('%s', '%s', '%s')",
dbesc($update_limit),
@ -70,7 +83,7 @@ function poco_init(App $a) {
dbesc(NETWORK_DIASPORA),
dbesc(NETWORK_OSTATUS)
);
} elseif($system_mode) {
} elseif ($system_mode) {
$r = q("SELECT count(*) AS `total` FROM `contact` WHERE `self` = 1
AND `uid` IN (SELECT `uid` FROM `pconfig` WHERE `cat` = 'system' AND `k` = 'suggestme' AND `v` = 1) ");
} else {
@ -84,14 +97,15 @@ function poco_init(App $a) {
dbesc(NETWORK_STATUSNET)
);
}
if (dbm::is_result($r))
if (dbm::is_result($r)) {
$totalResults = intval($r[0]['total']);
else
} else {
$totalResults = 0;
}
$startIndex = intval($_GET['startIndex']);
if(! $startIndex)
if (! $startIndex) {
$startIndex = 0;
}
$itemsPerPage = ((x($_GET,'count') && intval($_GET['count'])) ? intval($_GET['count']) : $totalResults);
if ($global) {
@ -105,7 +119,7 @@ function poco_init(App $a) {
intval($startIndex),
intval($itemsPerPage)
);
} elseif($system_mode) {
} elseif ($system_mode) {
logger("Start system mode query", LOGGER_DEBUG);
$r = q("SELECT `contact`.*, `profile`.`about` AS `pabout`, `profile`.`locality` AS `plocation`, `profile`.`pub_keywords`,
`profile`.`gender` AS `pgender`, `profile`.`address` AS `paddress`, `profile`.`region` AS `pregion`,
@ -134,13 +148,15 @@ function poco_init(App $a) {
logger("Query done", LOGGER_DEBUG);
$ret = array();
if(x($_GET,'sorted'))
if (x($_GET,'sorted')) {
$ret['sorted'] = false;
if(x($_GET,'filtered'))
}
if (x($_GET,'filtered')) {
$ret['filtered'] = false;
if(x($_GET,'updatedSince') AND !$global)
}
if (x($_GET,'updatedSince') AND !$global) {
$ret['updatedSince'] = false;
}
$ret['startIndex'] = (int) $startIndex;
$ret['itemsPerPage'] = (int) $itemsPerPage;
$ret['totalResults'] = (int) $totalResults;
@ -164,58 +180,61 @@ function poco_init(App $a) {
'generation' => false
);
if((! x($_GET,'fields')) || ($_GET['fields'] === '@all'))
foreach($fields_ret as $k => $v)
if ((! x($_GET,'fields')) || ($_GET['fields'] === '@all')) {
foreach ($fields_ret as $k => $v) {
$fields_ret[$k] = true;
else {
}
} else {
$fields_req = explode(',',$_GET['fields']);
foreach($fields_req as $f)
foreach ($fields_req as $f) {
$fields_ret[trim($f)] = true;
}
}
if(is_array($r)) {
if (is_array($r)) {
if (dbm::is_result($r)) {
foreach ($r as $rr) {
if (!isset($rr['generation'])) {
if ($global)
if ($global) {
$rr['generation'] = 3;
elseif ($system_mode)
} elseif ($system_mode) {
$rr['generation'] = 1;
else
} else {
$rr['generation'] = 2;
}
}
if (($rr['about'] == "") AND isset($rr['pabout']))
if (($rr['about'] == "") AND isset($rr['pabout'])) {
$rr['about'] = $rr['pabout'];
}
if ($rr['location'] == "") {
if (isset($rr['plocation']))
if (isset($rr['plocation'])) {
$rr['location'] = $rr['plocation'];
}
if (isset($rr['pregion']) AND ($rr['pregion'] != "")) {
if ($rr['location'] != "")
if ($rr['location'] != "") {
$rr['location'] .= ", ";
}
$rr['location'] .= $rr['pregion'];
}
if (isset($rr['pcountry']) AND ($rr['pcountry'] != "")) {
if ($rr['location'] != "")
if ($rr['location'] != "") {
$rr['location'] .= ", ";
}
$rr['location'] .= $rr['pcountry'];
}
}
if (($rr['gender'] == "") AND isset($rr['pgender']))
if (($rr['gender'] == "") AND isset($rr['pgender'])) {
$rr['gender'] = $rr['pgender'];
if (($rr['keywords'] == "") AND isset($rr['pub_keywords']))
}
if (($rr['keywords'] == "") AND isset($rr['pub_keywords'])) {
$rr['keywords'] = $rr['pub_keywords'];
if (isset($rr['account-type']))
}
if (isset($rr['account-type'])) {
$rr['contact-type'] = $rr['account-type'];
}
$about = Cache::get("about:".$rr['updated'].":".$rr['nurl']);
if (is_null($about)) {
$about = bbcode($rr['about'], false, false);
@ -230,111 +249,122 @@ function poco_init(App $a) {
}
$entry = array();
if($fields_ret['id'])
if ($fields_ret['id']) {
$entry['id'] = (int)$rr['id'];
if($fields_ret['displayName'])
$entry['displayName'] = $rr['name'];
if($fields_ret['aboutMe'])
$entry['aboutMe'] = $about;
if($fields_ret['currentLocation'])
$entry['currentLocation'] = $rr['location'];
if($fields_ret['gender'])
$entry['gender'] = $rr['gender'];
if($fields_ret['generation'])
$entry['generation'] = (int)$rr['generation'];
if($fields_ret['urls']) {
$entry['urls'] = array(array('value' => $rr['url'], 'type' => 'profile'));
if($rr['addr'] && ($rr['network'] !== NETWORK_MAIL))
$entry['urls'][] = array('value' => 'acct:' . $rr['addr'], 'type' => 'webfinger');
}
if($fields_ret['preferredUsername'])
if ($fields_ret['displayName']) {
$entry['displayName'] = $rr['name'];
}
if ($fields_ret['aboutMe']) {
$entry['aboutMe'] = $about;
}
if ($fields_ret['currentLocation']) {
$entry['currentLocation'] = $rr['location'];
}
if ($fields_ret['gender']) {
$entry['gender'] = $rr['gender'];
}
if ($fields_ret['generation']) {
$entry['generation'] = (int)$rr['generation'];
}
if ($fields_ret['urls']) {
$entry['urls'] = array(array('value' => $rr['url'], 'type' => 'profile'));
if ($rr['addr'] && ($rr['network'] !== NETWORK_MAIL)) {
$entry['urls'][] = array('value' => 'acct:' . $rr['addr'], 'type' => 'webfinger');
}
}
if ($fields_ret['preferredUsername']) {
$entry['preferredUsername'] = $rr['nick'];
if($fields_ret['updated']) {
}
if ($fields_ret['updated']) {
if (!$global) {
$entry['updated'] = $rr['success_update'];
if ($rr['name-date'] > $entry['updated'])
if ($rr['name-date'] > $entry['updated']) {
$entry['updated'] = $rr['name-date'];
if ($rr['uri-date'] > $entry['updated'])
}
if ($rr['uri-date'] > $entry['updated']) {
$entry['updated'] = $rr['uri-date'];
if ($rr['avatar-date'] > $entry['updated'])
}
if ($rr['avatar-date'] > $entry['updated']) {
$entry['updated'] = $rr['avatar-date'];
} else
}
} else {
$entry['updated'] = $rr['updated'];
}
$entry['updated'] = date("c", strtotime($entry['updated']));
}
if($fields_ret['photos'])
if ($fields_ret['photos']) {
$entry['photos'] = array(array('value' => $rr['photo'], 'type' => 'profile'));
if($fields_ret['network']) {
$entry['network'] = $rr['network'];
if ($entry['network'] == NETWORK_STATUSNET)
$entry['network'] = NETWORK_OSTATUS;
if (($entry['network'] == "") AND ($rr['self']))
$entry['network'] = NETWORK_DFRN;
}
if($fields_ret['tags']) {
if ($fields_ret['network']) {
$entry['network'] = $rr['network'];
if ($entry['network'] == NETWORK_STATUSNET) {
$entry['network'] = NETWORK_OSTATUS;
}
if (($entry['network'] == "") AND ($rr['self'])) {
$entry['network'] = NETWORK_DFRN;
}
}
if ($fields_ret['tags']) {
$tags = str_replace(","," ",$rr['keywords']);
$tags = explode(" ", $tags);
$cleaned = array();
foreach ($tags as $tag) {
$tag = trim(strtolower($tag));
if ($tag != "")
if ($tag != "") {
$cleaned[] = $tag;
}
}
$entry['tags'] = array($cleaned);
}
if($fields_ret['address']) {
if ($fields_ret['address']) {
$entry['address'] = array();
// Deactivated. It just reveals too much data. (Although its from the default profile)
//if (isset($rr['paddress']))
// $entry['address']['streetAddress'] = $rr['paddress'];
if (isset($rr['plocation']))
if (isset($rr['plocation'])) {
$entry['address']['locality'] = $rr['plocation'];
if (isset($rr['pregion']))
}
if (isset($rr['pregion'])) {
$entry['address']['region'] = $rr['pregion'];
}
// See above
//if (isset($rr['ppostalcode']))
// $entry['address']['postalCode'] = $rr['ppostalcode'];
if (isset($rr['pcountry']))
if (isset($rr['pcountry'])) {
$entry['address']['country'] = $rr['pcountry'];
}
}
if($fields_ret['contactType'])
if ($fields_ret['contactType']) {
$entry['contactType'] = intval($rr['contact-type']);
}
$ret['entry'][] = $entry;
}
}
else
} else {
$ret['entry'][] = array();
}
else
}
} else {
http_status_exit(500);
}
logger("End of poco", LOGGER_DEBUG);
if($format === 'xml') {
if ($format === 'xml') {
header('Content-type: text/xml');
echo replace_macros(get_markup_template('poco_xml.tpl'),array_xmlify(array('$response' => $ret)));
killme();
}
if($format === 'json') {
if ($format === 'json') {
header('Content-type: application/json');
echo json_encode($ret);
killme();
}
else
} else {
http_status_exit(500);
}
}

View file

@ -233,11 +233,11 @@ function profiles_post(App $a) {
$with = ((x($_POST,'with')) ? notags(trim($_POST['with'])) : '');
if(! strlen($howlong))
$howlong = '0000-00-00 00:00:00';
else
if(! strlen($howlong)) {
$howlong = NULL_DATE;
} else {
$howlong = datetime_convert(date_default_timezone_get(),'UTC',$howlong);
}
// linkify the relationship target if applicable
$withchanged = false;
@ -721,7 +721,7 @@ function profiles_content(App $a) {
'$gender' => gender_selector($r[0]['gender']),
'$marital' => marital_selector($r[0]['marital']),
'$with' => array('with', t("Who: \x28if applicable\x29"), strip_tags($r[0]['with']), t('Examples: cathy123, Cathy Williams, cathy@example.com')),
'$howlong' => array('howlong', t('Since [date]:'), ($r[0]['howlong'] === '0000-00-00 00:00:00' ? '' : datetime_convert('UTC',date_default_timezone_get(),$r[0]['howlong']))),
'$howlong' => array('howlong', t('Since [date]:'), ($r[0]['howlong'] <= NULL_DATE ? '' : datetime_convert('UTC',date_default_timezone_get(),$r[0]['howlong']))),
'$sexual' => sexpref_selector($r[0]['sexual']),
'$about' => array('about', t('Tell us about yourself...'), $r[0]['about']),
'$xmpp' => array('xmpp', t('XMPP (Jabber) address:'), $r[0]['xmpp'], t("The XMPP address will be propagated to your contacts so that they can follow you.")),

View file

@ -872,7 +872,7 @@ function settings_content(App $a) {
$mail_pubmail = ((dbm::is_result($r)) ? $r[0]['pubmail'] : 0);
$mail_action = ((dbm::is_result($r)) ? $r[0]['action'] : 0);
$mail_movetofolder = ((dbm::is_result($r)) ? $r[0]['movetofolder'] : '');
$mail_chk = ((dbm::is_result($r)) ? $r[0]['last_check'] : '0000-00-00 00:00:00');
$mail_chk = ((dbm::is_result($r)) ? $r[0]['last_check'] : NULL_DATE);
$tpl = get_markup_template("settings_connectors.tpl");

View file

@ -10,7 +10,7 @@ use \Friendica\Core\PConfig;
function worker_init($a){
if (!Config::get("system", "frontend_worker") OR !Config::get("system", "worker")) {
if (!Config::get("system", "frontend_worker")) {
return;
}

View file

@ -1,6 +1,6 @@
<?php
define('UPDATE_VERSION' , 1215);
define('UPDATE_VERSION' , 1216);
/**
*
@ -48,8 +48,8 @@ function update_1000() {
q("ALTER TABLE `intro` ADD `duplex` TINYINT( 1 ) NOT NULL DEFAULT '0' AFTER `knowyou` ");
q("ALTER TABLE `contact` ADD `duplex` TINYINT( 1 ) NOT NULL DEFAULT '0' AFTER `rel` ");
q("ALTER TABLE `contact` CHANGE `issued-pubkey` `issued-pubkey` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL");
q("ALTER TABLE `contact` ADD `term-date` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `avatar-date`");
q("ALTER TABLE `contact` CHANGE `issued-pubkey` `issued-pubkey` TEXTCHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL");
q("ALTER TABLE `contact` ADD `term-date` DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00' AFTER `avatar-date`");
}
function update_1001() {
@ -242,8 +242,8 @@ function update_1022() {
}
function update_1023() {
q("ALTER TABLE `user` ADD `register_date` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `timezone` ,
ADD `login_date` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `register_date` ");
q("ALTER TABLE `user` ADD `register_date` DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00' AFTER `timezone` ,
ADD `login_date` DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00' AFTER `register_date` ");
}
function update_1024() {
@ -349,7 +349,7 @@ function update_1034() {
function update_1035() {
q("ALTER TABLE `contact` ADD `success_update` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `last-update` ");
q("ALTER TABLE `contact` ADD `success_update` DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00' AFTER `last-update` ");
}
@ -443,7 +443,7 @@ function update_1049() {
`user` CHAR( 255 ) NOT NULL ,
`pass` CHAR( 255 ) NOT NULL ,
`reply_to` CHAR( 255 ) NOT NULL ,
`last_check` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00'
`last_check` DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00'
) ENGINE = MYISAM ");
}
@ -454,8 +454,8 @@ function update_1050() {
`filetype` CHAR( 64 ) NOT NULL ,
`filesize` INT NOT NULL ,
`data` LONGBLOB NOT NULL ,
`created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`edited` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00',
`edited` DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00',
`allow_cid` MEDIUMTEXT NOT NULL ,
`allow_gid` MEDIUMTEXT NOT NULL ,
`deny_cid` MEDIUMTEXT NOT NULL ,
@ -531,7 +531,7 @@ function update_1065() {
}
function update_1066() {
$r = q("ALTER TABLE `item` ADD `received` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `edited` ");
$r = q("ALTER TABLE `item` ADD `received` DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00' AFTER `edited` ");
if($r)
q("ALTER TABLE `item` ADD INDEX ( `received` ) ");
@ -673,7 +673,7 @@ function update_1079() {
}
function update_1080() {
q("ALTER TABLE `fcontact` ADD `updated` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00'");
q("ALTER TABLE `fcontact` ADD `updated` DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00'");
}
function update_1081() {
@ -728,7 +728,7 @@ function update_1086() {
}
function update_1087() {
q("ALTER TABLE `item` ADD `commented` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `edited` ");
q("ALTER TABLE `item` ADD `commented` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' AFTER `edited` ");
$r = q("SELECT `id` FROM `item` WHERE `parent` = `id` ");
if (dbm::is_result($r)) {
@ -747,8 +747,8 @@ function update_1087() {
function update_1088() {
q("ALTER TABLE `user` ADD `account_expired` TINYINT( 1 ) NOT NULL DEFAULT '0' AFTER `expire` ,
ADD `account_expires_on` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `account_expired` ,
ADD `expire_notification_sent` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `account_expires_on` ");
ADD `account_expires_on` DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00' AFTER `account_expired` ,
ADD `expire_notification_sent` DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00' AFTER `account_expires_on` ");
}
function update_1089() {
@ -932,8 +932,8 @@ ADD INDEX ( `hidden` ) ");
function update_1109() {
q("ALTER TABLE `conv` ADD `creator` CHAR( 255 ) NOT NULL ,
ADD `created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
ADD `updated` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
ADD `created` DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00',
ADD `updated` DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00',
ADD `subject` MEDIUMTEXT NOT NULL,
ADD INDEX ( `created` ), ADD INDEX ( `updated` ) ");
}
@ -1112,7 +1112,7 @@ function update_1127() {
function update_1128() {
q("alter table spam add `date` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `term` ");
q("alter table spam add `date` DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00' AFTER `term` ");
}
function update_1129() {
@ -1262,7 +1262,7 @@ function update_1144() {
}
function update_1145() {
$r = q("alter table profile add howlong datetime not null default '0000-00-00 00:00:00' after `with`");
$r = q("alter table profile add howlong datetime not null default '0001-01-01 00:00:00' after `with`");
if(! $r)
return UPDATE_FAILED ;
return UPDATE_SUCCESS ;
@ -1562,11 +1562,11 @@ function update_1169() {
`iid` int(10) unsigned NOT NULL DEFAULT '0',
`uid` int(10) unsigned NOT NULL DEFAULT '0',
`contact-id` int(11) unsigned NOT NULL DEFAULT '0',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`edited` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`commented` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`received` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`changed` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`edited` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`commented` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`received` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`changed` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`wall` tinyint(1) NOT NULL DEFAULT '0',
`private` tinyint(1) NOT NULL DEFAULT '0',
`pubmail` tinyint(1) NOT NULL DEFAULT '0',

View file

@ -17,17 +17,46 @@ unset($db_host, $db_user, $db_pass, $db_data);
Config::load();
$maint_mode = 1;
if($argc > 1)
if ($argc > 1) {
$maint_mode = intval($argv[1]);
set_config('system', 'maintenance', $maint_mode);
}
if($maint_mode)
Config::set('system', 'maintenance', $maint_mode);
if ($maint_mode AND ($argc > 2)) {
$reason_arr = $argv;
array_shift($reason_arr);
array_shift($reason_arr);
$reason = implode(' ', $reason_arr);
Config::set('system', 'maintenance_reason', $reason);
} else {
Config::set('system', 'maintenance_reason', '');
}
if ($maint_mode) {
$mode_str = "maintenance mode";
else
} else {
$mode_str = "normal mode";
}
echo "\n\tSystem set in $mode_str\n";
if ($reason != '') {
echo "\tMaintenance reason: $reason\n\n";
} else {
echo "\n";
}
echo "\n\tSystem set in $mode_str\n\n";
echo "Usage:\n\n";
echo "\tphp {$argv[0]} [1]\tSet the system in maintenance mode\n";
echo "\tphp {$argv[0]} 0 \tSet the system in normal mode\n\n";
echo "\tphp {$argv[0]} [1] [Maintenance reason|redirection url]\n";
echo "\t\tSet the system in maintenance mode\n\n";
echo "\t\tIf the optionally entered maintenance reason is an url\n";
echo "\t\tthe visitor is redirected to that page.\n";
echo "\n";
echo "\t\tExamples:\n";
echo "\t\t\tphp {$argv[0]} 1 System upgrade\n";
echo "\t\t\tphp {$argv[0]} 1 http://domain.tld/downtime\n";
echo "\n";
echo "\tphp {$argv[0]} 0\n";
echo "\t\tSet the system in normal mode\n\n";

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-03-03 10:29+0100\n"
"POT-Creation-Date: 2017-03-20 08:24+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"
@ -18,238 +18,132 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
#: include/profile_selectors.php:6
msgid "Male"
#: boot.php:976
msgid "Delete this item?"
msgstr ""
#: include/profile_selectors.php:6
msgid "Female"
#: boot.php:977 include/ForumManager.php:119 include/contact_widgets.php:253
#: include/items.php:2254 mod/content.php:624 object/Item.php:420
#: view/theme/vier/theme.php:255
msgid "show more"
msgstr ""
#: include/profile_selectors.php:6
msgid "Currently Male"
#: boot.php:978
msgid "show fewer"
msgstr ""
#: include/profile_selectors.php:6
msgid "Currently Female"
#: boot.php:1667
#, php-format
msgid "Update %s failed. See error logs."
msgstr ""
#: include/profile_selectors.php:6
msgid "Mostly Male"
#: boot.php:1779
msgid "Create a New Account"
msgstr ""
#: include/profile_selectors.php:6
msgid "Mostly Female"
#: boot.php:1780 include/nav.php:109 mod/register.php:289
msgid "Register"
msgstr ""
#: include/profile_selectors.php:6
msgid "Transgender"
#: boot.php:1804 include/nav.php:78 view/theme/frio/theme.php:243
msgid "Logout"
msgstr ""
#: include/profile_selectors.php:6
msgid "Intersex"
#: boot.php:1805 include/nav.php:95 mod/bookmarklet.php:12
msgid "Login"
msgstr ""
#: include/profile_selectors.php:6
msgid "Transsexual"
#: boot.php:1807 mod/lostpass.php:161
msgid "Nickname or Email: "
msgstr ""
#: include/profile_selectors.php:6
msgid "Hermaphrodite"
#: boot.php:1808
msgid "Password: "
msgstr ""
#: include/profile_selectors.php:6
msgid "Neuter"
#: boot.php:1809
msgid "Remember me"
msgstr ""
#: include/profile_selectors.php:6
msgid "Non-specific"
#: boot.php:1812
msgid "Or login using OpenID: "
msgstr ""
#: include/profile_selectors.php:6
msgid "Other"
#: boot.php:1818
msgid "Forgot your password?"
msgstr ""
#: include/profile_selectors.php:6 include/conversation.php:1478
msgid "Undecided"
msgid_plural "Undecided"
msgstr[0] ""
msgstr[1] ""
#: include/profile_selectors.php:23
msgid "Males"
#: boot.php:1819 mod/lostpass.php:110
msgid "Password Reset"
msgstr ""
#: include/profile_selectors.php:23
msgid "Females"
#: boot.php:1821
msgid "Website Terms of Service"
msgstr ""
#: include/profile_selectors.php:23
msgid "Gay"
#: boot.php:1822
msgid "terms of service"
msgstr ""
#: include/profile_selectors.php:23
msgid "Lesbian"
#: boot.php:1824
msgid "Website Privacy Policy"
msgstr ""
#: include/profile_selectors.php:23
msgid "No Preference"
#: boot.php:1825
msgid "privacy policy"
msgstr ""
#: include/profile_selectors.php:23
msgid "Bisexual"
#: include/Contact.php:387 include/Contact.php:400 include/Contact.php:445
#: include/conversation.php:970 include/conversation.php:986
#: mod/allfriends.php:68 mod/directory.php:157 mod/dirfind.php:209
#: mod/match.php:73 mod/suggest.php:82
msgid "View Profile"
msgstr ""
#: include/profile_selectors.php:23
msgid "Autosexual"
#: include/Contact.php:401 include/contact_widgets.php:32
#: include/conversation.php:983 mod/allfriends.php:69 mod/contacts.php:610
#: mod/dirfind.php:210 mod/follow.php:106 mod/match.php:74 mod/suggest.php:83
msgid "Connect/Follow"
msgstr ""
#: include/profile_selectors.php:23
msgid "Abstinent"
#: include/Contact.php:444 include/conversation.php:969
msgid "View Status"
msgstr ""
#: include/profile_selectors.php:23
msgid "Virgin"
#: include/Contact.php:446 include/conversation.php:971
msgid "View Photos"
msgstr ""
#: include/profile_selectors.php:23
msgid "Deviant"
#: include/Contact.php:447 include/conversation.php:972
msgid "Network Posts"
msgstr ""
#: include/profile_selectors.php:23
msgid "Fetish"
#: include/Contact.php:448 include/conversation.php:973
msgid "View Contact"
msgstr ""
#: include/profile_selectors.php:23
msgid "Oodles"
#: include/Contact.php:449
msgid "Drop Contact"
msgstr ""
#: include/profile_selectors.php:23
msgid "Nonsexual"
#: include/Contact.php:450 include/conversation.php:974
msgid "Send PM"
msgstr ""
#: include/profile_selectors.php:42
msgid "Single"
#: include/Contact.php:451 include/conversation.php:978
msgid "Poke"
msgstr ""
#: include/profile_selectors.php:42
msgid "Lonely"
#: include/Contact.php:828
msgid "Organisation"
msgstr ""
#: include/profile_selectors.php:42
msgid "Available"
#: include/Contact.php:831
msgid "News"
msgstr ""
#: include/profile_selectors.php:42
msgid "Unavailable"
msgstr ""
#: include/profile_selectors.php:42
msgid "Has crush"
msgstr ""
#: include/profile_selectors.php:42
msgid "Infatuated"
msgstr ""
#: include/profile_selectors.php:42
msgid "Dating"
msgstr ""
#: include/profile_selectors.php:42
msgid "Unfaithful"
msgstr ""
#: include/profile_selectors.php:42
msgid "Sex Addict"
msgstr ""
#: include/profile_selectors.php:42 include/user.php:280 include/user.php:284
msgid "Friends"
msgstr ""
#: include/profile_selectors.php:42
msgid "Friends/Benefits"
msgstr ""
#: include/profile_selectors.php:42
msgid "Casual"
msgstr ""
#: include/profile_selectors.php:42
msgid "Engaged"
msgstr ""
#: include/profile_selectors.php:42
msgid "Married"
msgstr ""
#: include/profile_selectors.php:42
msgid "Imaginarily married"
msgstr ""
#: include/profile_selectors.php:42
msgid "Partners"
msgstr ""
#: include/profile_selectors.php:42
msgid "Cohabiting"
msgstr ""
#: include/profile_selectors.php:42
msgid "Common law"
msgstr ""
#: include/profile_selectors.php:42
msgid "Happy"
msgstr ""
#: include/profile_selectors.php:42
msgid "Not looking"
msgstr ""
#: include/profile_selectors.php:42
msgid "Swinger"
msgstr ""
#: include/profile_selectors.php:42
msgid "Betrayed"
msgstr ""
#: include/profile_selectors.php:42
msgid "Separated"
msgstr ""
#: include/profile_selectors.php:42
msgid "Unstable"
msgstr ""
#: include/profile_selectors.php:42
msgid "Divorced"
msgstr ""
#: include/profile_selectors.php:42
msgid "Imaginarily divorced"
msgstr ""
#: include/profile_selectors.php:42
msgid "Widowed"
msgstr ""
#: include/profile_selectors.php:42
msgid "Uncertain"
msgstr ""
#: include/profile_selectors.php:42
msgid "It's complicated"
msgstr ""
#: include/profile_selectors.php:42
msgid "Don't care"
msgstr ""
#: include/profile_selectors.php:42
msgid "Ask me"
#: include/Contact.php:834
msgid "Forum"
msgstr ""
#: include/ForumManager.php:114 include/nav.php:131 include/text.php:1027
@ -261,23 +155,17 @@ msgstr ""
msgid "External link to forum"
msgstr ""
#: include/ForumManager.php:119 include/contact_widgets.php:253
#: include/items.php:2254 mod/content.php:624 object/Item.php:447
#: view/theme/vier/theme.php:255 boot.php:971
msgid "show more"
msgstr ""
#: include/NotificationsManager.php:153
msgid "System"
msgstr ""
#: include/NotificationsManager.php:160 include/nav.php:158 mod/admin.php:412
#: include/NotificationsManager.php:160 include/nav.php:158 mod/admin.php:421
#: view/theme/frio/theme.php:253
msgid "Network"
msgstr ""
#: include/NotificationsManager.php:167 mod/profiles.php:695
#: mod/network.php:846
#: include/NotificationsManager.php:167 mod/network.php:829
#: mod/profiles.php:695
msgid "Personal"
msgstr ""
@ -348,24 +236,101 @@ msgstr ""
msgid "Wall Photos"
msgstr ""
#: include/acl_selectors.php:341
msgid "Post to Email"
msgstr ""
#: include/acl_selectors.php:346
#, php-format
msgid "Connectors disabled, since \"%s\" is enabled."
msgstr ""
#: include/acl_selectors.php:347 mod/settings.php:1188
msgid "Hide your profile details from unknown viewers?"
msgstr ""
#: include/acl_selectors.php:352
msgid "Visible to everybody"
msgstr ""
#: include/acl_selectors.php:353 view/theme/vier/config.php:108
msgid "show"
msgstr ""
#: include/acl_selectors.php:354 view/theme/vier/config.php:108
msgid "don't show"
msgstr ""
#: include/acl_selectors.php:360 mod/editpost.php:123
msgid "CC: email addresses"
msgstr ""
#: include/acl_selectors.php:361 mod/editpost.php:130
msgid "Example: bob@example.com, mary@example.com"
msgstr ""
#: include/acl_selectors.php:363 mod/events.php:516 mod/photos.php:1176
#: mod/photos.php:1558
msgid "Permissions"
msgstr ""
#: include/acl_selectors.php:364
msgid "Close"
msgstr ""
#: include/api.php:1021
#, php-format
msgid "Daily posting limit of %d posts reached. The post was rejected."
msgstr ""
#: include/api.php:1041
#, php-format
msgid "Weekly posting limit of %d posts reached. The post was rejected."
msgstr ""
#: include/api.php:1062
#, php-format
msgid "Monthly posting limit of %d posts reached. The post was rejected."
msgstr ""
#: include/auth.php:45
msgid "Logged out."
msgstr ""
#: include/auth.php:116 include/auth.php:177 mod/openid.php:110
#: include/auth.php:116 include/auth.php:178 mod/openid.php:110
msgid "Login failed."
msgstr ""
#: include/auth.php:131 include/user.php:75
#: include/auth.php:132 include/user.php:75
msgid ""
"We encountered a problem while logging in with the OpenID you provided. "
"Please check the correct spelling of the ID."
msgstr ""
#: include/auth.php:131 include/user.php:75
#: include/auth.php:132 include/user.php:75
msgid "The error message was:"
msgstr ""
#: include/bb2diaspora.php:199 include/event.php:16 mod/localtime.php:12
msgid "l F d, Y \\@ g:i A"
msgstr ""
#: include/bb2diaspora.php:205 include/event.php:33 include/event.php:51
#: include/event.php:488
msgid "Starts:"
msgstr ""
#: include/bb2diaspora.php:213 include/event.php:36 include/event.php:57
#: include/event.php:489
msgid "Finishes:"
msgstr ""
#: include/bb2diaspora.php:221 include/event.php:39 include/event.php:63
#: include/event.php:490 include/identity.php:331 mod/contacts.php:636
#: mod/directory.php:139 mod/events.php:501 mod/notifications.php:238
msgid "Location:"
msgstr ""
#: include/bbcode.php:350 include/bbcode.php:1055 include/bbcode.php:1056
msgid "Image/photo"
msgstr ""
@ -383,19 +348,789 @@ msgstr ""
msgid "Encrypted content"
msgstr ""
#: include/bbcode.php:1167
#: include/bbcode.php:1169
msgid "Invalid source protocol"
msgstr ""
#: include/bbcode.php:1177
#: include/bbcode.php:1179
msgid "Invalid link protocol"
msgstr ""
#: include/dba_pdo.php:72 include/dba.php:56
#: include/contact_selectors.php:32
msgid "Unknown | Not categorised"
msgstr ""
#: include/contact_selectors.php:33
msgid "Block immediately"
msgstr ""
#: include/contact_selectors.php:34
msgid "Shady, spammer, self-marketer"
msgstr ""
#: include/contact_selectors.php:35
msgid "Known to me, but no opinion"
msgstr ""
#: include/contact_selectors.php:36
msgid "OK, probably harmless"
msgstr ""
#: include/contact_selectors.php:37
msgid "Reputable, has my trust"
msgstr ""
#: include/contact_selectors.php:56 mod/admin.php:893
msgid "Frequently"
msgstr ""
#: include/contact_selectors.php:57 mod/admin.php:894
msgid "Hourly"
msgstr ""
#: include/contact_selectors.php:58 mod/admin.php:895
msgid "Twice daily"
msgstr ""
#: include/contact_selectors.php:59 mod/admin.php:896
msgid "Daily"
msgstr ""
#: include/contact_selectors.php:60
msgid "Weekly"
msgstr ""
#: include/contact_selectors.php:61
msgid "Monthly"
msgstr ""
#: include/contact_selectors.php:76 mod/dfrn_request.php:881
msgid "Friendica"
msgstr ""
#: include/contact_selectors.php:77
msgid "OStatus"
msgstr ""
#: include/contact_selectors.php:78
msgid "RSS/Atom"
msgstr ""
#: include/contact_selectors.php:79 include/contact_selectors.php:86
#: mod/admin.php:1405 mod/admin.php:1418 mod/admin.php:1431 mod/admin.php:1449
msgid "Email"
msgstr ""
#: include/contact_selectors.php:80 mod/dfrn_request.php:883
#: mod/settings.php:848
msgid "Diaspora"
msgstr ""
#: include/contact_selectors.php:81
msgid "Facebook"
msgstr ""
#: include/contact_selectors.php:82
msgid "Zot!"
msgstr ""
#: include/contact_selectors.php:83
msgid "LinkedIn"
msgstr ""
#: include/contact_selectors.php:84
msgid "XMPP/IM"
msgstr ""
#: include/contact_selectors.php:85
msgid "MySpace"
msgstr ""
#: include/contact_selectors.php:87
msgid "Google+"
msgstr ""
#: include/contact_selectors.php:88
msgid "pump.io"
msgstr ""
#: include/contact_selectors.php:89
msgid "Twitter"
msgstr ""
#: include/contact_selectors.php:90
msgid "Diaspora Connector"
msgstr ""
#: include/contact_selectors.php:91
msgid "GNU Social"
msgstr ""
#: include/contact_selectors.php:92
msgid "pnut"
msgstr ""
#: include/contact_selectors.php:93
msgid "App.net"
msgstr ""
#: include/contact_selectors.php:104
msgid "Hubzilla/Redmatrix"
msgstr ""
#: include/contact_widgets.php:6
msgid "Add New Contact"
msgstr ""
#: include/contact_widgets.php:7
msgid "Enter address or web location"
msgstr ""
#: include/contact_widgets.php:8
msgid "Example: bob@example.com, http://example.com/barbara"
msgstr ""
#: include/contact_widgets.php:10 include/identity.php:219
#: mod/allfriends.php:85 mod/dirfind.php:207 mod/match.php:89
#: mod/suggest.php:101
msgid "Connect"
msgstr ""
#: include/contact_widgets.php:24
#, php-format
msgid "%d invitation available"
msgid_plural "%d invitations available"
msgstr[0] ""
msgstr[1] ""
#: include/contact_widgets.php:30
msgid "Find People"
msgstr ""
#: include/contact_widgets.php:31
msgid "Enter name or interest"
msgstr ""
#: include/contact_widgets.php:33
msgid "Examples: Robert Morgenstein, Fishing"
msgstr ""
#: include/contact_widgets.php:34 mod/contacts.php:806 mod/directory.php:206
msgid "Find"
msgstr ""
#: include/contact_widgets.php:35 mod/suggest.php:114
#: view/theme/vier/theme.php:198
msgid "Friend Suggestions"
msgstr ""
#: include/contact_widgets.php:36 view/theme/vier/theme.php:197
msgid "Similar Interests"
msgstr ""
#: include/contact_widgets.php:37
msgid "Random Profile"
msgstr ""
#: include/contact_widgets.php:38 view/theme/vier/theme.php:199
msgid "Invite Friends"
msgstr ""
#: include/contact_widgets.php:115
msgid "Networks"
msgstr ""
#: include/contact_widgets.php:118
msgid "All Networks"
msgstr ""
#: include/contact_widgets.php:150 include/features.php:104
msgid "Saved Folders"
msgstr ""
#: include/contact_widgets.php:153 include/contact_widgets.php:187
msgid "Everything"
msgstr ""
#: include/contact_widgets.php:184
msgid "Categories"
msgstr ""
#: include/contact_widgets.php:248
#, php-format
msgid "%d contact in common"
msgid_plural "%d contacts in common"
msgstr[0] ""
msgstr[1] ""
#: include/conversation.php:122 include/conversation.php:258
#: include/like.php:180 include/text.php:1804
msgid "event"
msgstr ""
#: include/conversation.php:125 include/conversation.php:134
#: include/conversation.php:261 include/conversation.php:270
#: include/diaspora.php:1530 include/like.php:178 mod/subthread.php:88
#: mod/tagger.php:62
msgid "status"
msgstr ""
#: include/conversation.php:130 include/conversation.php:266
#: include/like.php:178 include/text.php:1806 mod/subthread.php:88
#: mod/tagger.php:62
msgid "photo"
msgstr ""
#: include/conversation.php:141 include/diaspora.php:1526 include/like.php:27
#, php-format
msgid "%1$s likes %2$s's %3$s"
msgstr ""
#: include/conversation.php:144 include/like.php:31 include/like.php:36
#, php-format
msgid "%1$s doesn't like %2$s's %3$s"
msgstr ""
#: include/conversation.php:147
#, php-format
msgid "%1$s attends %2$s's %3$s"
msgstr ""
#: include/conversation.php:150
#, php-format
msgid "%1$s doesn't attend %2$s's %3$s"
msgstr ""
#: include/conversation.php:153
#, php-format
msgid "%1$s attends maybe %2$s's %3$s"
msgstr ""
#: include/conversation.php:185 mod/dfrn_confirm.php:478
#, php-format
msgid "%1$s is now friends with %2$s"
msgstr ""
#: include/conversation.php:219
#, php-format
msgid "%1$s poked %2$s"
msgstr ""
#: include/conversation.php:239 mod/mood.php:63
#, php-format
msgid "%1$s is currently %2$s"
msgstr ""
#: include/conversation.php:278 mod/tagger.php:95
#, php-format
msgid "%1$s tagged %2$s's %3$s with %4$s"
msgstr ""
#: include/conversation.php:303
msgid "post/item"
msgstr ""
#: include/conversation.php:304
#, php-format
msgid "%1$s marked %2$s's %3$s as favorite"
msgstr ""
#: include/conversation.php:587 mod/content.php:372 mod/photos.php:1629
#: mod/profiles.php:346
msgid "Likes"
msgstr ""
#: include/conversation.php:587 mod/content.php:372 mod/photos.php:1629
#: mod/profiles.php:350
msgid "Dislikes"
msgstr ""
#: include/conversation.php:588 include/conversation.php:1473
#: mod/content.php:373 mod/photos.php:1630
msgid "Attending"
msgid_plural "Attending"
msgstr[0] ""
msgstr[1] ""
#: include/conversation.php:588 mod/content.php:373 mod/photos.php:1630
msgid "Not attending"
msgstr ""
#: include/conversation.php:588 mod/content.php:373 mod/photos.php:1630
msgid "Might attend"
msgstr ""
#: include/conversation.php:710 mod/content.php:453 mod/content.php:759
#: mod/photos.php:1703 object/Item.php:137
msgid "Select"
msgstr ""
#: include/conversation.php:711 mod/admin.php:1423 mod/contacts.php:816
#: mod/contacts.php:1015 mod/content.php:454 mod/content.php:760
#: mod/group.php:181 mod/photos.php:1704 mod/settings.php:744
#: object/Item.php:138
msgid "Delete"
msgstr ""
#: include/conversation.php:755 mod/content.php:487 mod/content.php:915
#: mod/content.php:916 object/Item.php:356 object/Item.php:357
#, php-format
msgid "View %s's profile @ %s"
msgstr ""
#: include/conversation.php:767 object/Item.php:344
msgid "Categories:"
msgstr ""
#: include/conversation.php:768 object/Item.php:345
msgid "Filed under:"
msgstr ""
#: include/conversation.php:775 mod/content.php:497 mod/content.php:928
#: object/Item.php:370
#, php-format
msgid "%s from %s"
msgstr ""
#: include/conversation.php:791 mod/content.php:513
msgid "View in context"
msgstr ""
#: include/conversation.php:793 include/conversation.php:1256
#: mod/content.php:515 mod/content.php:953 mod/editpost.php:114
#: mod/message.php:337 mod/message.php:522 mod/photos.php:1592
#: mod/wallmessage.php:140 object/Item.php:395
msgid "Please wait"
msgstr ""
#: include/conversation.php:872
msgid "remove"
msgstr ""
#: include/conversation.php:876
msgid "Delete Selected Items"
msgstr ""
#: include/conversation.php:968
msgid "Follow Thread"
msgstr ""
#: include/conversation.php:1100
#, php-format
msgid "%s likes this."
msgstr ""
#: include/conversation.php:1103
#, php-format
msgid "%s doesn't like this."
msgstr ""
#: include/conversation.php:1106
#, php-format
msgid "%s attends."
msgstr ""
#: include/conversation.php:1109
#, php-format
msgid "%s doesn't attend."
msgstr ""
#: include/conversation.php:1112
#, php-format
msgid "%s attends maybe."
msgstr ""
#: include/conversation.php:1122
msgid "and"
msgstr ""
#: include/conversation.php:1128
#, php-format
msgid ", and %d other people"
msgstr ""
#: include/conversation.php:1137
#, php-format
msgid "<span %1$s>%2$d people</span> like this"
msgstr ""
#: include/conversation.php:1138
#, php-format
msgid "%s like this."
msgstr ""
#: include/conversation.php:1141
#, php-format
msgid "<span %1$s>%2$d people</span> don't like this"
msgstr ""
#: include/conversation.php:1142
#, php-format
msgid "%s don't like this."
msgstr ""
#: include/conversation.php:1145
#, php-format
msgid "<span %1$s>%2$d people</span> attend"
msgstr ""
#: include/conversation.php:1146
#, php-format
msgid "%s attend."
msgstr ""
#: include/conversation.php:1149
#, php-format
msgid "<span %1$s>%2$d people</span> don't attend"
msgstr ""
#: include/conversation.php:1150
#, php-format
msgid "%s don't attend."
msgstr ""
#: include/conversation.php:1153
#, php-format
msgid "<span %1$s>%2$d people</span> attend maybe"
msgstr ""
#: include/conversation.php:1154
#, php-format
msgid "%s anttend maybe."
msgstr ""
#: include/conversation.php:1184 include/conversation.php:1200
msgid "Visible to <strong>everybody</strong>"
msgstr ""
#: include/conversation.php:1185 include/conversation.php:1201
#: mod/message.php:271 mod/message.php:278 mod/message.php:418
#: mod/message.php:425 mod/wallmessage.php:114 mod/wallmessage.php:121
msgid "Please enter a link URL:"
msgstr ""
#: include/conversation.php:1186 include/conversation.php:1202
msgid "Please enter a video link/URL:"
msgstr ""
#: include/conversation.php:1187 include/conversation.php:1203
msgid "Please enter an audio link/URL:"
msgstr ""
#: include/conversation.php:1188 include/conversation.php:1204
msgid "Tag term:"
msgstr ""
#: include/conversation.php:1189 include/conversation.php:1205
#: mod/filer.php:30
msgid "Save to Folder:"
msgstr ""
#: include/conversation.php:1190 include/conversation.php:1206
msgid "Where are you right now?"
msgstr ""
#: include/conversation.php:1191
msgid "Delete item(s)?"
msgstr ""
#: include/conversation.php:1237
msgid "Share"
msgstr ""
#: include/conversation.php:1238 mod/editpost.php:100 mod/message.php:335
#: mod/message.php:519 mod/wallmessage.php:138
msgid "Upload photo"
msgstr ""
#: include/conversation.php:1239 mod/editpost.php:101
msgid "upload photo"
msgstr ""
#: include/conversation.php:1240 mod/editpost.php:102
msgid "Attach file"
msgstr ""
#: include/conversation.php:1241 mod/editpost.php:103
msgid "attach file"
msgstr ""
#: include/conversation.php:1242 mod/editpost.php:104 mod/message.php:336
#: mod/message.php:520 mod/wallmessage.php:139
msgid "Insert web link"
msgstr ""
#: include/conversation.php:1243 mod/editpost.php:105
msgid "web link"
msgstr ""
#: include/conversation.php:1244 mod/editpost.php:106
msgid "Insert video link"
msgstr ""
#: include/conversation.php:1245 mod/editpost.php:107
msgid "video link"
msgstr ""
#: include/conversation.php:1246 mod/editpost.php:108
msgid "Insert audio link"
msgstr ""
#: include/conversation.php:1247 mod/editpost.php:109
msgid "audio link"
msgstr ""
#: include/conversation.php:1248 mod/editpost.php:110
msgid "Set your location"
msgstr ""
#: include/conversation.php:1249 mod/editpost.php:111
msgid "set location"
msgstr ""
#: include/conversation.php:1250 mod/editpost.php:112
msgid "Clear browser location"
msgstr ""
#: include/conversation.php:1251 mod/editpost.php:113
msgid "clear location"
msgstr ""
#: include/conversation.php:1253 mod/editpost.php:127
msgid "Set title"
msgstr ""
#: include/conversation.php:1255 mod/editpost.php:129
msgid "Categories (comma-separated list)"
msgstr ""
#: include/conversation.php:1257 mod/editpost.php:115
msgid "Permission settings"
msgstr ""
#: include/conversation.php:1258 mod/editpost.php:144
msgid "permissions"
msgstr ""
#: include/conversation.php:1266 mod/editpost.php:124
msgid "Public post"
msgstr ""
#: include/conversation.php:1271 mod/content.php:737 mod/editpost.php:135
#: mod/events.php:511 mod/photos.php:1613 mod/photos.php:1661
#: mod/photos.php:1747 object/Item.php:714
msgid "Preview"
msgstr ""
#: include/conversation.php:1275 include/items.php:1983 mod/contacts.php:455
#: mod/dfrn_request.php:889 mod/editpost.php:138 mod/fbrowser.php:100
#: mod/fbrowser.php:135 mod/follow.php:124 mod/message.php:209
#: mod/photos.php:240 mod/photos.php:331 mod/settings.php:682
#: mod/settings.php:708 mod/suggest.php:32 mod/tagrm.php:11 mod/tagrm.php:96
#: mod/videos.php:132
msgid "Cancel"
msgstr ""
#: include/conversation.php:1281
msgid "Post to Groups"
msgstr ""
#: include/conversation.php:1282
msgid "Post to Contacts"
msgstr ""
#: include/conversation.php:1283
msgid "Private post"
msgstr ""
#: include/conversation.php:1288 include/identity.php:259 mod/editpost.php:142
msgid "Message"
msgstr ""
#: include/conversation.php:1289 mod/editpost.php:143
msgid "Browser"
msgstr ""
#: include/conversation.php:1445
msgid "View all"
msgstr ""
#: include/conversation.php:1467
msgid "Like"
msgid_plural "Likes"
msgstr[0] ""
msgstr[1] ""
#: include/conversation.php:1470
msgid "Dislike"
msgid_plural "Dislikes"
msgstr[0] ""
msgstr[1] ""
#: include/conversation.php:1476
msgid "Not Attending"
msgid_plural "Not Attending"
msgstr[0] ""
msgstr[1] ""
#: include/conversation.php:1479 include/profile_selectors.php:6
msgid "Undecided"
msgid_plural "Undecided"
msgstr[0] ""
msgstr[1] ""
#: include/datetime.php:58 include/datetime.php:60 mod/profiles.php:697
msgid "Miscellaneous"
msgstr ""
#: include/datetime.php:184 include/identity.php:641
msgid "Birthday:"
msgstr ""
#: include/datetime.php:186 mod/profiles.php:720
msgid "Age: "
msgstr ""
#: include/datetime.php:188
msgid "YYYY-MM-DD or MM-DD"
msgstr ""
#: include/datetime.php:343
msgid "never"
msgstr ""
#: include/datetime.php:349
msgid "less than a second ago"
msgstr ""
#: include/datetime.php:352
msgid "year"
msgstr ""
#: include/datetime.php:352
msgid "years"
msgstr ""
#: include/datetime.php:353 include/event.php:481 mod/cal.php:279
#: mod/events.php:396
msgid "month"
msgstr ""
#: include/datetime.php:353
msgid "months"
msgstr ""
#: include/datetime.php:354 include/event.php:482 mod/cal.php:280
#: mod/events.php:397
msgid "week"
msgstr ""
#: include/datetime.php:354
msgid "weeks"
msgstr ""
#: include/datetime.php:355 include/event.php:483 mod/cal.php:281
#: mod/events.php:398
msgid "day"
msgstr ""
#: include/datetime.php:355
msgid "days"
msgstr ""
#: include/datetime.php:356
msgid "hour"
msgstr ""
#: include/datetime.php:356
msgid "hours"
msgstr ""
#: include/datetime.php:357
msgid "minute"
msgstr ""
#: include/datetime.php:357
msgid "minutes"
msgstr ""
#: include/datetime.php:358
msgid "second"
msgstr ""
#: include/datetime.php:358
msgid "seconds"
msgstr ""
#: include/datetime.php:367
#, php-format
msgid "%1$d %2$s ago"
msgstr ""
#: include/datetime.php:585
#, php-format
msgid "%s's birthday"
msgstr ""
#: include/datetime.php:586 include/dfrn.php:1131
#, php-format
msgid "Happy Birthday %s"
msgstr ""
#: include/dba.php:43 include/dba_pdo.php:72
#, php-format
msgid "Cannot locate DNS info for database server '%s'"
msgstr ""
#: include/dbstructure.php:36
#, php-format
msgid ""
"\n"
"\t\t\tThe friendica developers released update %s recently,\n"
"\t\t\tbut when I tried to install it, something went terribly wrong.\n"
"\t\t\tThis needs to be fixed soon and I can't do it alone. Please contact a\n"
"\t\t\tfriendica developer if you can not help me on your own. My database "
"might be invalid."
msgstr ""
#: include/dbstructure.php:41
#, php-format
msgid ""
"The error message is\n"
"[pre]%s[/pre]"
msgstr ""
#: include/dbstructure.php:199
msgid "Errors encountered creating database tables."
msgstr ""
#: include/dbstructure.php:333 include/dbstructure.php:341
#: include/dbstructure.php:349 include/dbstructure.php:354
#: include/dbstructure.php:359
msgid "Errors encountered performing database changes."
msgstr ""
#: include/delivery.php:427
msgid "(no subject)"
msgstr ""
#: include/delivery.php:439 include/enotify.php:43
msgid "noreply"
msgstr ""
#: include/dfrn.php:1130
#, php-format
msgid "%s\\'s birthday"
msgstr ""
#: include/diaspora.php:2087
msgid "Sharing notification from Diaspora network"
msgstr ""
#: include/diaspora.php:3096
msgid "Attachments:"
msgstr ""
#: include/enotify.php:24
msgid "Friendica Notification"
msgstr ""
@ -414,10 +1149,6 @@ msgstr ""
msgid "%1$s, %2$s Administrator"
msgstr ""
#: include/enotify.php:43 include/delivery.php:482
msgid "noreply"
msgstr ""
#: include/enotify.php:70
#, php-format
msgid "%s <!item_type!>"
@ -692,1455 +1423,6 @@ msgstr ""
msgid "Please visit %s to approve or reject the request."
msgstr ""
#: include/follow.php:81 mod/dfrn_request.php:512
msgid "Disallowed profile URL."
msgstr ""
#: include/follow.php:86
msgid "Connect URL missing."
msgstr ""
#: include/follow.php:114
msgid ""
"This site is not configured to allow communications with other networks."
msgstr ""
#: include/follow.php:115 include/follow.php:129
msgid "No compatible communication protocols or feeds were discovered."
msgstr ""
#: include/follow.php:127
msgid "The profile address specified does not provide adequate information."
msgstr ""
#: include/follow.php:132
msgid "An author or name was not found."
msgstr ""
#: include/follow.php:135
msgid "No browser URL could be matched to this address."
msgstr ""
#: include/follow.php:138
msgid ""
"Unable to match @-style Identity Address with a known protocol or email "
"contact."
msgstr ""
#: include/follow.php:139
msgid "Use mailto: in front of address to force email check."
msgstr ""
#: include/follow.php:145
msgid ""
"The profile address specified belongs to a network which has been disabled "
"on this site."
msgstr ""
#: include/follow.php:150
msgid ""
"Limited profile. This person will be unable to receive direct/personal "
"notifications from you."
msgstr ""
#: include/follow.php:251
msgid "Unable to retrieve contact information."
msgstr ""
#: include/group.php:25
msgid ""
"A deleted group with this name was revived. Existing item permissions "
"<strong>may</strong> apply to this group and any future members. If this is "
"not what you intended, please create another group with a different name."
msgstr ""
#: include/group.php:210
msgid "Default privacy group for new contacts"
msgstr ""
#: include/group.php:243
msgid "Everybody"
msgstr ""
#: include/group.php:266
msgid "edit"
msgstr ""
#: include/group.php:287 mod/newmember.php:61
msgid "Groups"
msgstr ""
#: include/group.php:289
msgid "Edit groups"
msgstr ""
#: include/group.php:291
msgid "Edit group"
msgstr ""
#: include/group.php:292
msgid "Create a new group"
msgstr ""
#: include/group.php:293 mod/group.php:98 mod/group.php:188
msgid "Group Name: "
msgstr ""
#: include/group.php:295
msgid "Contacts not in any group"
msgstr ""
#: include/group.php:297 mod/network.php:200
msgid "add"
msgstr ""
#: include/like.php:164 include/conversation.php:130
#: include/conversation.php:266 include/text.php:1806 mod/subthread.php:88
#: mod/tagger.php:62
msgid "photo"
msgstr ""
#: include/like.php:164 include/conversation.php:125
#: include/conversation.php:134 include/conversation.php:261
#: include/conversation.php:270 include/diaspora.php:1530 mod/subthread.php:88
#: mod/tagger.php:62
msgid "status"
msgstr ""
#: include/like.php:166 include/conversation.php:122
#: include/conversation.php:258 include/text.php:1804
msgid "event"
msgstr ""
#: include/like.php:184 include/conversation.php:141 include/diaspora.php:1526
#, php-format
msgid "%1$s likes %2$s's %3$s"
msgstr ""
#: include/like.php:187 include/conversation.php:144
#, php-format
msgid "%1$s doesn't like %2$s's %3$s"
msgstr ""
#: include/like.php:190
#, php-format
msgid "%1$s is attending %2$s's %3$s"
msgstr ""
#: include/like.php:193
#, php-format
msgid "%1$s is not attending %2$s's %3$s"
msgstr ""
#: include/like.php:196
#, php-format
msgid "%1$s may attend %2$s's %3$s"
msgstr ""
#: include/message.php:15 include/message.php:169
msgid "[no subject]"
msgstr ""
#: include/nav.php:35 mod/navigation.php:19
msgid "Nothing new here"
msgstr ""
#: include/nav.php:39 mod/navigation.php:23
msgid "Clear notifications"
msgstr ""
#: include/nav.php:40 include/text.php:1017
msgid "@name, !forum, #tags, content"
msgstr ""
#: include/nav.php:78 view/theme/frio/theme.php:243 boot.php:1833
msgid "Logout"
msgstr ""
#: include/nav.php:78 view/theme/frio/theme.php:243
msgid "End this session"
msgstr ""
#: include/nav.php:81 include/identity.php:766 mod/contacts.php:645
#: mod/contacts.php:841 view/theme/frio/theme.php:246
msgid "Status"
msgstr ""
#: include/nav.php:81 include/nav.php:161 view/theme/frio/theme.php:246
msgid "Your posts and conversations"
msgstr ""
#: include/nav.php:82 include/identity.php:617 include/identity.php:741
#: include/identity.php:774 mod/newmember.php:32 mod/profperm.php:105
#: mod/contacts.php:647 mod/contacts.php:849 view/theme/frio/theme.php:247
msgid "Profile"
msgstr ""
#: include/nav.php:82 view/theme/frio/theme.php:247
msgid "Your profile page"
msgstr ""
#: include/nav.php:83 include/identity.php:782 mod/fbrowser.php:31
#: view/theme/frio/theme.php:248
msgid "Photos"
msgstr ""
#: include/nav.php:83 view/theme/frio/theme.php:248
msgid "Your photos"
msgstr ""
#: include/nav.php:84 include/identity.php:790 include/identity.php:793
#: view/theme/frio/theme.php:249
msgid "Videos"
msgstr ""
#: include/nav.php:84 view/theme/frio/theme.php:249
msgid "Your videos"
msgstr ""
#: include/nav.php:85 include/nav.php:149 include/identity.php:802
#: include/identity.php:813 mod/cal.php:270 mod/events.php:386
#: view/theme/frio/theme.php:250 view/theme/frio/theme.php:254
msgid "Events"
msgstr ""
#: include/nav.php:85 view/theme/frio/theme.php:250
msgid "Your events"
msgstr ""
#: include/nav.php:86
msgid "Personal notes"
msgstr ""
#: include/nav.php:86
msgid "Your personal notes"
msgstr ""
#: include/nav.php:95 mod/bookmarklet.php:12 boot.php:1834
msgid "Login"
msgstr ""
#: include/nav.php:95
msgid "Sign in"
msgstr ""
#: include/nav.php:105
msgid "Home Page"
msgstr ""
#: include/nav.php:109 mod/register.php:289 boot.php:1809
msgid "Register"
msgstr ""
#: include/nav.php:109
msgid "Create an account"
msgstr ""
#: include/nav.php:115 mod/help.php:47 view/theme/vier/theme.php:293
msgid "Help"
msgstr ""
#: include/nav.php:115
msgid "Help and documentation"
msgstr ""
#: include/nav.php:119
msgid "Apps"
msgstr ""
#: include/nav.php:119
msgid "Addon applications, utilities, games"
msgstr ""
#: include/nav.php:123 include/text.php:1014 mod/search.php:149
msgid "Search"
msgstr ""
#: include/nav.php:123
msgid "Search site content"
msgstr ""
#: include/nav.php:126 include/text.php:1022
msgid "Full Text"
msgstr ""
#: include/nav.php:127 include/text.php:1023
msgid "Tags"
msgstr ""
#: include/nav.php:128 include/nav.php:192 include/identity.php:835
#: include/identity.php:838 include/text.php:1024 mod/contacts.php:800
#: mod/contacts.php:861 mod/viewcontacts.php:121 view/theme/frio/theme.php:257
msgid "Contacts"
msgstr ""
#: include/nav.php:143 include/nav.php:145 mod/community.php:36
msgid "Community"
msgstr ""
#: include/nav.php:143
msgid "Conversations on this site"
msgstr ""
#: include/nav.php:145
msgid "Conversations on the network"
msgstr ""
#: include/nav.php:149 include/identity.php:805 include/identity.php:816
#: view/theme/frio/theme.php:254
msgid "Events and Calendar"
msgstr ""
#: include/nav.php:152
msgid "Directory"
msgstr ""
#: include/nav.php:152
msgid "People directory"
msgstr ""
#: include/nav.php:154
msgid "Information"
msgstr ""
#: include/nav.php:154
msgid "Information about this friendica instance"
msgstr ""
#: include/nav.php:158 view/theme/frio/theme.php:253
msgid "Conversations from your friends"
msgstr ""
#: include/nav.php:159
msgid "Network Reset"
msgstr ""
#: include/nav.php:159
msgid "Load Network page with no filters"
msgstr ""
#: include/nav.php:166
msgid "Friend Requests"
msgstr ""
#: include/nav.php:169 mod/notifications.php:96
msgid "Notifications"
msgstr ""
#: include/nav.php:170
msgid "See all notifications"
msgstr ""
#: include/nav.php:171 mod/settings.php:906
msgid "Mark as seen"
msgstr ""
#: include/nav.php:171
msgid "Mark all system notifications seen"
msgstr ""
#: include/nav.php:175 mod/message.php:179 view/theme/frio/theme.php:255
msgid "Messages"
msgstr ""
#: include/nav.php:175 view/theme/frio/theme.php:255
msgid "Private mail"
msgstr ""
#: include/nav.php:176
msgid "Inbox"
msgstr ""
#: include/nav.php:177
msgid "Outbox"
msgstr ""
#: include/nav.php:178 mod/message.php:16
msgid "New Message"
msgstr ""
#: include/nav.php:181
msgid "Manage"
msgstr ""
#: include/nav.php:181
msgid "Manage other pages"
msgstr ""
#: include/nav.php:184 mod/settings.php:81
msgid "Delegations"
msgstr ""
#: include/nav.php:184 mod/delegate.php:130
msgid "Delegate Page Management"
msgstr ""
#: include/nav.php:186 mod/newmember.php:22 mod/settings.php:111
#: mod/admin.php:1545 mod/admin.php:1815 view/theme/frio/theme.php:256
msgid "Settings"
msgstr ""
#: include/nav.php:186 view/theme/frio/theme.php:256
msgid "Account settings"
msgstr ""
#: include/nav.php:189 include/identity.php:285
msgid "Profiles"
msgstr ""
#: include/nav.php:189
msgid "Manage/Edit Profiles"
msgstr ""
#: include/nav.php:192 view/theme/frio/theme.php:257
msgid "Manage/edit friends and contacts"
msgstr ""
#: include/nav.php:197 mod/admin.php:187
msgid "Admin"
msgstr ""
#: include/nav.php:197
msgid "Site setup and configuration"
msgstr ""
#: include/nav.php:200
msgid "Navigation"
msgstr ""
#: include/nav.php:200
msgid "Site map"
msgstr ""
#: include/oembed.php:266
msgid "Embedded content"
msgstr ""
#: include/oembed.php:274
msgid "Embedding disabled"
msgstr ""
#: include/ostatus.php:1832
#, php-format
msgid "%s is now following %s."
msgstr ""
#: include/ostatus.php:1833
msgid "following"
msgstr ""
#: include/ostatus.php:1836
#, php-format
msgid "%s stopped following %s."
msgstr ""
#: include/ostatus.php:1837
msgid "stopped following"
msgstr ""
#: include/plugin.php:530 include/plugin.php:532
msgid "Click here to upgrade."
msgstr ""
#: include/plugin.php:538
msgid "This action exceeds the limits set by your subscription plan."
msgstr ""
#: include/plugin.php:543
msgid "This action is not available under your subscription plan."
msgstr ""
#: include/security.php:22
msgid "Welcome "
msgstr ""
#: include/security.php:23
msgid "Please upload a profile photo."
msgstr ""
#: include/security.php:26
msgid "Welcome back "
msgstr ""
#: include/security.php:375
msgid ""
"The form security token was not correct. This probably happened because the "
"form has been opened for too long (>3 hours) before submitting it."
msgstr ""
#: include/uimport.php:94
msgid "Error decoding account file"
msgstr ""
#: include/uimport.php:100
msgid "Error! No version data in file! This is not a Friendica account file?"
msgstr ""
#: include/uimport.php:116 include/uimport.php:127
msgid "Error! Cannot check nickname"
msgstr ""
#: include/uimport.php:120 include/uimport.php:131
#, php-format
msgid "User '%s' already exists on this server!"
msgstr ""
#: include/uimport.php:153
msgid "User creation error"
msgstr ""
#: include/uimport.php:173
msgid "User profile creation error"
msgstr ""
#: include/uimport.php:222
#, php-format
msgid "%d contact not imported"
msgid_plural "%d contacts not imported"
msgstr[0] ""
msgstr[1] ""
#: include/uimport.php:292
msgid "Done. You can now login with your username and password"
msgstr ""
#: include/user.php:39 mod/settings.php:375
msgid "Passwords do not match. Password unchanged."
msgstr ""
#: include/user.php:48
msgid "An invitation is required."
msgstr ""
#: include/user.php:53
msgid "Invitation could not be verified."
msgstr ""
#: include/user.php:61
msgid "Invalid OpenID url"
msgstr ""
#: include/user.php:82
msgid "Please enter the required information."
msgstr ""
#: include/user.php:96
msgid "Please use a shorter name."
msgstr ""
#: include/user.php:98
msgid "Name too short."
msgstr ""
#: include/user.php:113
msgid "That doesn't appear to be your full (First Last) name."
msgstr ""
#: include/user.php:118
msgid "Your email domain is not among those allowed on this site."
msgstr ""
#: include/user.php:121
msgid "Not a valid email address."
msgstr ""
#: include/user.php:134
msgid "Cannot use that email."
msgstr ""
#: include/user.php:140
msgid "Your \"nickname\" can only contain \"a-z\", \"0-9\" and \"_\"."
msgstr ""
#: include/user.php:147 include/user.php:245
msgid "Nickname is already registered. Please choose another."
msgstr ""
#: include/user.php:157
msgid ""
"Nickname was once registered here and may not be re-used. Please choose "
"another."
msgstr ""
#: include/user.php:173
msgid "SERIOUS ERROR: Generation of security keys failed."
msgstr ""
#: include/user.php:231
msgid "An error occurred during registration. Please try again."
msgstr ""
#: include/user.php:256 view/theme/duepuntozero/config.php:43
#: view/theme/clean/config.php:60
msgid "default"
msgstr ""
#: include/user.php:266
msgid "An error occurred creating your default profile. Please try again."
msgstr ""
#: include/user.php:326 include/user.php:334 include/user.php:342
#: mod/profile_photo.php:74 mod/profile_photo.php:82 mod/profile_photo.php:90
#: mod/profile_photo.php:215 mod/profile_photo.php:310
#: mod/profile_photo.php:320 mod/photos.php:68 mod/photos.php:182
#: mod/photos.php:768 mod/photos.php:1231 mod/photos.php:1252
#: mod/photos.php:1839
msgid "Profile Photos"
msgstr ""
#: include/user.php:417
#, php-format
msgid ""
"\n"
"\t\tDear %1$s,\n"
"\t\t\tThank you for registering at %2$s. Your account is pending for "
"approval by the administrator.\n"
"\t"
msgstr ""
#: include/user.php:427
#, php-format
msgid "Registration at %s"
msgstr ""
#: include/user.php:437
#, php-format
msgid ""
"\n"
"\t\tDear %1$s,\n"
"\t\t\tThank you for registering at %2$s. Your account has been created.\n"
"\t"
msgstr ""
#: include/user.php:441
#, php-format
msgid ""
"\n"
"\t\tThe login details are as follows:\n"
"\t\t\tSite Location:\t%3$s\n"
"\t\t\tLogin Name:\t%1$s\n"
"\t\t\tPassword:\t%5$s\n"
"\n"
"\t\tYou may change your password from your account \"Settings\" page after "
"logging\n"
"\t\tin.\n"
"\n"
"\t\tPlease take a few moments to review the other account settings on that "
"page.\n"
"\n"
"\t\tYou may also wish to add some basic information to your default profile\n"
"\t\t(on the \"Profiles\" page) so that other people can easily find you.\n"
"\n"
"\t\tWe recommend setting your full name, adding a profile photo,\n"
"\t\tadding some profile \"keywords\" (very useful in making new friends) - "
"and\n"
"\t\tperhaps what country you live in; if you do not wish to be more "
"specific\n"
"\t\tthan that.\n"
"\n"
"\t\tWe fully respect your right to privacy, and none of these items are "
"necessary.\n"
"\t\tIf you are new and do not know anybody here, they may help\n"
"\t\tyou to make some new and interesting friends.\n"
"\n"
"\n"
"\t\tThank you and welcome to %2$s."
msgstr ""
#: include/user.php:473 mod/admin.php:1234
#, php-format
msgid "Registration details for %s"
msgstr ""
#: include/acl_selectors.php:341
msgid "Post to Email"
msgstr ""
#: include/acl_selectors.php:346
#, php-format
msgid "Connectors disabled, since \"%s\" is enabled."
msgstr ""
#: include/acl_selectors.php:347 mod/settings.php:1188
msgid "Hide your profile details from unknown viewers?"
msgstr ""
#: include/acl_selectors.php:352
msgid "Visible to everybody"
msgstr ""
#: include/acl_selectors.php:353 view/theme/vier/config.php:108
msgid "show"
msgstr ""
#: include/acl_selectors.php:354 view/theme/vier/config.php:108
msgid "don't show"
msgstr ""
#: include/acl_selectors.php:360 mod/editpost.php:123
msgid "CC: email addresses"
msgstr ""
#: include/acl_selectors.php:361 mod/editpost.php:130
msgid "Example: bob@example.com, mary@example.com"
msgstr ""
#: include/acl_selectors.php:363 mod/events.php:516 mod/photos.php:1176
#: mod/photos.php:1558
msgid "Permissions"
msgstr ""
#: include/acl_selectors.php:364
msgid "Close"
msgstr ""
#: include/conversation.php:147
#, php-format
msgid "%1$s attends %2$s's %3$s"
msgstr ""
#: include/conversation.php:150
#, php-format
msgid "%1$s doesn't attend %2$s's %3$s"
msgstr ""
#: include/conversation.php:153
#, php-format
msgid "%1$s attends maybe %2$s's %3$s"
msgstr ""
#: include/conversation.php:185 mod/dfrn_confirm.php:478
#, php-format
msgid "%1$s is now friends with %2$s"
msgstr ""
#: include/conversation.php:219
#, php-format
msgid "%1$s poked %2$s"
msgstr ""
#: include/conversation.php:239 mod/mood.php:63
#, php-format
msgid "%1$s is currently %2$s"
msgstr ""
#: include/conversation.php:278 mod/tagger.php:95
#, php-format
msgid "%1$s tagged %2$s's %3$s with %4$s"
msgstr ""
#: include/conversation.php:303
msgid "post/item"
msgstr ""
#: include/conversation.php:304
#, php-format
msgid "%1$s marked %2$s's %3$s as favorite"
msgstr ""
#: include/conversation.php:587 mod/content.php:372 mod/photos.php:1629
#: mod/profiles.php:346
msgid "Likes"
msgstr ""
#: include/conversation.php:587 mod/content.php:372 mod/photos.php:1629
#: mod/profiles.php:350
msgid "Dislikes"
msgstr ""
#: include/conversation.php:588 include/conversation.php:1472
#: mod/content.php:373 mod/photos.php:1630
msgid "Attending"
msgid_plural "Attending"
msgstr[0] ""
msgstr[1] ""
#: include/conversation.php:588 mod/content.php:373 mod/photos.php:1630
msgid "Not attending"
msgstr ""
#: include/conversation.php:588 mod/content.php:373 mod/photos.php:1630
msgid "Might attend"
msgstr ""
#: include/conversation.php:710 mod/content.php:453 mod/content.php:759
#: mod/photos.php:1703 object/Item.php:137
msgid "Select"
msgstr ""
#: include/conversation.php:711 mod/content.php:454 mod/content.php:760
#: mod/group.php:181 mod/settings.php:744 mod/contacts.php:816
#: mod/contacts.php:1015 mod/photos.php:1704 mod/admin.php:1435
#: object/Item.php:138
msgid "Delete"
msgstr ""
#: include/conversation.php:755 mod/content.php:487 mod/content.php:915
#: mod/content.php:916 object/Item.php:382 object/Item.php:383
#, php-format
msgid "View %s's profile @ %s"
msgstr ""
#: include/conversation.php:767 object/Item.php:370
msgid "Categories:"
msgstr ""
#: include/conversation.php:768 object/Item.php:371
msgid "Filed under:"
msgstr ""
#: include/conversation.php:775 mod/content.php:497 mod/content.php:928
#: object/Item.php:396
#, php-format
msgid "%s from %s"
msgstr ""
#: include/conversation.php:791 mod/content.php:513
msgid "View in context"
msgstr ""
#: include/conversation.php:793 include/conversation.php:1255
#: mod/content.php:515 mod/content.php:953 mod/editpost.php:114
#: mod/message.php:337 mod/message.php:522 mod/wallmessage.php:140
#: mod/photos.php:1592 object/Item.php:421
msgid "Please wait"
msgstr ""
#: include/conversation.php:872
msgid "remove"
msgstr ""
#: include/conversation.php:876
msgid "Delete Selected Items"
msgstr ""
#: include/conversation.php:968
msgid "Follow Thread"
msgstr ""
#: include/conversation.php:969 include/Contact.php:445
msgid "View Status"
msgstr ""
#: include/conversation.php:970 include/conversation.php:986
#: include/Contact.php:388 include/Contact.php:401 include/Contact.php:446
#: mod/allfriends.php:68 mod/directory.php:157 mod/dirfind.php:209
#: mod/match.php:73 mod/suggest.php:82
msgid "View Profile"
msgstr ""
#: include/conversation.php:971 include/Contact.php:447
msgid "View Photos"
msgstr ""
#: include/conversation.php:972 include/Contact.php:448
msgid "Network Posts"
msgstr ""
#: include/conversation.php:973 include/Contact.php:449
msgid "View Contact"
msgstr ""
#: include/conversation.php:974 include/Contact.php:451
msgid "Send PM"
msgstr ""
#: include/conversation.php:978 include/Contact.php:452
msgid "Poke"
msgstr ""
#: include/conversation.php:983 include/contact_widgets.php:32
#: include/Contact.php:402 mod/allfriends.php:69 mod/dirfind.php:210
#: mod/follow.php:106 mod/match.php:74 mod/suggest.php:83 mod/contacts.php:610
msgid "Connect/Follow"
msgstr ""
#: include/conversation.php:1099
#, php-format
msgid "%s likes this."
msgstr ""
#: include/conversation.php:1102
#, php-format
msgid "%s doesn't like this."
msgstr ""
#: include/conversation.php:1105
#, php-format
msgid "%s attends."
msgstr ""
#: include/conversation.php:1108
#, php-format
msgid "%s doesn't attend."
msgstr ""
#: include/conversation.php:1111
#, php-format
msgid "%s attends maybe."
msgstr ""
#: include/conversation.php:1121
msgid "and"
msgstr ""
#: include/conversation.php:1127
#, php-format
msgid ", and %d other people"
msgstr ""
#: include/conversation.php:1136
#, php-format
msgid "<span %1$s>%2$d people</span> like this"
msgstr ""
#: include/conversation.php:1137
#, php-format
msgid "%s like this."
msgstr ""
#: include/conversation.php:1140
#, php-format
msgid "<span %1$s>%2$d people</span> don't like this"
msgstr ""
#: include/conversation.php:1141
#, php-format
msgid "%s don't like this."
msgstr ""
#: include/conversation.php:1144
#, php-format
msgid "<span %1$s>%2$d people</span> attend"
msgstr ""
#: include/conversation.php:1145
#, php-format
msgid "%s attend."
msgstr ""
#: include/conversation.php:1148
#, php-format
msgid "<span %1$s>%2$d people</span> don't attend"
msgstr ""
#: include/conversation.php:1149
#, php-format
msgid "%s don't attend."
msgstr ""
#: include/conversation.php:1152
#, php-format
msgid "<span %1$s>%2$d people</span> attend maybe"
msgstr ""
#: include/conversation.php:1153
#, php-format
msgid "%s anttend maybe."
msgstr ""
#: include/conversation.php:1183 include/conversation.php:1199
msgid "Visible to <strong>everybody</strong>"
msgstr ""
#: include/conversation.php:1184 include/conversation.php:1200
#: mod/message.php:271 mod/message.php:278 mod/message.php:418
#: mod/message.php:425 mod/wallmessage.php:114 mod/wallmessage.php:121
msgid "Please enter a link URL:"
msgstr ""
#: include/conversation.php:1185 include/conversation.php:1201
msgid "Please enter a video link/URL:"
msgstr ""
#: include/conversation.php:1186 include/conversation.php:1202
msgid "Please enter an audio link/URL:"
msgstr ""
#: include/conversation.php:1187 include/conversation.php:1203
msgid "Tag term:"
msgstr ""
#: include/conversation.php:1188 include/conversation.php:1204
#: mod/filer.php:30
msgid "Save to Folder:"
msgstr ""
#: include/conversation.php:1189 include/conversation.php:1205
msgid "Where are you right now?"
msgstr ""
#: include/conversation.php:1190
msgid "Delete item(s)?"
msgstr ""
#: include/conversation.php:1236
msgid "Share"
msgstr ""
#: include/conversation.php:1237 mod/editpost.php:100 mod/message.php:335
#: mod/message.php:519 mod/wallmessage.php:138
msgid "Upload photo"
msgstr ""
#: include/conversation.php:1238 mod/editpost.php:101
msgid "upload photo"
msgstr ""
#: include/conversation.php:1239 mod/editpost.php:102
msgid "Attach file"
msgstr ""
#: include/conversation.php:1240 mod/editpost.php:103
msgid "attach file"
msgstr ""
#: include/conversation.php:1241 mod/editpost.php:104 mod/message.php:336
#: mod/message.php:520 mod/wallmessage.php:139
msgid "Insert web link"
msgstr ""
#: include/conversation.php:1242 mod/editpost.php:105
msgid "web link"
msgstr ""
#: include/conversation.php:1243 mod/editpost.php:106
msgid "Insert video link"
msgstr ""
#: include/conversation.php:1244 mod/editpost.php:107
msgid "video link"
msgstr ""
#: include/conversation.php:1245 mod/editpost.php:108
msgid "Insert audio link"
msgstr ""
#: include/conversation.php:1246 mod/editpost.php:109
msgid "audio link"
msgstr ""
#: include/conversation.php:1247 mod/editpost.php:110
msgid "Set your location"
msgstr ""
#: include/conversation.php:1248 mod/editpost.php:111
msgid "set location"
msgstr ""
#: include/conversation.php:1249 mod/editpost.php:112
msgid "Clear browser location"
msgstr ""
#: include/conversation.php:1250 mod/editpost.php:113
msgid "clear location"
msgstr ""
#: include/conversation.php:1252 mod/editpost.php:127
msgid "Set title"
msgstr ""
#: include/conversation.php:1254 mod/editpost.php:129
msgid "Categories (comma-separated list)"
msgstr ""
#: include/conversation.php:1256 mod/editpost.php:115
msgid "Permission settings"
msgstr ""
#: include/conversation.php:1257 mod/editpost.php:144
msgid "permissions"
msgstr ""
#: include/conversation.php:1265 mod/editpost.php:124
msgid "Public post"
msgstr ""
#: include/conversation.php:1270 mod/content.php:737 mod/editpost.php:135
#: mod/events.php:511 mod/photos.php:1613 mod/photos.php:1661
#: mod/photos.php:1747 object/Item.php:741
msgid "Preview"
msgstr ""
#: include/conversation.php:1274 include/items.php:1983 mod/follow.php:124
#: mod/settings.php:682 mod/settings.php:708 mod/suggest.php:32
#: mod/tagrm.php:11 mod/tagrm.php:96 mod/videos.php:132 mod/contacts.php:455
#: mod/editpost.php:138 mod/fbrowser.php:100 mod/fbrowser.php:135
#: mod/message.php:209 mod/photos.php:240 mod/photos.php:331
#: mod/dfrn_request.php:889
msgid "Cancel"
msgstr ""
#: include/conversation.php:1280
msgid "Post to Groups"
msgstr ""
#: include/conversation.php:1281
msgid "Post to Contacts"
msgstr ""
#: include/conversation.php:1282
msgid "Private post"
msgstr ""
#: include/conversation.php:1287 include/identity.php:259 mod/editpost.php:142
msgid "Message"
msgstr ""
#: include/conversation.php:1288 mod/editpost.php:143
msgid "Browser"
msgstr ""
#: include/conversation.php:1444
msgid "View all"
msgstr ""
#: include/conversation.php:1466
msgid "Like"
msgid_plural "Likes"
msgstr[0] ""
msgstr[1] ""
#: include/conversation.php:1469
msgid "Dislike"
msgid_plural "Dislikes"
msgstr[0] ""
msgstr[1] ""
#: include/conversation.php:1475
msgid "Not Attending"
msgid_plural "Not Attending"
msgstr[0] ""
msgstr[1] ""
#: include/delivery.php:470
msgid "(no subject)"
msgstr ""
#: include/features.php:65
msgid "General Features"
msgstr ""
#: include/features.php:67
msgid "Multiple Profiles"
msgstr ""
#: include/features.php:67
msgid "Ability to create multiple profiles"
msgstr ""
#: include/features.php:68
msgid "Photo Location"
msgstr ""
#: include/features.php:68
msgid ""
"Photo metadata is normally stripped. This extracts the location (if present) "
"prior to stripping metadata and links it to a map."
msgstr ""
#: include/features.php:69
msgid "Export Public Calendar"
msgstr ""
#: include/features.php:69
msgid "Ability for visitors to download the public calendar"
msgstr ""
#: include/features.php:74
msgid "Post Composition Features"
msgstr ""
#: include/features.php:75
msgid "Post Preview"
msgstr ""
#: include/features.php:75
msgid "Allow previewing posts and comments before publishing them"
msgstr ""
#: include/features.php:76
msgid "Auto-mention Forums"
msgstr ""
#: include/features.php:76
msgid ""
"Add/remove mention when a forum page is selected/deselected in ACL window."
msgstr ""
#: include/features.php:81
msgid "Network Sidebar Widgets"
msgstr ""
#: include/features.php:82
msgid "Search by Date"
msgstr ""
#: include/features.php:82
msgid "Ability to select posts by date ranges"
msgstr ""
#: include/features.php:83 include/features.php:113
msgid "List Forums"
msgstr ""
#: include/features.php:83
msgid "Enable widget to display the forums your are connected with"
msgstr ""
#: include/features.php:84
msgid "Group Filter"
msgstr ""
#: include/features.php:84
msgid "Enable widget to display Network posts only from selected group"
msgstr ""
#: include/features.php:85
msgid "Network Filter"
msgstr ""
#: include/features.php:85
msgid "Enable widget to display Network posts only from selected network"
msgstr ""
#: include/features.php:86 mod/network.php:199 mod/search.php:34
msgid "Saved Searches"
msgstr ""
#: include/features.php:86
msgid "Save search terms for re-use"
msgstr ""
#: include/features.php:91
msgid "Network Tabs"
msgstr ""
#: include/features.php:92
msgid "Network Personal Tab"
msgstr ""
#: include/features.php:92
msgid "Enable tab to display only Network posts that you've interacted on"
msgstr ""
#: include/features.php:93
msgid "Network New Tab"
msgstr ""
#: include/features.php:93
msgid "Enable tab to display only new Network posts (from the last 12 hours)"
msgstr ""
#: include/features.php:94
msgid "Network Shared Links Tab"
msgstr ""
#: include/features.php:94
msgid "Enable tab to display only Network posts with links in them"
msgstr ""
#: include/features.php:99
msgid "Post/Comment Tools"
msgstr ""
#: include/features.php:100
msgid "Multiple Deletion"
msgstr ""
#: include/features.php:100
msgid "Select and delete multiple posts/comments at once"
msgstr ""
#: include/features.php:101
msgid "Edit Sent Posts"
msgstr ""
#: include/features.php:101
msgid "Edit and correct posts and comments after sending"
msgstr ""
#: include/features.php:102
msgid "Tagging"
msgstr ""
#: include/features.php:102
msgid "Ability to tag existing posts"
msgstr ""
#: include/features.php:103
msgid "Post Categories"
msgstr ""
#: include/features.php:103
msgid "Add categories to your posts"
msgstr ""
#: include/features.php:104 include/contact_widgets.php:150
msgid "Saved Folders"
msgstr ""
#: include/features.php:104
msgid "Ability to file posts under folders"
msgstr ""
#: include/features.php:105
msgid "Dislike Posts"
msgstr ""
#: include/features.php:105
msgid "Ability to dislike posts/comments"
msgstr ""
#: include/features.php:106
msgid "Star Posts"
msgstr ""
#: include/features.php:106
msgid "Ability to mark special posts with a star indicator"
msgstr ""
#: include/features.php:107
msgid "Mute Post Notifications"
msgstr ""
#: include/features.php:107
msgid "Ability to mute notifications for a thread"
msgstr ""
#: include/features.php:112
msgid "Advanced Profile Settings"
msgstr ""
#: include/features.php:113
msgid "Show visitors public community forums at the Advanced Profile Page"
msgstr ""
#: include/photos.php:57 include/photos.php:67 mod/fbrowser.php:40
#: mod/fbrowser.php:61 mod/photos.php:182 mod/photos.php:1106
#: mod/photos.php:1231 mod/photos.php:1252 mod/photos.php:1817
#: mod/photos.php:1829
msgid "Contact Photos"
msgstr ""
#: include/datetime.php:58 include/datetime.php:60 mod/profiles.php:697
msgid "Miscellaneous"
msgstr ""
#: include/datetime.php:184 include/identity.php:641
msgid "Birthday:"
msgstr ""
#: include/datetime.php:186 mod/profiles.php:720
msgid "Age: "
msgstr ""
#: include/datetime.php:188
msgid "YYYY-MM-DD or MM-DD"
msgstr ""
#: include/datetime.php:343
msgid "never"
msgstr ""
#: include/datetime.php:349
msgid "less than a second ago"
msgstr ""
#: include/datetime.php:352
msgid "year"
msgstr ""
#: include/datetime.php:352
msgid "years"
msgstr ""
#: include/datetime.php:353 include/event.php:481 mod/cal.php:279
#: mod/events.php:396
msgid "month"
msgstr ""
#: include/datetime.php:353
msgid "months"
msgstr ""
#: include/datetime.php:354 include/event.php:482 mod/cal.php:280
#: mod/events.php:397
msgid "week"
msgstr ""
#: include/datetime.php:354
msgid "weeks"
msgstr ""
#: include/datetime.php:355 include/event.php:483 mod/cal.php:281
#: mod/events.php:398
msgid "day"
msgstr ""
#: include/datetime.php:355
msgid "days"
msgstr ""
#: include/datetime.php:356
msgid "hour"
msgstr ""
#: include/datetime.php:356
msgid "hours"
msgstr ""
#: include/datetime.php:357
msgid "minute"
msgstr ""
#: include/datetime.php:357
msgid "minutes"
msgstr ""
#: include/datetime.php:358
msgid "second"
msgstr ""
#: include/datetime.php:358
msgid "seconds"
msgstr ""
#: include/datetime.php:367
#, php-format
msgid "%1$d %2$s ago"
msgstr ""
#: include/datetime.php:585
#, php-format
msgid "%s's birthday"
msgstr ""
#: include/datetime.php:586 include/dfrn.php:1122
#, php-format
msgid "Happy Birthday %s"
msgstr ""
#: include/event.php:16 include/bb2diaspora.php:199 mod/localtime.php:12
msgid "l F d, Y \\@ g:i A"
msgstr ""
#: include/event.php:33 include/event.php:51 include/event.php:488
#: include/bb2diaspora.php:205
msgid "Starts:"
msgstr ""
#: include/event.php:36 include/event.php:57 include/event.php:489
#: include/bb2diaspora.php:213
msgid "Finishes:"
msgstr ""
#: include/event.php:39 include/event.php:63 include/event.php:490
#: include/bb2diaspora.php:221 include/identity.php:331 mod/directory.php:139
#: mod/contacts.php:636 mod/events.php:501 mod/notifications.php:238
msgid "Location:"
msgstr ""
#: include/event.php:442
msgid "Sun"
msgstr ""
@ -2325,235 +1607,301 @@ msgstr ""
msgid "Export calendar as csv"
msgstr ""
#: include/dfrn.php:1121
#, php-format
msgid "%s\\'s birthday"
#: include/features.php:65
msgid "General Features"
msgstr ""
#: include/contact_selectors.php:32
msgid "Unknown | Not categorised"
#: include/features.php:67
msgid "Multiple Profiles"
msgstr ""
#: include/contact_selectors.php:33
msgid "Block immediately"
#: include/features.php:67
msgid "Ability to create multiple profiles"
msgstr ""
#: include/contact_selectors.php:34
msgid "Shady, spammer, self-marketer"
#: include/features.php:68
msgid "Photo Location"
msgstr ""
#: include/contact_selectors.php:35
msgid "Known to me, but no opinion"
#: include/features.php:68
msgid ""
"Photo metadata is normally stripped. This extracts the location (if present) "
"prior to stripping metadata and links it to a map."
msgstr ""
#: include/contact_selectors.php:36
msgid "OK, probably harmless"
#: include/features.php:69
msgid "Export Public Calendar"
msgstr ""
#: include/contact_selectors.php:37
msgid "Reputable, has my trust"
#: include/features.php:69
msgid "Ability for visitors to download the public calendar"
msgstr ""
#: include/contact_selectors.php:56 mod/admin.php:901
msgid "Frequently"
#: include/features.php:74
msgid "Post Composition Features"
msgstr ""
#: include/contact_selectors.php:57 mod/admin.php:902
msgid "Hourly"
#: include/features.php:75
msgid "Post Preview"
msgstr ""
#: include/contact_selectors.php:58 mod/admin.php:903
msgid "Twice daily"
#: include/features.php:75
msgid "Allow previewing posts and comments before publishing them"
msgstr ""
#: include/contact_selectors.php:59 mod/admin.php:904
msgid "Daily"
#: include/features.php:76
msgid "Auto-mention Forums"
msgstr ""
#: include/contact_selectors.php:60
msgid "Weekly"
#: include/features.php:76
msgid ""
"Add/remove mention when a forum page is selected/deselected in ACL window."
msgstr ""
#: include/contact_selectors.php:61
msgid "Monthly"
#: include/features.php:81
msgid "Network Sidebar Widgets"
msgstr ""
#: include/contact_selectors.php:76 mod/dfrn_request.php:881
msgid "Friendica"
#: include/features.php:82
msgid "Search by Date"
msgstr ""
#: include/contact_selectors.php:77
msgid "OStatus"
#: include/features.php:82
msgid "Ability to select posts by date ranges"
msgstr ""
#: include/contact_selectors.php:78
msgid "RSS/Atom"
#: include/features.php:83 include/features.php:113
msgid "List Forums"
msgstr ""
#: include/contact_selectors.php:79 include/contact_selectors.php:86
#: mod/admin.php:1417 mod/admin.php:1430 mod/admin.php:1443 mod/admin.php:1461
msgid "Email"
#: include/features.php:83
msgid "Enable widget to display the forums your are connected with"
msgstr ""
#: include/contact_selectors.php:80 mod/settings.php:848
#: mod/dfrn_request.php:883
msgid "Diaspora"
#: include/features.php:84
msgid "Group Filter"
msgstr ""
#: include/contact_selectors.php:81
msgid "Facebook"
#: include/features.php:84
msgid "Enable widget to display Network posts only from selected group"
msgstr ""
#: include/contact_selectors.php:82
msgid "Zot!"
#: include/features.php:85
msgid "Network Filter"
msgstr ""
#: include/contact_selectors.php:83
msgid "LinkedIn"
#: include/features.php:85
msgid "Enable widget to display Network posts only from selected network"
msgstr ""
#: include/contact_selectors.php:84
msgid "XMPP/IM"
#: include/features.php:86 mod/network.php:199 mod/search.php:34
msgid "Saved Searches"
msgstr ""
#: include/contact_selectors.php:85
msgid "MySpace"
#: include/features.php:86
msgid "Save search terms for re-use"
msgstr ""
#: include/contact_selectors.php:87
msgid "Google+"
#: include/features.php:91
msgid "Network Tabs"
msgstr ""
#: include/contact_selectors.php:88
msgid "pump.io"
#: include/features.php:92
msgid "Network Personal Tab"
msgstr ""
#: include/contact_selectors.php:89
msgid "Twitter"
#: include/features.php:92
msgid "Enable tab to display only Network posts that you've interacted on"
msgstr ""
#: include/contact_selectors.php:90
msgid "Diaspora Connector"
#: include/features.php:93
msgid "Network New Tab"
msgstr ""
#: include/contact_selectors.php:91
msgid "GNU Social"
#: include/features.php:93
msgid "Enable tab to display only new Network posts (from the last 12 hours)"
msgstr ""
#: include/contact_selectors.php:92
msgid "pnut"
#: include/features.php:94
msgid "Network Shared Links Tab"
msgstr ""
#: include/contact_selectors.php:93
msgid "App.net"
#: include/features.php:94
msgid "Enable tab to display only Network posts with links in them"
msgstr ""
#: include/contact_selectors.php:104
msgid "Hubzilla/Redmatrix"
#: include/features.php:99
msgid "Post/Comment Tools"
msgstr ""
#: include/contact_widgets.php:6
msgid "Add New Contact"
#: include/features.php:100
msgid "Multiple Deletion"
msgstr ""
#: include/contact_widgets.php:7
msgid "Enter address or web location"
#: include/features.php:100
msgid "Select and delete multiple posts/comments at once"
msgstr ""
#: include/contact_widgets.php:8
msgid "Example: bob@example.com, http://example.com/barbara"
#: include/features.php:101
msgid "Edit Sent Posts"
msgstr ""
#: include/contact_widgets.php:10 include/identity.php:219
#: mod/allfriends.php:85 mod/dirfind.php:207 mod/match.php:89
#: mod/suggest.php:101
msgid "Connect"
#: include/features.php:101
msgid "Edit and correct posts and comments after sending"
msgstr ""
#: include/contact_widgets.php:24
#, php-format
msgid "%d invitation available"
msgid_plural "%d invitations available"
msgstr[0] ""
msgstr[1] ""
#: include/contact_widgets.php:30
msgid "Find People"
#: include/features.php:102
msgid "Tagging"
msgstr ""
#: include/contact_widgets.php:31
msgid "Enter name or interest"
#: include/features.php:102
msgid "Ability to tag existing posts"
msgstr ""
#: include/contact_widgets.php:33
msgid "Examples: Robert Morgenstein, Fishing"
#: include/features.php:103
msgid "Post Categories"
msgstr ""
#: include/contact_widgets.php:34 mod/directory.php:206 mod/contacts.php:806
msgid "Find"
#: include/features.php:103
msgid "Add categories to your posts"
msgstr ""
#: include/contact_widgets.php:35 mod/suggest.php:114
#: view/theme/vier/theme.php:198
msgid "Friend Suggestions"
#: include/features.php:104
msgid "Ability to file posts under folders"
msgstr ""
#: include/contact_widgets.php:36 view/theme/vier/theme.php:197
msgid "Similar Interests"
#: include/features.php:105
msgid "Dislike Posts"
msgstr ""
#: include/contact_widgets.php:37
msgid "Random Profile"
#: include/features.php:105
msgid "Ability to dislike posts/comments"
msgstr ""
#: include/contact_widgets.php:38 view/theme/vier/theme.php:199
msgid "Invite Friends"
#: include/features.php:106
msgid "Star Posts"
msgstr ""
#: include/contact_widgets.php:115
msgid "Networks"
#: include/features.php:106
msgid "Ability to mark special posts with a star indicator"
msgstr ""
#: include/contact_widgets.php:118
msgid "All Networks"
#: include/features.php:107
msgid "Mute Post Notifications"
msgstr ""
#: include/contact_widgets.php:153 include/contact_widgets.php:187
msgid "Everything"
#: include/features.php:107
msgid "Ability to mute notifications for a thread"
msgstr ""
#: include/contact_widgets.php:184
msgid "Categories"
#: include/features.php:112
msgid "Advanced Profile Settings"
msgstr ""
#: include/contact_widgets.php:248
#, php-format
msgid "%d contact in common"
msgid_plural "%d contacts in common"
msgstr[0] ""
msgstr[1] ""
#: include/api.php:1021
#, php-format
msgid "Daily posting limit of %d posts reached. The post was rejected."
#: include/features.php:113
msgid "Show visitors public community forums at the Advanced Profile Page"
msgstr ""
#: include/api.php:1041
#, php-format
msgid "Weekly posting limit of %d posts reached. The post was rejected."
#: include/follow.php:81 mod/dfrn_request.php:512
msgid "Disallowed profile URL."
msgstr ""
#: include/api.php:1062
#, php-format
msgid "Monthly posting limit of %d posts reached. The post was rejected."
#: include/follow.php:86
msgid "Connect URL missing."
msgstr ""
#: include/diaspora.php:2087
msgid "Sharing notification from Diaspora network"
#: include/follow.php:114
msgid ""
"This site is not configured to allow communications with other networks."
msgstr ""
#: include/diaspora.php:3096
msgid "Attachments:"
#: include/follow.php:115 include/follow.php:129
msgid "No compatible communication protocols or feeds were discovered."
msgstr ""
#: include/follow.php:127
msgid "The profile address specified does not provide adequate information."
msgstr ""
#: include/follow.php:132
msgid "An author or name was not found."
msgstr ""
#: include/follow.php:135
msgid "No browser URL could be matched to this address."
msgstr ""
#: include/follow.php:138
msgid ""
"Unable to match @-style Identity Address with a known protocol or email "
"contact."
msgstr ""
#: include/follow.php:139
msgid "Use mailto: in front of address to force email check."
msgstr ""
#: include/follow.php:145
msgid ""
"The profile address specified belongs to a network which has been disabled "
"on this site."
msgstr ""
#: include/follow.php:150
msgid ""
"Limited profile. This person will be unable to receive direct/personal "
"notifications from you."
msgstr ""
#: include/follow.php:251
msgid "Unable to retrieve contact information."
msgstr ""
#: include/group.php:25
msgid ""
"A deleted group with this name was revived. Existing item permissions "
"<strong>may</strong> apply to this group and any future members. If this is "
"not what you intended, please create another group with a different name."
msgstr ""
#: include/group.php:210
msgid "Default privacy group for new contacts"
msgstr ""
#: include/group.php:243
msgid "Everybody"
msgstr ""
#: include/group.php:266
msgid "edit"
msgstr ""
#: include/group.php:287 mod/newmember.php:61
msgid "Groups"
msgstr ""
#: include/group.php:289
msgid "Edit groups"
msgstr ""
#: include/group.php:291
msgid "Edit group"
msgstr ""
#: include/group.php:292
msgid "Create a new group"
msgstr ""
#: include/group.php:293 mod/group.php:98 mod/group.php:188
msgid "Group Name: "
msgstr ""
#: include/group.php:295
msgid "Contacts not in any group"
msgstr ""
#: include/group.php:297 mod/network.php:200
msgid "add"
msgstr ""
#: include/identity.php:43
@ -2572,6 +1920,10 @@ msgstr ""
msgid "Atom feed"
msgstr ""
#: include/identity.php:285 include/nav.php:189
msgid "Profiles"
msgstr ""
#: include/identity.php:285
msgid "Manage/edit profiles"
msgstr ""
@ -2609,8 +1961,8 @@ msgstr ""
msgid "Homepage:"
msgstr ""
#: include/identity.php:340 include/identity.php:684 mod/directory.php:147
#: mod/contacts.php:640 mod/notifications.php:240
#: include/identity.php:340 include/identity.php:684 mod/contacts.php:640
#: mod/directory.php:147 mod/notifications.php:240
msgid "About:"
msgstr ""
@ -2654,6 +2006,12 @@ msgstr ""
msgid "Events this week:"
msgstr ""
#: include/identity.php:617 include/identity.php:741 include/identity.php:774
#: include/nav.php:82 mod/contacts.php:647 mod/contacts.php:849
#: mod/newmember.php:32 mod/profperm.php:105 view/theme/frio/theme.php:247
msgid "Profile"
msgstr ""
#: include/identity.php:626 mod/settings.php:1286
msgid "Full Name:"
msgstr ""
@ -2683,7 +2041,7 @@ msgstr ""
msgid "Hometown:"
msgstr ""
#: include/identity.php:672 mod/follow.php:137 mod/contacts.php:642
#: include/identity.php:672 mod/contacts.php:642 mod/follow.php:137
#: mod/notifications.php:242
msgid "Tags:"
msgstr ""
@ -2748,12 +2106,17 @@ msgstr ""
msgid "Basic"
msgstr ""
#: include/identity.php:743 mod/contacts.php:878 mod/events.php:515
#: mod/admin.php:980
#: include/identity.php:743 mod/admin.php:972 mod/contacts.php:878
#: mod/events.php:515
msgid "Advanced"
msgstr ""
#: include/identity.php:769 mod/follow.php:145 mod/contacts.php:844
#: include/identity.php:766 include/nav.php:81 mod/contacts.php:645
#: mod/contacts.php:841 view/theme/frio/theme.php:246
msgid "Status"
msgstr ""
#: include/identity.php:769 mod/contacts.php:844 mod/follow.php:145
msgid "Status Messages and Posts"
msgstr ""
@ -2761,10 +2124,31 @@ msgstr ""
msgid "Profile Details"
msgstr ""
#: include/identity.php:782 include/nav.php:83 mod/fbrowser.php:31
#: view/theme/frio/theme.php:248
msgid "Photos"
msgstr ""
#: include/identity.php:785 mod/photos.php:89
msgid "Photo Albums"
msgstr ""
#: include/identity.php:790 include/identity.php:793 include/nav.php:84
#: view/theme/frio/theme.php:249
msgid "Videos"
msgstr ""
#: include/identity.php:802 include/identity.php:813 include/nav.php:85
#: include/nav.php:149 mod/cal.php:270 mod/events.php:386
#: view/theme/frio/theme.php:250 view/theme/frio/theme.php:254
msgid "Events"
msgstr ""
#: include/identity.php:805 include/identity.php:816 include/nav.php:149
#: view/theme/frio/theme.php:254
msgid "Events and Calendar"
msgstr ""
#: include/identity.php:824 mod/notes.php:47
msgid "Personal Notes"
msgstr ""
@ -2773,30 +2157,617 @@ msgstr ""
msgid "Only You Can See This"
msgstr ""
#: include/text.php:304
#: include/identity.php:835 include/identity.php:838 include/nav.php:128
#: include/nav.php:192 include/text.php:1024 mod/contacts.php:800
#: mod/contacts.php:861 mod/viewcontacts.php:121 view/theme/frio/theme.php:257
msgid "Contacts"
msgstr ""
#: include/items.php:1584 mod/dfrn_confirm.php:735 mod/dfrn_request.php:754
msgid "[Name Withheld]"
msgstr ""
#: include/items.php:1939 mod/admin.php:240 mod/admin.php:1480
#: mod/admin.php:1731 mod/display.php:103 mod/display.php:279
#: mod/display.php:484 mod/notice.php:15 mod/viewsrc.php:15
msgid "Item not found."
msgstr ""
#: include/items.php:1978
msgid "Do you really want to delete this item?"
msgstr ""
#: include/items.php:1980 mod/api.php:105 mod/contacts.php:452
#: mod/dfrn_request.php:875 mod/follow.php:113 mod/message.php:206
#: mod/profiles.php:640 mod/profiles.php:643 mod/profiles.php:669
#: mod/register.php:245 mod/settings.php:1171 mod/settings.php:1177
#: mod/settings.php:1184 mod/settings.php:1188 mod/settings.php:1193
#: mod/settings.php:1198 mod/settings.php:1203 mod/settings.php:1208
#: mod/settings.php:1234 mod/settings.php:1235 mod/settings.php:1236
#: mod/settings.php:1237 mod/settings.php:1238 mod/suggest.php:29
msgid "Yes"
msgstr ""
#: include/items.php:2143 index.php:407 mod/allfriends.php:12 mod/api.php:26
#: mod/api.php:31 mod/attach.php:33 mod/cal.php:299 mod/common.php:18
#: mod/contacts.php:360 mod/crepair.php:102 mod/delegate.php:12
#: mod/dfrn_confirm.php:61 mod/dirfind.php:11 mod/display.php:481
#: mod/editpost.php:10 mod/events.php:195 mod/follow.php:11 mod/follow.php:74
#: mod/follow.php:158 mod/fsuggest.php:79 mod/group.php:19 mod/invite.php:15
#: mod/invite.php:103 mod/item.php:193 mod/item.php:205 mod/manage.php:98
#: mod/message.php:46 mod/message.php:171 mod/mood.php:115 mod/network.php:4
#: mod/nogroup.php:27 mod/notes.php:23 mod/notifications.php:71
#: mod/ostatus_subscribe.php:9 mod/photos.php:161 mod/photos.php:1092
#: mod/poke.php:154 mod/profile_photo.php:19 mod/profile_photo.php:180
#: mod/profile_photo.php:191 mod/profile_photo.php:204 mod/profiles.php:166
#: mod/profiles.php:607 mod/register.php:42 mod/regmod.php:113
#: mod/repair_ostatus.php:9 mod/settings.php:22 mod/settings.php:130
#: mod/settings.php:668 mod/suggest.php:58 mod/uimport.php:24
#: mod/viewcontacts.php:46 mod/wall_attach.php:67 mod/wall_attach.php:70
#: mod/wall_upload.php:77 mod/wall_upload.php:80 mod/wallmessage.php:9
#: mod/wallmessage.php:33 mod/wallmessage.php:73 mod/wallmessage.php:97
msgid "Permission denied."
msgstr ""
#: include/items.php:2248
msgid "Archives"
msgstr ""
#: include/like.php:41
#, php-format
msgid "%1$s is attending %2$s's %3$s"
msgstr ""
#: include/like.php:46
#, php-format
msgid "%1$s is not attending %2$s's %3$s"
msgstr ""
#: include/like.php:51
#, php-format
msgid "%1$s may attend %2$s's %3$s"
msgstr ""
#: include/message.php:15 include/message.php:169
msgid "[no subject]"
msgstr ""
#: include/nav.php:35 mod/navigation.php:19
msgid "Nothing new here"
msgstr ""
#: include/nav.php:39 mod/navigation.php:23
msgid "Clear notifications"
msgstr ""
#: include/nav.php:40 include/text.php:1017
msgid "@name, !forum, #tags, content"
msgstr ""
#: include/nav.php:78 view/theme/frio/theme.php:243
msgid "End this session"
msgstr ""
#: include/nav.php:81 include/nav.php:161 view/theme/frio/theme.php:246
msgid "Your posts and conversations"
msgstr ""
#: include/nav.php:82 view/theme/frio/theme.php:247
msgid "Your profile page"
msgstr ""
#: include/nav.php:83 view/theme/frio/theme.php:248
msgid "Your photos"
msgstr ""
#: include/nav.php:84 view/theme/frio/theme.php:249
msgid "Your videos"
msgstr ""
#: include/nav.php:85 view/theme/frio/theme.php:250
msgid "Your events"
msgstr ""
#: include/nav.php:86
msgid "Personal notes"
msgstr ""
#: include/nav.php:86
msgid "Your personal notes"
msgstr ""
#: include/nav.php:95
msgid "Sign in"
msgstr ""
#: include/nav.php:105
msgid "Home Page"
msgstr ""
#: include/nav.php:109
msgid "Create an account"
msgstr ""
#: include/nav.php:115 mod/help.php:47 view/theme/vier/theme.php:293
msgid "Help"
msgstr ""
#: include/nav.php:115
msgid "Help and documentation"
msgstr ""
#: include/nav.php:119
msgid "Apps"
msgstr ""
#: include/nav.php:119
msgid "Addon applications, utilities, games"
msgstr ""
#: include/nav.php:123 include/text.php:1014 mod/search.php:149
msgid "Search"
msgstr ""
#: include/nav.php:123
msgid "Search site content"
msgstr ""
#: include/nav.php:126 include/text.php:1022
msgid "Full Text"
msgstr ""
#: include/nav.php:127 include/text.php:1023
msgid "Tags"
msgstr ""
#: include/nav.php:143 include/nav.php:145 mod/community.php:36
msgid "Community"
msgstr ""
#: include/nav.php:143
msgid "Conversations on this site"
msgstr ""
#: include/nav.php:145
msgid "Conversations on the network"
msgstr ""
#: include/nav.php:152
msgid "Directory"
msgstr ""
#: include/nav.php:152
msgid "People directory"
msgstr ""
#: include/nav.php:154
msgid "Information"
msgstr ""
#: include/nav.php:154
msgid "Information about this friendica instance"
msgstr ""
#: include/nav.php:158 view/theme/frio/theme.php:253
msgid "Conversations from your friends"
msgstr ""
#: include/nav.php:159
msgid "Network Reset"
msgstr ""
#: include/nav.php:159
msgid "Load Network page with no filters"
msgstr ""
#: include/nav.php:166
msgid "Friend Requests"
msgstr ""
#: include/nav.php:169 mod/notifications.php:96
msgid "Notifications"
msgstr ""
#: include/nav.php:170
msgid "See all notifications"
msgstr ""
#: include/nav.php:171 mod/settings.php:906
msgid "Mark as seen"
msgstr ""
#: include/nav.php:171
msgid "Mark all system notifications seen"
msgstr ""
#: include/nav.php:175 mod/message.php:179 view/theme/frio/theme.php:255
msgid "Messages"
msgstr ""
#: include/nav.php:175 view/theme/frio/theme.php:255
msgid "Private mail"
msgstr ""
#: include/nav.php:176
msgid "Inbox"
msgstr ""
#: include/nav.php:177
msgid "Outbox"
msgstr ""
#: include/nav.php:178 mod/message.php:16
msgid "New Message"
msgstr ""
#: include/nav.php:181
msgid "Manage"
msgstr ""
#: include/nav.php:181
msgid "Manage other pages"
msgstr ""
#: include/nav.php:184 mod/settings.php:81
msgid "Delegations"
msgstr ""
#: include/nav.php:184 mod/delegate.php:130
msgid "Delegate Page Management"
msgstr ""
#: include/nav.php:186 mod/admin.php:1533 mod/admin.php:1809
#: mod/newmember.php:22 mod/settings.php:111 view/theme/frio/theme.php:256
msgid "Settings"
msgstr ""
#: include/nav.php:186 view/theme/frio/theme.php:256
msgid "Account settings"
msgstr ""
#: include/nav.php:189
msgid "Manage/Edit Profiles"
msgstr ""
#: include/nav.php:192 view/theme/frio/theme.php:257
msgid "Manage/edit friends and contacts"
msgstr ""
#: include/nav.php:197 mod/admin.php:192
msgid "Admin"
msgstr ""
#: include/nav.php:197
msgid "Site setup and configuration"
msgstr ""
#: include/nav.php:200
msgid "Navigation"
msgstr ""
#: include/nav.php:200
msgid "Site map"
msgstr ""
#: include/network.php:622
msgid "view full size"
msgstr ""
#: include/oembed.php:266
msgid "Embedded content"
msgstr ""
#: include/oembed.php:274
msgid "Embedding disabled"
msgstr ""
#: include/ostatus.php:1832
#, php-format
msgid "%s is now following %s."
msgstr ""
#: include/ostatus.php:1833
msgid "following"
msgstr ""
#: include/ostatus.php:1836
#, php-format
msgid "%s stopped following %s."
msgstr ""
#: include/ostatus.php:1837
msgid "stopped following"
msgstr ""
#: include/photos.php:57 include/photos.php:67 mod/fbrowser.php:40
#: mod/fbrowser.php:61 mod/photos.php:182 mod/photos.php:1106
#: mod/photos.php:1231 mod/photos.php:1252 mod/photos.php:1817
#: mod/photos.php:1829
msgid "Contact Photos"
msgstr ""
#: include/plugin.php:530 include/plugin.php:532
msgid "Click here to upgrade."
msgstr ""
#: include/plugin.php:538
msgid "This action exceeds the limits set by your subscription plan."
msgstr ""
#: include/plugin.php:543
msgid "This action is not available under your subscription plan."
msgstr ""
#: include/profile_selectors.php:6
msgid "Male"
msgstr ""
#: include/profile_selectors.php:6
msgid "Female"
msgstr ""
#: include/profile_selectors.php:6
msgid "Currently Male"
msgstr ""
#: include/profile_selectors.php:6
msgid "Currently Female"
msgstr ""
#: include/profile_selectors.php:6
msgid "Mostly Male"
msgstr ""
#: include/profile_selectors.php:6
msgid "Mostly Female"
msgstr ""
#: include/profile_selectors.php:6
msgid "Transgender"
msgstr ""
#: include/profile_selectors.php:6
msgid "Intersex"
msgstr ""
#: include/profile_selectors.php:6
msgid "Transsexual"
msgstr ""
#: include/profile_selectors.php:6
msgid "Hermaphrodite"
msgstr ""
#: include/profile_selectors.php:6
msgid "Neuter"
msgstr ""
#: include/profile_selectors.php:6
msgid "Non-specific"
msgstr ""
#: include/profile_selectors.php:6
msgid "Other"
msgstr ""
#: include/profile_selectors.php:23
msgid "Males"
msgstr ""
#: include/profile_selectors.php:23
msgid "Females"
msgstr ""
#: include/profile_selectors.php:23
msgid "Gay"
msgstr ""
#: include/profile_selectors.php:23
msgid "Lesbian"
msgstr ""
#: include/profile_selectors.php:23
msgid "No Preference"
msgstr ""
#: include/profile_selectors.php:23
msgid "Bisexual"
msgstr ""
#: include/profile_selectors.php:23
msgid "Autosexual"
msgstr ""
#: include/profile_selectors.php:23
msgid "Abstinent"
msgstr ""
#: include/profile_selectors.php:23
msgid "Virgin"
msgstr ""
#: include/profile_selectors.php:23
msgid "Deviant"
msgstr ""
#: include/profile_selectors.php:23
msgid "Fetish"
msgstr ""
#: include/profile_selectors.php:23
msgid "Oodles"
msgstr ""
#: include/profile_selectors.php:23
msgid "Nonsexual"
msgstr ""
#: include/profile_selectors.php:42
msgid "Single"
msgstr ""
#: include/profile_selectors.php:42
msgid "Lonely"
msgstr ""
#: include/profile_selectors.php:42
msgid "Available"
msgstr ""
#: include/profile_selectors.php:42
msgid "Unavailable"
msgstr ""
#: include/profile_selectors.php:42
msgid "Has crush"
msgstr ""
#: include/profile_selectors.php:42
msgid "Infatuated"
msgstr ""
#: include/profile_selectors.php:42
msgid "Dating"
msgstr ""
#: include/profile_selectors.php:42
msgid "Unfaithful"
msgstr ""
#: include/profile_selectors.php:42
msgid "Sex Addict"
msgstr ""
#: include/profile_selectors.php:42 include/user.php:280 include/user.php:284
msgid "Friends"
msgstr ""
#: include/profile_selectors.php:42
msgid "Friends/Benefits"
msgstr ""
#: include/profile_selectors.php:42
msgid "Casual"
msgstr ""
#: include/profile_selectors.php:42
msgid "Engaged"
msgstr ""
#: include/profile_selectors.php:42
msgid "Married"
msgstr ""
#: include/profile_selectors.php:42
msgid "Imaginarily married"
msgstr ""
#: include/profile_selectors.php:42
msgid "Partners"
msgstr ""
#: include/profile_selectors.php:42
msgid "Cohabiting"
msgstr ""
#: include/profile_selectors.php:42
msgid "Common law"
msgstr ""
#: include/profile_selectors.php:42
msgid "Happy"
msgstr ""
#: include/profile_selectors.php:42
msgid "Not looking"
msgstr ""
#: include/profile_selectors.php:42
msgid "Swinger"
msgstr ""
#: include/profile_selectors.php:42
msgid "Betrayed"
msgstr ""
#: include/profile_selectors.php:42
msgid "Separated"
msgstr ""
#: include/profile_selectors.php:42
msgid "Unstable"
msgstr ""
#: include/profile_selectors.php:42
msgid "Divorced"
msgstr ""
#: include/profile_selectors.php:42
msgid "Imaginarily divorced"
msgstr ""
#: include/profile_selectors.php:42
msgid "Widowed"
msgstr ""
#: include/profile_selectors.php:42
msgid "Uncertain"
msgstr ""
#: include/profile_selectors.php:42
msgid "It's complicated"
msgstr ""
#: include/profile_selectors.php:42
msgid "Don't care"
msgstr ""
#: include/profile_selectors.php:42
msgid "Ask me"
msgstr ""
#: include/security.php:61
msgid "Welcome "
msgstr ""
#: include/security.php:62
msgid "Please upload a profile photo."
msgstr ""
#: include/security.php:65
msgid "Welcome back "
msgstr ""
#: include/security.php:429
msgid ""
"The form security token was not correct. This probably happened because the "
"form has been opened for too long (>3 hours) before submitting it."
msgstr ""
#: include/text.php:307
msgid "newer"
msgstr ""
#: include/text.php:306
#: include/text.php:308
msgid "older"
msgstr ""
#: include/text.php:311
msgid "prev"
msgstr ""
#: include/text.php:313
msgid "first"
msgstr ""
#: include/text.php:345
msgid "last"
#: include/text.php:314
msgid "prev"
msgstr ""
#: include/text.php:348
msgid "next"
msgstr ""
#: include/text.php:349
msgid "last"
msgstr ""
#: include/text.php:403
msgid "Loading more entries..."
msgstr ""
@ -2820,7 +2791,7 @@ msgstr[1] ""
msgid "View Contacts"
msgstr ""
#: include/text.php:1015 mod/filer.php:31 mod/notes.php:62 mod/editpost.php:99
#: include/text.php:1015 mod/editpost.php:99 mod/filer.php:31 mod/notes.php:62
msgid "Save"
msgstr ""
@ -2976,8 +2947,8 @@ msgstr ""
msgid "activity"
msgstr ""
#: include/text.php:1810 mod/content.php:623 object/Item.php:446
#: object/Item.php:458
#: include/text.php:1810 mod/content.php:623 object/Item.php:419
#: object/Item.php:431
msgid "comment"
msgid_plural "comments"
msgstr[0] ""
@ -2991,103 +2962,1569 @@ msgstr ""
msgid "Item filed"
msgstr ""
#: include/Contact.php:450
msgid "Drop Contact"
#: include/uimport.php:91
msgid "Error decoding account file"
msgstr ""
#: include/Contact.php:827
msgid "Organisation"
#: include/uimport.php:97
msgid "Error! No version data in file! This is not a Friendica account file?"
msgstr ""
#: include/Contact.php:830
msgid "News"
#: include/uimport.php:113 include/uimport.php:124
msgid "Error! Cannot check nickname"
msgstr ""
#: include/Contact.php:833
msgid "Forum"
#: include/uimport.php:117 include/uimport.php:128
#, php-format
msgid "User '%s' already exists on this server!"
msgstr ""
#: include/items.php:1584 mod/dfrn_confirm.php:735 mod/dfrn_request.php:754
msgid "[Name Withheld]"
#: include/uimport.php:150
msgid "User creation error"
msgstr ""
#: include/items.php:1939 mod/notice.php:15 mod/viewsrc.php:15
#: mod/display.php:103 mod/display.php:279 mod/display.php:484
#: mod/admin.php:235 mod/admin.php:1492 mod/admin.php:1738
msgid "Item not found."
#: include/uimport.php:170
msgid "User profile creation error"
msgstr ""
#: include/items.php:1978
msgid "Do you really want to delete this item?"
#: include/uimport.php:219
#, php-format
msgid "%d contact not imported"
msgid_plural "%d contacts not imported"
msgstr[0] ""
msgstr[1] ""
#: include/uimport.php:289
msgid "Done. You can now login with your username and password"
msgstr ""
#: include/items.php:1980 mod/api.php:105 mod/follow.php:113
#: mod/register.php:245 mod/settings.php:1171 mod/settings.php:1177
#: mod/settings.php:1184 mod/settings.php:1188 mod/settings.php:1193
#: mod/settings.php:1198 mod/settings.php:1203 mod/settings.php:1208
#: mod/settings.php:1234 mod/settings.php:1235 mod/settings.php:1236
#: mod/settings.php:1237 mod/settings.php:1238 mod/suggest.php:29
#: mod/contacts.php:452 mod/message.php:206 mod/dfrn_request.php:875
#: mod/profiles.php:640 mod/profiles.php:643 mod/profiles.php:669
msgid "Yes"
#: include/user.php:39 mod/settings.php:375
msgid "Passwords do not match. Password unchanged."
msgstr ""
#: include/items.php:2143 mod/allfriends.php:12 mod/api.php:26 mod/api.php:31
#: mod/attach.php:33 mod/common.php:18 mod/crepair.php:102 mod/delegate.php:12
#: mod/dirfind.php:11 mod/follow.php:11 mod/follow.php:74 mod/follow.php:158
#: mod/fsuggest.php:79 mod/group.php:19 mod/invite.php:15 mod/invite.php:103
#: mod/manage.php:98 mod/mood.php:115 mod/nogroup.php:27 mod/notes.php:23
#: mod/ostatus_subscribe.php:9 mod/poke.php:154 mod/profile_photo.php:19
#: mod/profile_photo.php:180 mod/profile_photo.php:191
#: mod/profile_photo.php:204 mod/register.php:42 mod/regmod.php:113
#: mod/repair_ostatus.php:9 mod/settings.php:22 mod/settings.php:130
#: mod/settings.php:668 mod/suggest.php:58 mod/uimport.php:24
#: mod/wall_attach.php:67 mod/wall_attach.php:70 mod/cal.php:299
#: mod/contacts.php:360 mod/dfrn_confirm.php:61 mod/editpost.php:10
#: mod/events.php:195 mod/item.php:193 mod/item.php:205 mod/message.php:46
#: mod/message.php:171 mod/wall_upload.php:77 mod/wall_upload.php:80
#: mod/wallmessage.php:9 mod/wallmessage.php:33 mod/wallmessage.php:73
#: mod/wallmessage.php:97 mod/photos.php:161 mod/photos.php:1092
#: mod/profiles.php:166 mod/profiles.php:607 mod/display.php:481
#: mod/viewcontacts.php:46 mod/network.php:4 mod/notifications.php:71
#: index.php:407
msgid "Permission denied."
#: include/user.php:48
msgid "An invitation is required."
msgstr ""
#: include/items.php:2248
msgid "Archives"
#: include/user.php:53
msgid "Invitation could not be verified."
msgstr ""
#: include/dbstructure.php:33
#: include/user.php:61
msgid "Invalid OpenID url"
msgstr ""
#: include/user.php:82
msgid "Please enter the required information."
msgstr ""
#: include/user.php:96
msgid "Please use a shorter name."
msgstr ""
#: include/user.php:98
msgid "Name too short."
msgstr ""
#: include/user.php:113
msgid "That doesn't appear to be your full (First Last) name."
msgstr ""
#: include/user.php:118
msgid "Your email domain is not among those allowed on this site."
msgstr ""
#: include/user.php:121
msgid "Not a valid email address."
msgstr ""
#: include/user.php:134
msgid "Cannot use that email."
msgstr ""
#: include/user.php:140
msgid "Your \"nickname\" can only contain \"a-z\", \"0-9\" and \"_\"."
msgstr ""
#: include/user.php:147 include/user.php:245
msgid "Nickname is already registered. Please choose another."
msgstr ""
#: include/user.php:157
msgid ""
"Nickname was once registered here and may not be re-used. Please choose "
"another."
msgstr ""
#: include/user.php:173
msgid "SERIOUS ERROR: Generation of security keys failed."
msgstr ""
#: include/user.php:231
msgid "An error occurred during registration. Please try again."
msgstr ""
#: include/user.php:256 view/theme/duepuntozero/config.php:43
msgid "default"
msgstr ""
#: include/user.php:266
msgid "An error occurred creating your default profile. Please try again."
msgstr ""
#: include/user.php:326 include/user.php:334 include/user.php:342
#: mod/photos.php:68 mod/photos.php:182 mod/photos.php:768 mod/photos.php:1231
#: mod/photos.php:1252 mod/photos.php:1839 mod/profile_photo.php:74
#: mod/profile_photo.php:82 mod/profile_photo.php:90 mod/profile_photo.php:215
#: mod/profile_photo.php:310 mod/profile_photo.php:320
msgid "Profile Photos"
msgstr ""
#: include/user.php:417
#, php-format
msgid ""
"\n"
"\t\t\tThe friendica developers released update %s recently,\n"
"\t\t\tbut when I tried to install it, something went terribly wrong.\n"
"\t\t\tThis needs to be fixed soon and I can't do it alone. Please contact a\n"
"\t\t\tfriendica developer if you can not help me on your own. My database "
"might be invalid."
"\t\tDear %1$s,\n"
"\t\t\tThank you for registering at %2$s. Your account is pending for "
"approval by the administrator.\n"
"\t"
msgstr ""
#: include/dbstructure.php:38
#: include/user.php:427
#, php-format
msgid "Registration at %s"
msgstr ""
#: include/user.php:437
#, php-format
msgid ""
"The error message is\n"
"[pre]%s[/pre]"
"\n"
"\t\tDear %1$s,\n"
"\t\t\tThank you for registering at %2$s. Your account has been created.\n"
"\t"
msgstr ""
#: include/dbstructure.php:195
msgid "Errors encountered creating database tables."
#: include/user.php:441
#, php-format
msgid ""
"\n"
"\t\tThe login details are as follows:\n"
"\t\t\tSite Location:\t%3$s\n"
"\t\t\tLogin Name:\t%1$s\n"
"\t\t\tPassword:\t%5$s\n"
"\n"
"\t\tYou may change your password from your account \"Settings\" page after "
"logging\n"
"\t\tin.\n"
"\n"
"\t\tPlease take a few moments to review the other account settings on that "
"page.\n"
"\n"
"\t\tYou may also wish to add some basic information to your default profile\n"
"\t\t(on the \"Profiles\" page) so that other people can easily find you.\n"
"\n"
"\t\tWe recommend setting your full name, adding a profile photo,\n"
"\t\tadding some profile \"keywords\" (very useful in making new friends) - "
"and\n"
"\t\tperhaps what country you live in; if you do not wish to be more "
"specific\n"
"\t\tthan that.\n"
"\n"
"\t\tWe fully respect your right to privacy, and none of these items are "
"necessary.\n"
"\t\tIf you are new and do not know anybody here, they may help\n"
"\t\tyou to make some new and interesting friends.\n"
"\n"
"\n"
"\t\tThank you and welcome to %2$s."
msgstr ""
#: include/dbstructure.php:329 include/dbstructure.php:337
#: include/dbstructure.php:345 include/dbstructure.php:350
#: include/dbstructure.php:355
msgid "Errors encountered performing database changes."
#: include/user.php:473 mod/admin.php:1223
#, php-format
msgid "Registration details for %s"
msgstr ""
#: include/network.php:619
msgid "view full size"
#: index.php:248 mod/apps.php:7
msgid "You must be logged in to use addons. "
msgstr ""
#: index.php:292 mod/fetch.php:12 mod/fetch.php:39 mod/fetch.php:48
#: mod/help.php:53 mod/p.php:16 mod/p.php:43 mod/p.php:52
msgid "Not Found"
msgstr ""
#: index.php:295 mod/help.php:56
msgid "Page not found."
msgstr ""
#: index.php:406 mod/group.php:76 mod/profperm.php:20
msgid "Permission denied"
msgstr ""
#: index.php:457
msgid "toggle mobile"
msgstr ""
#: mod/admin.php:96
msgid "Theme settings updated."
msgstr ""
#: mod/admin.php:162 mod/admin.php:967
msgid "Site"
msgstr ""
#: mod/admin.php:163 mod/admin.php:901 mod/admin.php:1413 mod/admin.php:1429
msgid "Users"
msgstr ""
#: mod/admin.php:164 mod/admin.php:1531 mod/admin.php:1594 mod/settings.php:74
msgid "Plugins"
msgstr ""
#: mod/admin.php:165 mod/admin.php:1807 mod/admin.php:1857
msgid "Themes"
msgstr ""
#: mod/admin.php:166 mod/settings.php:52
msgid "Additional features"
msgstr ""
#: mod/admin.php:167
msgid "DB updates"
msgstr ""
#: mod/admin.php:168 mod/admin.php:416
msgid "Inspect Queue"
msgstr ""
#: mod/admin.php:169 mod/admin.php:382
msgid "Federation Statistics"
msgstr ""
#: mod/admin.php:183 mod/admin.php:194 mod/admin.php:1931
msgid "Logs"
msgstr ""
#: mod/admin.php:184 mod/admin.php:1999
msgid "View Logs"
msgstr ""
#: mod/admin.php:185
msgid "probe address"
msgstr ""
#: mod/admin.php:186
msgid "check webfinger"
msgstr ""
#: mod/admin.php:193
msgid "Plugin Features"
msgstr ""
#: mod/admin.php:195
msgid "diagnostics"
msgstr ""
#: mod/admin.php:196
msgid "User registrations waiting for confirmation"
msgstr ""
#: mod/admin.php:312
msgid "unknown"
msgstr ""
#: mod/admin.php:375
msgid ""
"This page offers you some numbers to the known part of the federated social "
"network your Friendica node is part of. These numbers are not complete but "
"only reflect the part of the network your node is aware of."
msgstr ""
#: mod/admin.php:376
msgid ""
"The <em>Auto Discovered Contact Directory</em> feature is not enabled, it "
"will improve the data displayed here."
msgstr ""
#: mod/admin.php:381 mod/admin.php:415 mod/admin.php:493 mod/admin.php:966
#: mod/admin.php:1412 mod/admin.php:1530 mod/admin.php:1593 mod/admin.php:1806
#: mod/admin.php:1856 mod/admin.php:1930 mod/admin.php:1998
msgid "Administration"
msgstr ""
#: mod/admin.php:388
#, php-format
msgid "Currently this node is aware of %d nodes from the following platforms:"
msgstr ""
#: mod/admin.php:418
msgid "ID"
msgstr ""
#: mod/admin.php:419
msgid "Recipient Name"
msgstr ""
#: mod/admin.php:420
msgid "Recipient Profile"
msgstr ""
#: mod/admin.php:422
msgid "Created"
msgstr ""
#: mod/admin.php:423
msgid "Last Tried"
msgstr ""
#: mod/admin.php:424
msgid ""
"This page lists the content of the queue for outgoing postings. These are "
"postings the initial delivery failed for. They will be resend later and "
"eventually deleted if the delivery fails permanently."
msgstr ""
#: mod/admin.php:449
#, php-format
msgid ""
"Your DB still runs with MyISAM tables. You should change the engine type to "
"InnoDB. As Friendica will use InnoDB only features in the future, you should "
"change this! See <a href=\"%s\">here</a> for a guide that may be helpful "
"converting the table engines. You may also use the <tt>convert_innodb.sql</"
"tt> in the <tt>/util</tt> directory of your Friendica installation.<br />"
msgstr ""
#: mod/admin.php:454
msgid ""
"You are using a MySQL version which does not support all features that "
"Friendica uses. You should consider switching to MariaDB."
msgstr ""
#: mod/admin.php:458 mod/admin.php:1362
msgid "Normal Account"
msgstr ""
#: mod/admin.php:459 mod/admin.php:1363
msgid "Soapbox Account"
msgstr ""
#: mod/admin.php:460 mod/admin.php:1364
msgid "Community/Celebrity Account"
msgstr ""
#: mod/admin.php:461 mod/admin.php:1365
msgid "Automatic Friend Account"
msgstr ""
#: mod/admin.php:462
msgid "Blog Account"
msgstr ""
#: mod/admin.php:463
msgid "Private Forum"
msgstr ""
#: mod/admin.php:488
msgid "Message queues"
msgstr ""
#: mod/admin.php:494
msgid "Summary"
msgstr ""
#: mod/admin.php:496
msgid "Registered users"
msgstr ""
#: mod/admin.php:498
msgid "Pending registrations"
msgstr ""
#: mod/admin.php:499
msgid "Version"
msgstr ""
#: mod/admin.php:504
msgid "Active plugins"
msgstr ""
#: mod/admin.php:529
msgid "Can not parse base url. Must have at least <scheme>://<domain>"
msgstr ""
#: mod/admin.php:819
msgid "RINO2 needs mcrypt php extension to work."
msgstr ""
#: mod/admin.php:827
msgid "Site settings updated."
msgstr ""
#: mod/admin.php:855 mod/settings.php:943
msgid "No special theme for mobile devices"
msgstr ""
#: mod/admin.php:884
msgid "No community page"
msgstr ""
#: mod/admin.php:885
msgid "Public postings from users of this site"
msgstr ""
#: mod/admin.php:886
msgid "Global community page"
msgstr ""
#: mod/admin.php:891 mod/contacts.php:538
msgid "Never"
msgstr ""
#: mod/admin.php:892
msgid "At post arrival"
msgstr ""
#: mod/admin.php:900 mod/contacts.php:565
msgid "Disabled"
msgstr ""
#: mod/admin.php:902
msgid "Users, Global Contacts"
msgstr ""
#: mod/admin.php:903
msgid "Users, Global Contacts/fallback"
msgstr ""
#: mod/admin.php:907
msgid "One month"
msgstr ""
#: mod/admin.php:908
msgid "Three months"
msgstr ""
#: mod/admin.php:909
msgid "Half a year"
msgstr ""
#: mod/admin.php:910
msgid "One year"
msgstr ""
#: mod/admin.php:915
msgid "Multi user instance"
msgstr ""
#: mod/admin.php:938
msgid "Closed"
msgstr ""
#: mod/admin.php:939
msgid "Requires approval"
msgstr ""
#: mod/admin.php:940
msgid "Open"
msgstr ""
#: mod/admin.php:944
msgid "No SSL policy, links will track page SSL state"
msgstr ""
#: mod/admin.php:945
msgid "Force all links to use SSL"
msgstr ""
#: mod/admin.php:946
msgid "Self-signed certificate, use SSL for local links only (discouraged)"
msgstr ""
#: mod/admin.php:968 mod/admin.php:1595 mod/admin.php:1858 mod/admin.php:1932
#: mod/admin.php:2085 mod/settings.php:681 mod/settings.php:792
#: mod/settings.php:841 mod/settings.php:908 mod/settings.php:1005
#: mod/settings.php:1271
msgid "Save Settings"
msgstr ""
#: mod/admin.php:969 mod/register.php:272
msgid "Registration"
msgstr ""
#: mod/admin.php:970
msgid "File upload"
msgstr ""
#: mod/admin.php:971
msgid "Policies"
msgstr ""
#: mod/admin.php:973
msgid "Auto Discovered Contact Directory"
msgstr ""
#: mod/admin.php:974
msgid "Performance"
msgstr ""
#: mod/admin.php:975
msgid "Worker"
msgstr ""
#: mod/admin.php:976
msgid ""
"Relocate - WARNING: advanced function. Could make this server unreachable."
msgstr ""
#: mod/admin.php:979
msgid "Site name"
msgstr ""
#: mod/admin.php:980
msgid "Host name"
msgstr ""
#: mod/admin.php:981
msgid "Sender Email"
msgstr ""
#: mod/admin.php:981
msgid ""
"The email address your server shall use to send notification emails from."
msgstr ""
#: mod/admin.php:982
msgid "Banner/Logo"
msgstr ""
#: mod/admin.php:983
msgid "Shortcut icon"
msgstr ""
#: mod/admin.php:983
msgid "Link to an icon that will be used for browsers."
msgstr ""
#: mod/admin.php:984
msgid "Touch icon"
msgstr ""
#: mod/admin.php:984
msgid "Link to an icon that will be used for tablets and mobiles."
msgstr ""
#: mod/admin.php:985
msgid "Additional Info"
msgstr ""
#: mod/admin.php:985
#, php-format
msgid ""
"For public servers: you can add additional information here that will be "
"listed at %s/siteinfo."
msgstr ""
#: mod/admin.php:986
msgid "System language"
msgstr ""
#: mod/admin.php:987
msgid "System theme"
msgstr ""
#: mod/admin.php:987
msgid ""
"Default system theme - may be over-ridden by user profiles - <a href='#' "
"id='cnftheme'>change theme settings</a>"
msgstr ""
#: mod/admin.php:988
msgid "Mobile system theme"
msgstr ""
#: mod/admin.php:988
msgid "Theme for mobile devices"
msgstr ""
#: mod/admin.php:989
msgid "SSL link policy"
msgstr ""
#: mod/admin.php:989
msgid "Determines whether generated links should be forced to use SSL"
msgstr ""
#: mod/admin.php:990
msgid "Force SSL"
msgstr ""
#: mod/admin.php:990
msgid ""
"Force all Non-SSL requests to SSL - Attention: on some systems it could lead "
"to endless loops."
msgstr ""
#: mod/admin.php:991
msgid "Hide help entry from navigation menu"
msgstr ""
#: mod/admin.php:991
msgid ""
"Hides the menu entry for the Help pages from the navigation menu. You can "
"still access it calling /help directly."
msgstr ""
#: mod/admin.php:992
msgid "Single user instance"
msgstr ""
#: mod/admin.php:992
msgid "Make this instance multi-user or single-user for the named user"
msgstr ""
#: mod/admin.php:993
msgid "Maximum image size"
msgstr ""
#: mod/admin.php:993
msgid ""
"Maximum size in bytes of uploaded images. Default is 0, which means no "
"limits."
msgstr ""
#: mod/admin.php:994
msgid "Maximum image length"
msgstr ""
#: mod/admin.php:994
msgid ""
"Maximum length in pixels of the longest side of uploaded images. Default is "
"-1, which means no limits."
msgstr ""
#: mod/admin.php:995
msgid "JPEG image quality"
msgstr ""
#: mod/admin.php:995
msgid ""
"Uploaded JPEGS will be saved at this quality setting [0-100]. Default is "
"100, which is full quality."
msgstr ""
#: mod/admin.php:997
msgid "Register policy"
msgstr ""
#: mod/admin.php:998
msgid "Maximum Daily Registrations"
msgstr ""
#: mod/admin.php:998
msgid ""
"If registration is permitted above, this sets the maximum number of new user "
"registrations to accept per day. If register is set to closed, this setting "
"has no effect."
msgstr ""
#: mod/admin.php:999
msgid "Register text"
msgstr ""
#: mod/admin.php:999
msgid "Will be displayed prominently on the registration page."
msgstr ""
#: mod/admin.php:1000
msgid "Accounts abandoned after x days"
msgstr ""
#: mod/admin.php:1000
msgid ""
"Will not waste system resources polling external sites for abandonded "
"accounts. Enter 0 for no time limit."
msgstr ""
#: mod/admin.php:1001
msgid "Allowed friend domains"
msgstr ""
#: mod/admin.php:1001
msgid ""
"Comma separated list of domains which are allowed to establish friendships "
"with this site. Wildcards are accepted. Empty to allow any domains"
msgstr ""
#: mod/admin.php:1002
msgid "Allowed email domains"
msgstr ""
#: mod/admin.php:1002
msgid ""
"Comma separated list of domains which are allowed in email addresses for "
"registrations to this site. Wildcards are accepted. Empty to allow any "
"domains"
msgstr ""
#: mod/admin.php:1003
msgid "Block public"
msgstr ""
#: mod/admin.php:1003
msgid ""
"Check to block public access to all otherwise public personal pages on this "
"site unless you are currently logged in."
msgstr ""
#: mod/admin.php:1004
msgid "Force publish"
msgstr ""
#: mod/admin.php:1004
msgid ""
"Check to force all profiles on this site to be listed in the site directory."
msgstr ""
#: mod/admin.php:1005
msgid "Global directory URL"
msgstr ""
#: mod/admin.php:1005
msgid ""
"URL to the global directory. If this is not set, the global directory is "
"completely unavailable to the application."
msgstr ""
#: mod/admin.php:1006
msgid "Allow threaded items"
msgstr ""
#: mod/admin.php:1006
msgid "Allow infinite level threading for items on this site."
msgstr ""
#: mod/admin.php:1007
msgid "Private posts by default for new users"
msgstr ""
#: mod/admin.php:1007
msgid ""
"Set default post permissions for all new members to the default privacy "
"group rather than public."
msgstr ""
#: mod/admin.php:1008
msgid "Don't include post content in email notifications"
msgstr ""
#: mod/admin.php:1008
msgid ""
"Don't include the content of a post/comment/private message/etc. in the "
"email notifications that are sent out from this site, as a privacy measure."
msgstr ""
#: mod/admin.php:1009
msgid "Disallow public access to addons listed in the apps menu."
msgstr ""
#: mod/admin.php:1009
msgid ""
"Checking this box will restrict addons listed in the apps menu to members "
"only."
msgstr ""
#: mod/admin.php:1010
msgid "Don't embed private images in posts"
msgstr ""
#: mod/admin.php:1010
msgid ""
"Don't replace locally-hosted private photos in posts with an embedded copy "
"of the image. This means that contacts who receive posts containing private "
"photos will have to authenticate and load each image, which may take a while."
msgstr ""
#: mod/admin.php:1011
msgid "Allow Users to set remote_self"
msgstr ""
#: mod/admin.php:1011
msgid ""
"With checking this, every user is allowed to mark every contact as a "
"remote_self in the repair contact dialog. Setting this flag on a contact "
"causes mirroring every posting of that contact in the users stream."
msgstr ""
#: mod/admin.php:1012
msgid "Block multiple registrations"
msgstr ""
#: mod/admin.php:1012
msgid "Disallow users to register additional accounts for use as pages."
msgstr ""
#: mod/admin.php:1013
msgid "OpenID support"
msgstr ""
#: mod/admin.php:1013
msgid "OpenID support for registration and logins."
msgstr ""
#: mod/admin.php:1014
msgid "Fullname check"
msgstr ""
#: mod/admin.php:1014
msgid ""
"Force users to register with a space between firstname and lastname in Full "
"name, as an antispam measure"
msgstr ""
#: mod/admin.php:1015
msgid "UTF-8 Regular expressions"
msgstr ""
#: mod/admin.php:1015
msgid "Use PHP UTF8 regular expressions"
msgstr ""
#: mod/admin.php:1016
msgid "Community Page Style"
msgstr ""
#: mod/admin.php:1016
msgid ""
"Type of community page to show. 'Global community' shows every public "
"posting from an open distributed network that arrived on this server."
msgstr ""
#: mod/admin.php:1017
msgid "Posts per user on community page"
msgstr ""
#: mod/admin.php:1017
msgid ""
"The maximum number of posts per user on the community page. (Not valid for "
"'Global Community')"
msgstr ""
#: mod/admin.php:1018
msgid "Enable OStatus support"
msgstr ""
#: mod/admin.php:1018
msgid ""
"Provide built-in OStatus (StatusNet, GNU Social etc.) compatibility. All "
"communications in OStatus are public, so privacy warnings will be "
"occasionally displayed."
msgstr ""
#: mod/admin.php:1019
msgid "OStatus conversation completion interval"
msgstr ""
#: mod/admin.php:1019
msgid ""
"How often shall the poller check for new entries in OStatus conversations? "
"This can be a very ressource task."
msgstr ""
#: mod/admin.php:1020
msgid "Only import OStatus threads from our contacts"
msgstr ""
#: mod/admin.php:1020
msgid ""
"Normally we import every content from our OStatus contacts. With this option "
"we only store threads that are started by a contact that is known on our "
"system."
msgstr ""
#: mod/admin.php:1021
msgid "OStatus support can only be enabled if threading is enabled."
msgstr ""
#: mod/admin.php:1023
msgid ""
"Diaspora support can't be enabled because Friendica was installed into a sub "
"directory."
msgstr ""
#: mod/admin.php:1024
msgid "Enable Diaspora support"
msgstr ""
#: mod/admin.php:1024
msgid "Provide built-in Diaspora network compatibility."
msgstr ""
#: mod/admin.php:1025
msgid "Only allow Friendica contacts"
msgstr ""
#: mod/admin.php:1025
msgid ""
"All contacts must use Friendica protocols. All other built-in communication "
"protocols disabled."
msgstr ""
#: mod/admin.php:1026
msgid "Verify SSL"
msgstr ""
#: mod/admin.php:1026
msgid ""
"If you wish, you can turn on strict certificate checking. This will mean you "
"cannot connect (at all) to self-signed SSL sites."
msgstr ""
#: mod/admin.php:1027
msgid "Proxy user"
msgstr ""
#: mod/admin.php:1028
msgid "Proxy URL"
msgstr ""
#: mod/admin.php:1029
msgid "Network timeout"
msgstr ""
#: mod/admin.php:1029
msgid "Value is in seconds. Set to 0 for unlimited (not recommended)."
msgstr ""
#: mod/admin.php:1030
msgid "Maximum Load Average"
msgstr ""
#: mod/admin.php:1030
msgid ""
"Maximum system load before delivery and poll processes are deferred - "
"default 50."
msgstr ""
#: mod/admin.php:1031
msgid "Maximum Load Average (Frontend)"
msgstr ""
#: mod/admin.php:1031
msgid "Maximum system load before the frontend quits service - default 50."
msgstr ""
#: mod/admin.php:1032
msgid "Maximum table size for optimization"
msgstr ""
#: mod/admin.php:1032
msgid ""
"Maximum table size (in MB) for the automatic optimization - default 100 MB. "
"Enter -1 to disable it."
msgstr ""
#: mod/admin.php:1033
msgid "Minimum level of fragmentation"
msgstr ""
#: mod/admin.php:1033
msgid ""
"Minimum fragmenation level to start the automatic optimization - default "
"value is 30%."
msgstr ""
#: mod/admin.php:1035
msgid "Periodical check of global contacts"
msgstr ""
#: mod/admin.php:1035
msgid ""
"If enabled, the global contacts are checked periodically for missing or "
"outdated data and the vitality of the contacts and servers."
msgstr ""
#: mod/admin.php:1036
msgid "Days between requery"
msgstr ""
#: mod/admin.php:1036
msgid "Number of days after which a server is requeried for his contacts."
msgstr ""
#: mod/admin.php:1037
msgid "Discover contacts from other servers"
msgstr ""
#: mod/admin.php:1037
msgid ""
"Periodically query other servers for contacts. You can choose between "
"'users': the users on the remote system, 'Global Contacts': active contacts "
"that are known on the system. The fallback is meant for Redmatrix servers "
"and older friendica servers, where global contacts weren't available. The "
"fallback increases the server load, so the recommened setting is 'Users, "
"Global Contacts'."
msgstr ""
#: mod/admin.php:1038
msgid "Timeframe for fetching global contacts"
msgstr ""
#: mod/admin.php:1038
msgid ""
"When the discovery is activated, this value defines the timeframe for the "
"activity of the global contacts that are fetched from other servers."
msgstr ""
#: mod/admin.php:1039
msgid "Search the local directory"
msgstr ""
#: mod/admin.php:1039
msgid ""
"Search the local directory instead of the global directory. When searching "
"locally, every search will be executed on the global directory in the "
"background. This improves the search results when the search is repeated."
msgstr ""
#: mod/admin.php:1041
msgid "Publish server information"
msgstr ""
#: mod/admin.php:1041
msgid ""
"If enabled, general server and usage data will be published. The data "
"contains the name and version of the server, number of users with public "
"profiles, number of posts and the activated protocols and connectors. See <a "
"href='http://the-federation.info/'>the-federation.info</a> for details."
msgstr ""
#: mod/admin.php:1043
msgid "Use MySQL full text engine"
msgstr ""
#: mod/admin.php:1043
msgid ""
"Activates the full text engine. Speeds up search - but can only search for "
"four and more characters."
msgstr ""
#: mod/admin.php:1044
msgid "Suppress Tags"
msgstr ""
#: mod/admin.php:1044
msgid "Suppress showing a list of hashtags at the end of the posting."
msgstr ""
#: mod/admin.php:1045
msgid "Path to item cache"
msgstr ""
#: mod/admin.php:1045
msgid "The item caches buffers generated bbcode and external images."
msgstr ""
#: mod/admin.php:1046
msgid "Cache duration in seconds"
msgstr ""
#: mod/admin.php:1046
msgid ""
"How long should the cache files be hold? Default value is 86400 seconds (One "
"day). To disable the item cache, set the value to -1."
msgstr ""
#: mod/admin.php:1047
msgid "Maximum numbers of comments per post"
msgstr ""
#: mod/admin.php:1047
msgid "How much comments should be shown for each post? Default value is 100."
msgstr ""
#: mod/admin.php:1048
msgid "Temp path"
msgstr ""
#: mod/admin.php:1048
msgid ""
"If you have a restricted system where the webserver can't access the system "
"temp path, enter another path here."
msgstr ""
#: mod/admin.php:1049
msgid "Base path to installation"
msgstr ""
#: mod/admin.php:1049
msgid ""
"If the system cannot detect the correct path to your installation, enter the "
"correct path here. This setting should only be set if you are using a "
"restricted system and symbolic links to your webroot."
msgstr ""
#: mod/admin.php:1050
msgid "Disable picture proxy"
msgstr ""
#: mod/admin.php:1050
msgid ""
"The picture proxy increases performance and privacy. It shouldn't be used on "
"systems with very low bandwith."
msgstr ""
#: mod/admin.php:1051
msgid "Only search in tags"
msgstr ""
#: mod/admin.php:1051
msgid "On large systems the text search can slow down the system extremely."
msgstr ""
#: mod/admin.php:1053
msgid "New base url"
msgstr ""
#: mod/admin.php:1053
msgid ""
"Change base url for this server. Sends relocate message to all DFRN contacts "
"of all users."
msgstr ""
#: mod/admin.php:1055
msgid "RINO Encryption"
msgstr ""
#: mod/admin.php:1055
msgid "Encryption layer between nodes."
msgstr ""
#: mod/admin.php:1056
msgid "Embedly API key"
msgstr ""
#: mod/admin.php:1056
msgid ""
"<a href='http://embed.ly'>Embedly</a> is used to fetch additional data for "
"web pages. This is an optional parameter."
msgstr ""
#: mod/admin.php:1058
msgid "Maximum number of parallel workers"
msgstr ""
#: mod/admin.php:1058
msgid ""
"On shared hosters set this to 2. On larger systems, values of 10 are great. "
"Default value is 4."
msgstr ""
#: mod/admin.php:1059
msgid "Don't use 'proc_open' with the worker"
msgstr ""
#: mod/admin.php:1059
msgid ""
"Enable this if your system doesn't allow the use of 'proc_open'. This can "
"happen on shared hosters. If this is enabled you should increase the "
"frequency of poller calls in your crontab."
msgstr ""
#: mod/admin.php:1060
msgid "Enable fastlane"
msgstr ""
#: mod/admin.php:1060
msgid ""
"When enabed, the fastlane mechanism starts an additional worker if processes "
"with higher priority are blocked by processes of lower priority."
msgstr ""
#: mod/admin.php:1061
msgid "Enable frontend worker"
msgstr ""
#: mod/admin.php:1061
msgid ""
"When enabled the Worker process is triggered when backend access is "
"performed (e.g. messages being delivered). On smaller sites you might want "
"to call yourdomain.tld/worker on a regular basis via an external cron job. "
"You should only enable this option if you cannot utilize cron/scheduled jobs "
"on your server. The worker background process needs to be activated for this."
msgstr ""
#: mod/admin.php:1091
msgid "Update has been marked successful"
msgstr ""
#: mod/admin.php:1099
#, php-format
msgid "Database structure update %s was successfully applied."
msgstr ""
#: mod/admin.php:1102
#, php-format
msgid "Executing of database structure update %s failed with error: %s"
msgstr ""
#: mod/admin.php:1116
#, php-format
msgid "Executing %s failed with error: %s"
msgstr ""
#: mod/admin.php:1119
#, php-format
msgid "Update %s was successfully applied."
msgstr ""
#: mod/admin.php:1122
#, php-format
msgid "Update %s did not return a status. Unknown if it succeeded."
msgstr ""
#: mod/admin.php:1125
#, php-format
msgid "There was no additional update function %s that needed to be called."
msgstr ""
#: mod/admin.php:1145
msgid "No failed updates."
msgstr ""
#: mod/admin.php:1146
msgid "Check database structure"
msgstr ""
#: mod/admin.php:1151
msgid "Failed Updates"
msgstr ""
#: mod/admin.php:1152
msgid ""
"This does not include updates prior to 1139, which did not return a status."
msgstr ""
#: mod/admin.php:1153
msgid "Mark success (if update was manually applied)"
msgstr ""
#: mod/admin.php:1154
msgid "Attempt to execute this update step automatically"
msgstr ""
#: mod/admin.php:1188
#, php-format
msgid ""
"\n"
"\t\t\tDear %1$s,\n"
"\t\t\t\tthe administrator of %2$s has set up an account for you."
msgstr ""
#: mod/admin.php:1191
#, php-format
msgid ""
"\n"
"\t\t\tThe login details are as follows:\n"
"\n"
"\t\t\tSite Location:\t%1$s\n"
"\t\t\tLogin Name:\t\t%2$s\n"
"\t\t\tPassword:\t\t%3$s\n"
"\n"
"\t\t\tYou may change your password from your account \"Settings\" page after "
"logging\n"
"\t\t\tin.\n"
"\n"
"\t\t\tPlease take a few moments to review the other account settings on that "
"page.\n"
"\n"
"\t\t\tYou may also wish to add some basic information to your default "
"profile\n"
"\t\t\t(on the \"Profiles\" page) so that other people can easily find you.\n"
"\n"
"\t\t\tWe recommend setting your full name, adding a profile photo,\n"
"\t\t\tadding some profile \"keywords\" (very useful in making new friends) - "
"and\n"
"\t\t\tperhaps what country you live in; if you do not wish to be more "
"specific\n"
"\t\t\tthan that.\n"
"\n"
"\t\t\tWe fully respect your right to privacy, and none of these items are "
"necessary.\n"
"\t\t\tIf you are new and do not know anybody here, they may help\n"
"\t\t\tyou to make some new and interesting friends.\n"
"\n"
"\t\t\tThank you and welcome to %4$s."
msgstr ""
#: mod/admin.php:1235
#, php-format
msgid "%s user blocked/unblocked"
msgid_plural "%s users blocked/unblocked"
msgstr[0] ""
msgstr[1] ""
#: mod/admin.php:1242
#, php-format
msgid "%s user deleted"
msgid_plural "%s users deleted"
msgstr[0] ""
msgstr[1] ""
#: mod/admin.php:1289
#, php-format
msgid "User '%s' deleted"
msgstr ""
#: mod/admin.php:1297
#, php-format
msgid "User '%s' unblocked"
msgstr ""
#: mod/admin.php:1297
#, php-format
msgid "User '%s' blocked"
msgstr ""
#: mod/admin.php:1405 mod/admin.php:1418 mod/admin.php:1431 mod/admin.php:1447
#: mod/crepair.php:167 mod/settings.php:683 mod/settings.php:709
msgid "Name"
msgstr ""
#: mod/admin.php:1405 mod/admin.php:1431
msgid "Register date"
msgstr ""
#: mod/admin.php:1405 mod/admin.php:1431
msgid "Last login"
msgstr ""
#: mod/admin.php:1405 mod/admin.php:1431
msgid "Last item"
msgstr ""
#: mod/admin.php:1405 mod/settings.php:43
msgid "Account"
msgstr ""
#: mod/admin.php:1414
msgid "Add User"
msgstr ""
#: mod/admin.php:1415
msgid "select all"
msgstr ""
#: mod/admin.php:1416
msgid "User registrations waiting for confirm"
msgstr ""
#: mod/admin.php:1417
msgid "User waiting for permanent deletion"
msgstr ""
#: mod/admin.php:1418
msgid "Request date"
msgstr ""
#: mod/admin.php:1419
msgid "No registrations."
msgstr ""
#: mod/admin.php:1420
msgid "Note from the user"
msgstr ""
#: mod/admin.php:1421 mod/notifications.php:176 mod/notifications.php:255
msgid "Approve"
msgstr ""
#: mod/admin.php:1422
msgid "Deny"
msgstr ""
#: mod/admin.php:1424 mod/contacts.php:613 mod/contacts.php:813
#: mod/contacts.php:991
msgid "Block"
msgstr ""
#: mod/admin.php:1425 mod/contacts.php:613 mod/contacts.php:813
#: mod/contacts.php:991
msgid "Unblock"
msgstr ""
#: mod/admin.php:1426
msgid "Site admin"
msgstr ""
#: mod/admin.php:1427
msgid "Account expired"
msgstr ""
#: mod/admin.php:1430
msgid "New User"
msgstr ""
#: mod/admin.php:1431
msgid "Deleted since"
msgstr ""
#: mod/admin.php:1436
msgid ""
"Selected users will be deleted!\\n\\nEverything these users had posted on "
"this site will be permanently deleted!\\n\\nAre you sure?"
msgstr ""
#: mod/admin.php:1437
msgid ""
"The user {0} will be deleted!\\n\\nEverything this user has posted on this "
"site will be permanently deleted!\\n\\nAre you sure?"
msgstr ""
#: mod/admin.php:1447
msgid "Name of the new user."
msgstr ""
#: mod/admin.php:1448
msgid "Nickname"
msgstr ""
#: mod/admin.php:1448
msgid "Nickname of the new user."
msgstr ""
#: mod/admin.php:1449
msgid "Email address of the new user."
msgstr ""
#: mod/admin.php:1492
#, php-format
msgid "Plugin %s disabled."
msgstr ""
#: mod/admin.php:1496
#, php-format
msgid "Plugin %s enabled."
msgstr ""
#: mod/admin.php:1507 mod/admin.php:1759
msgid "Disable"
msgstr ""
#: mod/admin.php:1509 mod/admin.php:1761
msgid "Enable"
msgstr ""
#: mod/admin.php:1532 mod/admin.php:1808
msgid "Toggle"
msgstr ""
#: mod/admin.php:1540 mod/admin.php:1817
msgid "Author: "
msgstr ""
#: mod/admin.php:1541 mod/admin.php:1818
msgid "Maintainer: "
msgstr ""
#: mod/admin.php:1596
msgid "Reload active plugins"
msgstr ""
#: mod/admin.php:1601
#, php-format
msgid ""
"There are currently no plugins available on your node. You can find the "
"official plugin repository at %1$s and might find other interesting plugins "
"in the open plugin registry at %2$s"
msgstr ""
#: mod/admin.php:1720
msgid "No themes found."
msgstr ""
#: mod/admin.php:1799
msgid "Screenshot"
msgstr ""
#: mod/admin.php:1859
msgid "Reload active themes"
msgstr ""
#: mod/admin.php:1864
#, php-format
msgid "No themes found on the system. They should be paced in %1$s"
msgstr ""
#: mod/admin.php:1865
msgid "[Experimental]"
msgstr ""
#: mod/admin.php:1866
msgid "[Unsupported]"
msgstr ""
#: mod/admin.php:1890
msgid "Log settings updated."
msgstr ""
#: mod/admin.php:1922
msgid "PHP log currently enabled."
msgstr ""
#: mod/admin.php:1924
msgid "PHP log currently disabled."
msgstr ""
#: mod/admin.php:1933
msgid "Clear"
msgstr ""
#: mod/admin.php:1938
msgid "Enable Debugging"
msgstr ""
#: mod/admin.php:1939
msgid "Log file"
msgstr ""
#: mod/admin.php:1939
msgid ""
"Must be writable by web server. Relative to your Friendica top-level "
"directory."
msgstr ""
#: mod/admin.php:1940
msgid "Log level"
msgstr ""
#: mod/admin.php:1943
msgid "PHP logging"
msgstr ""
#: mod/admin.php:1944
msgid ""
"To enable logging of PHP errors and warnings you can add the following to "
"the .htconfig.php file of your installation. The filename set in the "
"'error_log' line is relative to the friendica top-level directory and must "
"be writeable by the web server. The option '1' for 'log_errors' and "
"'display_errors' is to enable these options, set to '0' to disable them."
msgstr ""
#: mod/admin.php:2074 mod/admin.php:2075 mod/settings.php:782
msgid "Off"
msgstr ""
#: mod/admin.php:2074 mod/admin.php:2075 mod/settings.php:782
msgid "On"
msgstr ""
#: mod/admin.php:2075
#, php-format
msgid "Lock feature %s"
msgstr ""
#: mod/admin.php:2083
msgid "Manage Additional Features"
msgstr ""
#: mod/allfriends.php:46
@ -3112,20 +4549,16 @@ msgid ""
"and/or create new posts for you?"
msgstr ""
#: mod/api.php:106 mod/follow.php:113 mod/register.php:246
#: mod/settings.php:1171 mod/settings.php:1177 mod/settings.php:1184
#: mod/settings.php:1188 mod/settings.php:1193 mod/settings.php:1198
#: mod/settings.php:1203 mod/settings.php:1208 mod/settings.php:1234
#: mod/settings.php:1235 mod/settings.php:1236 mod/settings.php:1237
#: mod/settings.php:1238 mod/dfrn_request.php:875 mod/profiles.php:640
#: mod/profiles.php:644 mod/profiles.php:669
#: mod/api.php:106 mod/dfrn_request.php:875 mod/follow.php:113
#: mod/profiles.php:640 mod/profiles.php:644 mod/profiles.php:669
#: mod/register.php:246 mod/settings.php:1171 mod/settings.php:1177
#: mod/settings.php:1184 mod/settings.php:1188 mod/settings.php:1193
#: mod/settings.php:1198 mod/settings.php:1203 mod/settings.php:1208
#: mod/settings.php:1234 mod/settings.php:1235 mod/settings.php:1236
#: mod/settings.php:1237 mod/settings.php:1238
msgid "No"
msgstr ""
#: mod/apps.php:7 index.php:248
msgid "You must be logged in to use addons. "
msgstr ""
#: mod/apps.php:11
msgid "Applications"
msgstr ""
@ -3194,2229 +4627,10 @@ msgstr ""
msgid "The post was created"
msgstr ""
#: mod/common.php:91
msgid "No contacts in common."
msgstr ""
#: mod/common.php:141 mod/contacts.php:871
msgid "Common Friends"
msgstr ""
#: mod/community.php:22 mod/directory.php:37 mod/videos.php:198
#: mod/photos.php:964 mod/dfrn_request.php:799 mod/display.php:200
#: mod/viewcontacts.php:36 mod/search.php:93 mod/search.php:99
msgid "Public access denied."
msgstr ""
#: mod/community.php:27
msgid "Not available."
msgstr ""
#: mod/community.php:66 mod/community.php:75 mod/search.php:224
msgid "No results."
msgstr ""
#: mod/content.php:119 mod/network.php:468
msgid "No such group"
msgstr ""
#: mod/content.php:130 mod/group.php:203 mod/network.php:495
msgid "Group is empty"
msgstr ""
#: mod/content.php:135 mod/network.php:499
#, php-format
msgid "Group: %s"
msgstr ""
#: mod/content.php:325 object/Item.php:96
msgid "This entry was edited"
msgstr ""
#: mod/content.php:621 object/Item.php:444
#, php-format
msgid "%d comment"
msgid_plural "%d comments"
msgstr[0] ""
msgstr[1] ""
#: mod/content.php:638 mod/photos.php:1402 object/Item.php:117
msgid "Private Message"
msgstr ""
#: mod/content.php:702 mod/photos.php:1590 object/Item.php:274
msgid "I like this (toggle)"
msgstr ""
#: mod/content.php:702 object/Item.php:274
msgid "like"
msgstr ""
#: mod/content.php:703 mod/photos.php:1591 object/Item.php:275
msgid "I don't like this (toggle)"
msgstr ""
#: mod/content.php:703 object/Item.php:275
msgid "dislike"
msgstr ""
#: mod/content.php:705 object/Item.php:278
msgid "Share this"
msgstr ""
#: mod/content.php:705 object/Item.php:278
msgid "share"
msgstr ""
#: mod/content.php:725 mod/photos.php:1609 mod/photos.php:1657
#: mod/photos.php:1743 object/Item.php:729
msgid "This is you"
msgstr ""
#: mod/content.php:727 mod/content.php:950 mod/photos.php:1611
#: mod/photos.php:1659 mod/photos.php:1745 object/Item.php:418
#: object/Item.php:731
msgid "Comment"
msgstr ""
#: mod/content.php:728 mod/crepair.php:156 mod/fsuggest.php:108
#: mod/invite.php:142 mod/localtime.php:45 mod/manage.php:145 mod/mood.php:138
#: mod/poke.php:203 mod/contacts.php:585 mod/events.php:513
#: mod/message.php:338 mod/message.php:521 mod/photos.php:1124
#: mod/photos.php:1246 mod/photos.php:1562 mod/photos.php:1612
#: mod/photos.php:1660 mod/photos.php:1746 mod/install.php:276
#: mod/install.php:316 mod/profiles.php:680 object/Item.php:732
#: view/theme/quattro/config.php:67 view/theme/vier/config.php:112
#: view/theme/duepuntozero/config.php:61 view/theme/clean/config.php:87
#: view/theme/frio/config.php:64
msgid "Submit"
msgstr ""
#: mod/content.php:729 object/Item.php:733
msgid "Bold"
msgstr ""
#: mod/content.php:730 object/Item.php:734
msgid "Italic"
msgstr ""
#: mod/content.php:731 object/Item.php:735
msgid "Underline"
msgstr ""
#: mod/content.php:732 object/Item.php:736
msgid "Quote"
msgstr ""
#: mod/content.php:733 object/Item.php:737
msgid "Code"
msgstr ""
#: mod/content.php:734 object/Item.php:738
msgid "Image"
msgstr ""
#: mod/content.php:735 object/Item.php:739
msgid "Link"
msgstr ""
#: mod/content.php:736 object/Item.php:740
msgid "Video"
msgstr ""
#: mod/content.php:746 mod/settings.php:743 object/Item.php:122
#: object/Item.php:124
msgid "Edit"
msgstr ""
#: mod/content.php:772 object/Item.php:238
msgid "add star"
msgstr ""
#: mod/content.php:773 object/Item.php:239
msgid "remove star"
msgstr ""
#: mod/content.php:774 object/Item.php:240
msgid "toggle star status"
msgstr ""
#: mod/content.php:777 object/Item.php:243
msgid "starred"
msgstr ""
#: mod/content.php:778 mod/content.php:800 object/Item.php:263
msgid "add tag"
msgstr ""
#: mod/content.php:789 object/Item.php:251
msgid "ignore thread"
msgstr ""
#: mod/content.php:790 object/Item.php:252
msgid "unignore thread"
msgstr ""
#: mod/content.php:791 object/Item.php:253
msgid "toggle ignore status"
msgstr ""
#: mod/content.php:794 mod/ostatus_subscribe.php:73 object/Item.php:256
msgid "ignored"
msgstr ""
#: mod/content.php:805 object/Item.php:141
msgid "save to folder"
msgstr ""
#: mod/content.php:853 object/Item.php:212
msgid "I will attend"
msgstr ""
#: mod/content.php:853 object/Item.php:212
msgid "I will not attend"
msgstr ""
#: mod/content.php:853 object/Item.php:212
msgid "I might attend"
msgstr ""
#: mod/content.php:917 object/Item.php:384
msgid "to"
msgstr ""
#: mod/content.php:918 object/Item.php:386
msgid "Wall-to-Wall"
msgstr ""
#: mod/content.php:919 object/Item.php:387
msgid "via Wall-To-Wall:"
msgstr ""
#: mod/credits.php:16
msgid "Credits"
msgstr ""
#: mod/credits.php:17
msgid ""
"Friendica is a community project, that would not be possible without the "
"help of many people. Here is a list of those who have contributed to the "
"code or the translation of Friendica. Thank you all!"
msgstr ""
#: mod/crepair.php:89
msgid "Contact settings applied."
msgstr ""
#: mod/crepair.php:91
msgid "Contact update failed."
msgstr ""
#: mod/crepair.php:116 mod/fsuggest.php:21 mod/fsuggest.php:93
#: mod/dfrn_confirm.php:126
msgid "Contact not found."
msgstr ""
#: mod/crepair.php:122
msgid ""
"<strong>WARNING: This is highly advanced</strong> and if you enter incorrect "
"information your communications with this contact may stop working."
msgstr ""
#: mod/crepair.php:123
msgid ""
"Please use your browser 'Back' button <strong>now</strong> if you are "
"uncertain what to do on this page."
msgstr ""
#: mod/crepair.php:136 mod/crepair.php:138
msgid "No mirroring"
msgstr ""
#: mod/crepair.php:136
msgid "Mirror as forwarded posting"
msgstr ""
#: mod/crepair.php:136 mod/crepair.php:138
msgid "Mirror as my own posting"
msgstr ""
#: mod/crepair.php:152
msgid "Return to contact editor"
msgstr ""
#: mod/crepair.php:154
msgid "Refetch contact data"
msgstr ""
#: mod/crepair.php:158
msgid "Remote Self"
msgstr ""
#: mod/crepair.php:161
msgid "Mirror postings from this contact"
msgstr ""
#: mod/crepair.php:163
msgid ""
"Mark this contact as remote_self, this will cause friendica to repost new "
"entries from this contact."
msgstr ""
#: mod/crepair.php:167 mod/settings.php:683 mod/settings.php:709
#: mod/admin.php:1417 mod/admin.php:1430 mod/admin.php:1443 mod/admin.php:1459
msgid "Name"
msgstr ""
#: mod/crepair.php:168
msgid "Account Nickname"
msgstr ""
#: mod/crepair.php:169
msgid "@Tagname - overrides Name/Nickname"
msgstr ""
#: mod/crepair.php:170
msgid "Account URL"
msgstr ""
#: mod/crepair.php:171
msgid "Friend Request URL"
msgstr ""
#: mod/crepair.php:172
msgid "Friend Confirm URL"
msgstr ""
#: mod/crepair.php:173
msgid "Notification Endpoint URL"
msgstr ""
#: mod/crepair.php:174
msgid "Poll/Feed URL"
msgstr ""
#: mod/crepair.php:175
msgid "New photo from this URL"
msgstr ""
#: mod/delegate.php:101
msgid "No potential page delegates located."
msgstr ""
#: mod/delegate.php:132
msgid ""
"Delegates are able to manage all aspects of this account/page except for "
"basic account settings. Please do not delegate your personal account to "
"anybody that you do not trust completely."
msgstr ""
#: mod/delegate.php:133
msgid "Existing Page Managers"
msgstr ""
#: mod/delegate.php:135
msgid "Existing Page Delegates"
msgstr ""
#: mod/delegate.php:137
msgid "Potential Delegates"
msgstr ""
#: mod/delegate.php:139 mod/tagrm.php:95
msgid "Remove"
msgstr ""
#: mod/delegate.php:140
msgid "Add"
msgstr ""
#: mod/delegate.php:141
msgid "No entries."
msgstr ""
#: mod/dfrn_poll.php:104 mod/dfrn_poll.php:539
#, php-format
msgid "%1$s welcomes %2$s"
msgstr ""
#: mod/directory.php:199 view/theme/vier/theme.php:196
msgid "Global Directory"
msgstr ""
#: mod/directory.php:201
msgid "Find on this site"
msgstr ""
#: mod/directory.php:203
msgid "Results for:"
msgstr ""
#: mod/directory.php:205
msgid "Site Directory"
msgstr ""
#: mod/directory.php:212
msgid "No entries (some entries may be hidden)."
msgstr ""
#: mod/dirfind.php:37
#, php-format
msgid "People Search - %s"
msgstr ""
#: mod/dirfind.php:48
#, php-format
msgid "Forum Search - %s"
msgstr ""
#: mod/dirfind.php:245 mod/match.php:109
msgid "No matches"
msgstr ""
#: mod/filer.php:30
msgid "- select -"
msgstr ""
#: mod/follow.php:19 mod/dfrn_request.php:888
msgid "Submit Request"
msgstr ""
#: mod/follow.php:30
msgid "You already added this contact."
msgstr ""
#: mod/follow.php:39
msgid "Diaspora support isn't enabled. Contact can't be added."
msgstr ""
#: mod/follow.php:46
msgid "OStatus support is disabled. Contact can't be added."
msgstr ""
#: mod/follow.php:53
msgid "The network type couldn't be detected. Contact can't be added."
msgstr ""
#: mod/follow.php:112 mod/dfrn_request.php:874
msgid "Please answer the following:"
msgstr ""
#: mod/follow.php:113 mod/dfrn_request.php:875
#, php-format
msgid "Does %s know you?"
msgstr ""
#: mod/follow.php:114 mod/dfrn_request.php:879
msgid "Add a personal note:"
msgstr ""
#: mod/follow.php:120 mod/dfrn_request.php:885
msgid "Your Identity Address:"
msgstr ""
#: mod/follow.php:129 mod/contacts.php:632 mod/notifications.php:249
msgid "Profile URL"
msgstr ""
#: mod/follow.php:186
msgid "Contact added"
msgstr ""
#: mod/fsuggest.php:64
msgid "Friend suggestion sent."
msgstr ""
#: mod/fsuggest.php:98
msgid "Suggest Friends"
msgstr ""
#: mod/fsuggest.php:100
#, php-format
msgid "Suggest a friend for %s"
msgstr ""
#: mod/group.php:29
msgid "Group created."
msgstr ""
#: mod/group.php:35
msgid "Could not create group."
msgstr ""
#: mod/group.php:49 mod/group.php:150
msgid "Group not found."
msgstr ""
#: mod/group.php:63
msgid "Group name changed."
msgstr ""
#: mod/group.php:76 mod/profperm.php:20 index.php:406
msgid "Permission denied"
msgstr ""
#: mod/group.php:91
msgid "Save Group"
msgstr ""
#: mod/group.php:97
msgid "Create a group of contacts/friends."
msgstr ""
#: mod/group.php:122
msgid "Group removed."
msgstr ""
#: mod/group.php:124
msgid "Unable to remove group."
msgstr ""
#: mod/group.php:187
msgid "Group Editor"
msgstr ""
#: mod/group.php:200
msgid "Members"
msgstr ""
#: mod/group.php:202 mod/contacts.php:700
msgid "All Contacts"
msgstr ""
#: mod/group.php:233 mod/profperm.php:107
msgid "Click on a contact to add or remove."
msgstr ""
#: mod/hcard.php:11
msgid "No profile"
msgstr ""
#: mod/help.php:41
msgid "Help:"
msgstr ""
#: mod/help.php:53 mod/fetch.php:12 mod/fetch.php:39 mod/fetch.php:48
#: mod/p.php:16 mod/p.php:43 mod/p.php:52 index.php:292
msgid "Not Found"
msgstr ""
#: mod/help.php:56 index.php:295
msgid "Page not found."
msgstr ""
#: mod/home.php:39
#, php-format
msgid "Welcome to %s"
msgstr ""
#: mod/invite.php:28
msgid "Total invitation limit exceeded."
msgstr ""
#: mod/invite.php:51
#, php-format
msgid "%s : Not a valid email address."
msgstr ""
#: mod/invite.php:76
msgid "Please join us on Friendica"
msgstr ""
#: mod/invite.php:87
msgid "Invitation limit exceeded. Please contact your site administrator."
msgstr ""
#: mod/invite.php:91
#, php-format
msgid "%s : Message delivery failed."
msgstr ""
#: mod/invite.php:95
#, php-format
msgid "%d message sent."
msgid_plural "%d messages sent."
msgstr[0] ""
msgstr[1] ""
#: mod/invite.php:114
msgid "You have no more invitations available"
msgstr ""
#: mod/invite.php:122
#, php-format
msgid ""
"Visit %s for a list of public sites that you can join. Friendica members on "
"other sites can all connect with each other, as well as with members of many "
"other social networks."
msgstr ""
#: mod/invite.php:124
#, php-format
msgid ""
"To accept this invitation, please visit and register at %s or any other "
"public Friendica website."
msgstr ""
#: mod/invite.php:125
#, php-format
msgid ""
"Friendica sites all inter-connect to create a huge privacy-enhanced social "
"web that is owned and controlled by its members. They can also connect with "
"many traditional social networks. See %s for a list of alternate Friendica "
"sites you can join."
msgstr ""
#: mod/invite.php:128
msgid ""
"Our apologies. This system is not currently configured to connect with other "
"public sites or invite members."
msgstr ""
#: mod/invite.php:134
msgid "Send invitations"
msgstr ""
#: mod/invite.php:135
msgid "Enter email addresses, one per line:"
msgstr ""
#: mod/invite.php:136 mod/message.php:332 mod/message.php:515
#: mod/wallmessage.php:135
msgid "Your message:"
msgstr ""
#: mod/invite.php:137
msgid ""
"You are cordially invited to join me and other close friends on Friendica - "
"and help us to create a better social web."
msgstr ""
#: mod/invite.php:139
msgid "You will need to supply this invitation code: $invite_code"
msgstr ""
#: mod/invite.php:139
msgid ""
"Once you have registered, please connect with me via my profile page at:"
msgstr ""
#: mod/invite.php:141
msgid ""
"For more information about the Friendica project and why we feel it is "
"important, please visit http://friendica.com"
msgstr ""
#: mod/localtime.php:24
msgid "Time Conversion"
msgstr ""
#: mod/localtime.php:26
msgid ""
"Friendica provides this service for sharing events with other networks and "
"friends in unknown timezones."
msgstr ""
#: mod/localtime.php:30
#, php-format
msgid "UTC time: %s"
msgstr ""
#: mod/localtime.php:33
#, php-format
msgid "Current timezone: %s"
msgstr ""
#: mod/localtime.php:36
#, php-format
msgid "Converted localtime: %s"
msgstr ""
#: mod/localtime.php:41
msgid "Please select your timezone:"
msgstr ""
#: mod/lockview.php:32 mod/lockview.php:40
msgid "Remote privacy information not available."
msgstr ""
#: mod/lockview.php:49
msgid "Visible to:"
msgstr ""
#: mod/lostpass.php:19
msgid "No valid account found."
msgstr ""
#: mod/lostpass.php:35
msgid "Password reset request issued. Check your email."
msgstr ""
#: mod/lostpass.php:41
#, php-format
msgid ""
"\n"
"\t\tDear %1$s,\n"
"\t\t\tA request was recently received at \"%2$s\" to reset your account\n"
"\t\tpassword. In order to confirm this request, please select the "
"verification link\n"
"\t\tbelow or paste it into your web browser address bar.\n"
"\n"
"\t\tIf you did NOT request this change, please DO NOT follow the link\n"
"\t\tprovided and ignore and/or delete this email.\n"
"\n"
"\t\tYour password will not be changed unless we can verify that you\n"
"\t\tissued this request."
msgstr ""
#: mod/lostpass.php:52
#, php-format
msgid ""
"\n"
"\t\tFollow this link to verify your identity:\n"
"\n"
"\t\t%1$s\n"
"\n"
"\t\tYou will then receive a follow-up message containing the new password.\n"
"\t\tYou may change that password from your account settings page after "
"logging in.\n"
"\n"
"\t\tThe login details are as follows:\n"
"\n"
"\t\tSite Location:\t%2$s\n"
"\t\tLogin Name:\t%3$s"
msgstr ""
#: mod/lostpass.php:71
#, php-format
msgid "Password reset requested at %s"
msgstr ""
#: mod/lostpass.php:91
msgid ""
"Request could not be verified. (You may have previously submitted it.) "
"Password reset failed."
msgstr ""
#: mod/lostpass.php:110 boot.php:1848
msgid "Password Reset"
msgstr ""
#: mod/lostpass.php:111
msgid "Your password has been reset as requested."
msgstr ""
#: mod/lostpass.php:112
msgid "Your new password is"
msgstr ""
#: mod/lostpass.php:113
msgid "Save or copy your new password - and then"
msgstr ""
#: mod/lostpass.php:114
msgid "click here to login"
msgstr ""
#: mod/lostpass.php:115
msgid ""
"Your password may be changed from the <em>Settings</em> page after "
"successful login."
msgstr ""
#: mod/lostpass.php:125
#, php-format
msgid ""
"\n"
"\t\t\t\tDear %1$s,\n"
"\t\t\t\t\tYour password has been changed as requested. Please retain this\n"
"\t\t\t\tinformation for your records (or change your password immediately "
"to\n"
"\t\t\t\tsomething that you will remember).\n"
"\t\t\t"
msgstr ""
#: mod/lostpass.php:131
#, php-format
msgid ""
"\n"
"\t\t\t\tYour login details are as follows:\n"
"\n"
"\t\t\t\tSite Location:\t%1$s\n"
"\t\t\t\tLogin Name:\t%2$s\n"
"\t\t\t\tPassword:\t%3$s\n"
"\n"
"\t\t\t\tYou may change that password from your account settings page after "
"logging in.\n"
"\t\t\t"
msgstr ""
#: mod/lostpass.php:147
#, php-format
msgid "Your password has been changed at %s"
msgstr ""
#: mod/lostpass.php:159
msgid "Forgot your Password?"
msgstr ""
#: mod/lostpass.php:160
msgid ""
"Enter your email address and submit to have your password reset. Then check "
"your email for further instructions."
msgstr ""
#: mod/lostpass.php:161 boot.php:1836
msgid "Nickname or Email: "
msgstr ""
#: mod/lostpass.php:162
msgid "Reset"
msgstr ""
#: mod/maintenance.php:9
msgid "System down for maintenance"
msgstr ""
#: mod/manage.php:141
msgid "Manage Identities and/or Pages"
msgstr ""
#: mod/manage.php:142
msgid ""
"Toggle between different identities or community/group pages which share "
"your account details or which you have been granted \"manage\" permissions"
msgstr ""
#: mod/manage.php:143
msgid "Select an identity to manage: "
msgstr ""
#: mod/match.php:35
msgid "No keywords to match. Please add keywords to your default profile."
msgstr ""
#: mod/match.php:88
msgid "is interested in:"
msgstr ""
#: mod/match.php:102
msgid "Profile Match"
msgstr ""
#: mod/mood.php:134
msgid "Mood"
msgstr ""
#: mod/mood.php:135
msgid "Set your current mood and tell your friends"
msgstr ""
#: mod/newmember.php:6
msgid "Welcome to Friendica"
msgstr ""
#: mod/newmember.php:8
msgid "New Member Checklist"
msgstr ""
#: mod/newmember.php:12
msgid ""
"We would like to offer some tips and links to help make your experience "
"enjoyable. Click any item to visit the relevant page. A link to this page "
"will be visible from your home page for two weeks after your initial "
"registration and then will quietly disappear."
msgstr ""
#: mod/newmember.php:14
msgid "Getting Started"
msgstr ""
#: mod/newmember.php:18
msgid "Friendica Walk-Through"
msgstr ""
#: mod/newmember.php:18
msgid ""
"On your <em>Quick Start</em> page - find a brief introduction to your "
"profile and network tabs, make some new connections, and find some groups to "
"join."
msgstr ""
#: mod/newmember.php:26
msgid "Go to Your Settings"
msgstr ""
#: mod/newmember.php:26
msgid ""
"On your <em>Settings</em> page - change your initial password. Also make a "
"note of your Identity Address. This looks just like an email address - and "
"will be useful in making friends on the free social web."
msgstr ""
#: mod/newmember.php:28
msgid ""
"Review the other settings, particularly the privacy settings. An unpublished "
"directory listing is like having an unlisted phone number. In general, you "
"should probably publish your listing - unless all of your friends and "
"potential friends know exactly how to find you."
msgstr ""
#: mod/newmember.php:36 mod/profile_photo.php:256 mod/profiles.php:699
msgid "Upload Profile Photo"
msgstr ""
#: mod/newmember.php:36
msgid ""
"Upload a profile photo if you have not done so already. Studies have shown "
"that people with real photos of themselves are ten times more likely to make "
"friends than people who do not."
msgstr ""
#: mod/newmember.php:38
msgid "Edit Your Profile"
msgstr ""
#: mod/newmember.php:38
msgid ""
"Edit your <strong>default</strong> profile to your liking. Review the "
"settings for hiding your list of friends and hiding the profile from unknown "
"visitors."
msgstr ""
#: mod/newmember.php:40
msgid "Profile Keywords"
msgstr ""
#: mod/newmember.php:40
msgid ""
"Set some public keywords for your default profile which describe your "
"interests. We may be able to find other people with similar interests and "
"suggest friendships."
msgstr ""
#: mod/newmember.php:44
msgid "Connecting"
msgstr ""
#: mod/newmember.php:51
msgid "Importing Emails"
msgstr ""
#: mod/newmember.php:51
msgid ""
"Enter your email access information on your Connector Settings page if you "
"wish to import and interact with friends or mailing lists from your email "
"INBOX"
msgstr ""
#: mod/newmember.php:53
msgid "Go to Your Contacts Page"
msgstr ""
#: mod/newmember.php:53
msgid ""
"Your Contacts page is your gateway to managing friendships and connecting "
"with friends on other networks. Typically you enter their address or site "
"URL in the <em>Add New Contact</em> dialog."
msgstr ""
#: mod/newmember.php:55
msgid "Go to Your Site's Directory"
msgstr ""
#: mod/newmember.php:55
msgid ""
"The Directory page lets you find other people in this network or other "
"federated sites. Look for a <em>Connect</em> or <em>Follow</em> link on "
"their profile page. Provide your own Identity Address if requested."
msgstr ""
#: mod/newmember.php:57
msgid "Finding New People"
msgstr ""
#: mod/newmember.php:57
msgid ""
"On the side panel of the Contacts page are several tools to find new "
"friends. We can match people by interest, look up people by name or "
"interest, and provide suggestions based on network relationships. On a brand "
"new site, friend suggestions will usually begin to be populated within 24 "
"hours."
msgstr ""
#: mod/newmember.php:65
msgid "Group Your Contacts"
msgstr ""
#: mod/newmember.php:65
msgid ""
"Once you have made some friends, organize them into private conversation "
"groups from the sidebar of your Contacts page and then you can interact with "
"each group privately on your Network page."
msgstr ""
#: mod/newmember.php:68
msgid "Why Aren't My Posts Public?"
msgstr ""
#: mod/newmember.php:68
msgid ""
"Friendica respects your privacy. By default, your posts will only show up to "
"people you've added as friends. For more information, see the help section "
"from the link above."
msgstr ""
#: mod/newmember.php:73
msgid "Getting Help"
msgstr ""
#: mod/newmember.php:77
msgid "Go to the Help Section"
msgstr ""
#: mod/newmember.php:77
msgid ""
"Our <strong>help</strong> pages may be consulted for detail on other program "
"features and resources."
msgstr ""
#: mod/nogroup.php:43 mod/contacts.php:594 mod/contacts.php:938
#: mod/viewcontacts.php:102
#, php-format
msgid "Visit %s's profile [%s]"
msgstr ""
#: mod/nogroup.php:44 mod/contacts.php:939
msgid "Edit contact"
msgstr ""
#: mod/nogroup.php:65
msgid "Contacts who are not members of a group"
msgstr ""
#: mod/notify.php:65
msgid "No more system notifications."
msgstr ""
#: mod/notify.php:69 mod/notifications.php:111
msgid "System Notifications"
msgstr ""
#: mod/oexchange.php:21
msgid "Post successful."
msgstr ""
#: mod/openid.php:24
msgid "OpenID protocol error. No ID returned."
msgstr ""
#: mod/openid.php:60
msgid ""
"Account not found and OpenID registration is not permitted on this site."
msgstr ""
#: mod/ostatus_subscribe.php:14
msgid "Subscribing to OStatus contacts"
msgstr ""
#: mod/ostatus_subscribe.php:25
msgid "No contact provided."
msgstr ""
#: mod/ostatus_subscribe.php:31
msgid "Couldn't fetch information for contact."
msgstr ""
#: mod/ostatus_subscribe.php:40
msgid "Couldn't fetch friends for contact."
msgstr ""
#: mod/ostatus_subscribe.php:54 mod/repair_ostatus.php:44
msgid "Done"
msgstr ""
#: mod/ostatus_subscribe.php:68
msgid "success"
msgstr ""
#: mod/ostatus_subscribe.php:70
msgid "failed"
msgstr ""
#: mod/ostatus_subscribe.php:78 mod/repair_ostatus.php:50
msgid "Keep this window open until done."
msgstr ""
#: mod/poke.php:196
msgid "Poke/Prod"
msgstr ""
#: mod/poke.php:197
msgid "poke, prod or do other things to somebody"
msgstr ""
#: mod/poke.php:198
msgid "Recipient"
msgstr ""
#: mod/poke.php:199
msgid "Choose what you wish to do to recipient"
msgstr ""
#: mod/poke.php:202
msgid "Make this post private"
msgstr ""
#: mod/profile.php:154 mod/cal.php:143 mod/display.php:328
#: mod/cal.php:143 mod/display.php:328 mod/profile.php:154
msgid "Access to this profile has been restricted."
msgstr ""
#: mod/profile.php:174
msgid "Tips for New Members"
msgstr ""
#: mod/profile_photo.php:44
msgid "Image uploaded but image cropping failed."
msgstr ""
#: mod/profile_photo.php:77 mod/profile_photo.php:85 mod/profile_photo.php:93
#: mod/profile_photo.php:323
#, php-format
msgid "Image size reduction [%s] failed."
msgstr ""
#: mod/profile_photo.php:127
msgid ""
"Shift-reload the page or clear browser cache if the new photo does not "
"display immediately."
msgstr ""
#: mod/profile_photo.php:137
msgid "Unable to process image"
msgstr ""
#: mod/profile_photo.php:156 mod/wall_upload.php:151 mod/photos.php:803
#, php-format
msgid "Image exceeds size limit of %s"
msgstr ""
#: mod/profile_photo.php:165 mod/wall_upload.php:186 mod/photos.php:844
msgid "Unable to process image."
msgstr ""
#: mod/profile_photo.php:254
msgid "Upload File:"
msgstr ""
#: mod/profile_photo.php:255
msgid "Select a profile:"
msgstr ""
#: mod/profile_photo.php:257
msgid "Upload"
msgstr ""
#: mod/profile_photo.php:260
msgid "or"
msgstr ""
#: mod/profile_photo.php:260
msgid "skip this step"
msgstr ""
#: mod/profile_photo.php:260
msgid "select a photo from your photo albums"
msgstr ""
#: mod/profile_photo.php:274
msgid "Crop Image"
msgstr ""
#: mod/profile_photo.php:275
msgid "Please adjust the image cropping for optimum viewing."
msgstr ""
#: mod/profile_photo.php:277
msgid "Done Editing"
msgstr ""
#: mod/profile_photo.php:313
msgid "Image uploaded successfully."
msgstr ""
#: mod/profile_photo.php:315 mod/wall_upload.php:219 mod/photos.php:871
msgid "Image upload failed."
msgstr ""
#: mod/profperm.php:26 mod/profperm.php:57
msgid "Invalid profile identifier."
msgstr ""
#: mod/profperm.php:103
msgid "Profile Visibility Editor"
msgstr ""
#: mod/profperm.php:116
msgid "Visible To"
msgstr ""
#: mod/profperm.php:132
msgid "All Contacts (with secure profile access)"
msgstr ""
#: mod/register.php:93
msgid ""
"Registration successful. Please check your email for further instructions."
msgstr ""
#: mod/register.php:98
#, php-format
msgid ""
"Failed to send email message. Here your accout details:<br> login: %s<br> "
"password: %s<br><br>You can change your password after login."
msgstr ""
#: mod/register.php:105
msgid "Registration successful."
msgstr ""
#: mod/register.php:111
msgid "Your registration can not be processed."
msgstr ""
#: mod/register.php:160
msgid "Your registration is pending approval by the site owner."
msgstr ""
#: mod/register.php:198 mod/uimport.php:51
msgid ""
"This site has exceeded the number of allowed daily account registrations. "
"Please try again tomorrow."
msgstr ""
#: mod/register.php:226
msgid ""
"You may (optionally) fill in this form via OpenID by supplying your OpenID "
"and clicking 'Register'."
msgstr ""
#: mod/register.php:227
msgid ""
"If you are not familiar with OpenID, please leave that field blank and fill "
"in the rest of the items."
msgstr ""
#: mod/register.php:228
msgid "Your OpenID (optional): "
msgstr ""
#: mod/register.php:242
msgid "Include your profile in member directory?"
msgstr ""
#: mod/register.php:267
msgid "Note for the admin"
msgstr ""
#: mod/register.php:267
msgid "Leave a message for the admin, why you want to join this node"
msgstr ""
#: mod/register.php:268
msgid "Membership on this site is by invitation only."
msgstr ""
#: mod/register.php:269
msgid "Your invitation ID: "
msgstr ""
#: mod/register.php:272 mod/admin.php:977
msgid "Registration"
msgstr ""
#: mod/register.php:280
msgid "Your Full Name (e.g. Joe Smith, real or real-looking): "
msgstr ""
#: mod/register.php:281
msgid "Your Email Address: "
msgstr ""
#: mod/register.php:283 mod/settings.php:1278
msgid "New Password:"
msgstr ""
#: mod/register.php:283
msgid "Leave empty for an auto generated password."
msgstr ""
#: mod/register.php:284 mod/settings.php:1279
msgid "Confirm:"
msgstr ""
#: mod/register.php:285
msgid ""
"Choose a profile nickname. This must begin with a text character. Your "
"profile address on this site will then be '<strong>nickname@$sitename</"
"strong>'."
msgstr ""
#: mod/register.php:286
msgid "Choose a nickname: "
msgstr ""
#: mod/register.php:295 mod/uimport.php:66
msgid "Import"
msgstr ""
#: mod/register.php:296
msgid "Import your profile to this friendica instance"
msgstr ""
#: mod/regmod.php:58
msgid "Account approved."
msgstr ""
#: mod/regmod.php:95
#, php-format
msgid "Registration revoked for %s"
msgstr ""
#: mod/regmod.php:107
msgid "Please login."
msgstr ""
#: mod/removeme.php:52 mod/removeme.php:55
msgid "Remove My Account"
msgstr ""
#: mod/removeme.php:53
msgid ""
"This will completely remove your account. Once this has been done it is not "
"recoverable."
msgstr ""
#: mod/removeme.php:54
msgid "Please enter your password for verification:"
msgstr ""
#: mod/repair_ostatus.php:14
msgid "Resubscribing to OStatus contacts"
msgstr ""
#: mod/repair_ostatus.php:30
msgid "Error"
msgstr ""
#: mod/settings.php:36 mod/photos.php:107
msgid "everybody"
msgstr ""
#: mod/settings.php:43 mod/admin.php:1417
msgid "Account"
msgstr ""
#: mod/settings.php:52 mod/admin.php:161
msgid "Additional features"
msgstr ""
#: mod/settings.php:60
msgid "Display"
msgstr ""
#: mod/settings.php:67 mod/settings.php:890
msgid "Social Networks"
msgstr ""
#: mod/settings.php:74 mod/admin.php:159 mod/admin.php:1543 mod/admin.php:1606
msgid "Plugins"
msgstr ""
#: mod/settings.php:88
msgid "Connected apps"
msgstr ""
#: mod/settings.php:95 mod/uexport.php:45
msgid "Export personal data"
msgstr ""
#: mod/settings.php:102
msgid "Remove account"
msgstr ""
#: mod/settings.php:157
msgid "Missing some important data!"
msgstr ""
#: mod/settings.php:160 mod/settings.php:707 mod/contacts.php:812
msgid "Update"
msgstr ""
#: mod/settings.php:271
msgid "Failed to connect with email account using the settings provided."
msgstr ""
#: mod/settings.php:276
msgid "Email settings updated."
msgstr ""
#: mod/settings.php:291
msgid "Features updated"
msgstr ""
#: mod/settings.php:361
msgid "Relocate message has been send to your contacts"
msgstr ""
#: mod/settings.php:380
msgid "Empty passwords are not allowed. Password unchanged."
msgstr ""
#: mod/settings.php:388
msgid "Wrong password."
msgstr ""
#: mod/settings.php:399
msgid "Password changed."
msgstr ""
#: mod/settings.php:401
msgid "Password update failed. Please try again."
msgstr ""
#: mod/settings.php:481
msgid " Please use a shorter name."
msgstr ""
#: mod/settings.php:483
msgid " Name too short."
msgstr ""
#: mod/settings.php:492
msgid "Wrong Password"
msgstr ""
#: mod/settings.php:497
msgid " Not valid email."
msgstr ""
#: mod/settings.php:503
msgid " Cannot change to that email."
msgstr ""
#: mod/settings.php:559
msgid "Private forum has no privacy permissions. Using default privacy group."
msgstr ""
#: mod/settings.php:563
msgid "Private forum has no privacy permissions and no default privacy group."
msgstr ""
#: mod/settings.php:603
msgid "Settings updated."
msgstr ""
#: mod/settings.php:680 mod/settings.php:706 mod/settings.php:742
msgid "Add application"
msgstr ""
#: mod/settings.php:681 mod/settings.php:792 mod/settings.php:841
#: mod/settings.php:908 mod/settings.php:1005 mod/settings.php:1271
#: mod/admin.php:976 mod/admin.php:1607 mod/admin.php:1864 mod/admin.php:1938
#: mod/admin.php:2088
msgid "Save Settings"
msgstr ""
#: mod/settings.php:684 mod/settings.php:710
msgid "Consumer Key"
msgstr ""
#: mod/settings.php:685 mod/settings.php:711
msgid "Consumer Secret"
msgstr ""
#: mod/settings.php:686 mod/settings.php:712
msgid "Redirect"
msgstr ""
#: mod/settings.php:687 mod/settings.php:713
msgid "Icon url"
msgstr ""
#: mod/settings.php:698
msgid "You can't edit this application."
msgstr ""
#: mod/settings.php:741
msgid "Connected Apps"
msgstr ""
#: mod/settings.php:745
msgid "Client key starts with"
msgstr ""
#: mod/settings.php:746
msgid "No name"
msgstr ""
#: mod/settings.php:747
msgid "Remove authorization"
msgstr ""
#: mod/settings.php:759
msgid "No Plugin settings configured"
msgstr ""
#: mod/settings.php:768
msgid "Plugin Settings"
msgstr ""
#: mod/settings.php:782 mod/admin.php:2077 mod/admin.php:2078
msgid "Off"
msgstr ""
#: mod/settings.php:782 mod/admin.php:2077 mod/admin.php:2078
msgid "On"
msgstr ""
#: mod/settings.php:790
msgid "Additional Features"
msgstr ""
#: mod/settings.php:800 mod/settings.php:804
msgid "General Social Media Settings"
msgstr ""
#: mod/settings.php:810
msgid "Disable intelligent shortening"
msgstr ""
#: mod/settings.php:812
msgid ""
"Normally the system tries to find the best link to add to shortened posts. "
"If this option is enabled then every shortened post will always point to the "
"original friendica post."
msgstr ""
#: mod/settings.php:818
msgid "Automatically follow any GNU Social (OStatus) followers/mentioners"
msgstr ""
#: mod/settings.php:820
msgid ""
"If you receive a message from an unknown OStatus user, this option decides "
"what to do. If it is checked, a new contact will be created for every "
"unknown user."
msgstr ""
#: mod/settings.php:826
msgid "Default group for OStatus contacts"
msgstr ""
#: mod/settings.php:834
msgid "Your legacy GNU Social account"
msgstr ""
#: mod/settings.php:836
msgid ""
"If you enter your old GNU Social/Statusnet account name here (in the format "
"user@domain.tld), your contacts will be added automatically. The field will "
"be emptied when done."
msgstr ""
#: mod/settings.php:839
msgid "Repair OStatus subscriptions"
msgstr ""
#: mod/settings.php:848 mod/settings.php:849
#, php-format
msgid "Built-in support for %s connectivity is %s"
msgstr ""
#: mod/settings.php:848 mod/settings.php:849
msgid "enabled"
msgstr ""
#: mod/settings.php:848 mod/settings.php:849
msgid "disabled"
msgstr ""
#: mod/settings.php:849
msgid "GNU Social (OStatus)"
msgstr ""
#: mod/settings.php:883
msgid "Email access is disabled on this site."
msgstr ""
#: mod/settings.php:895
msgid "Email/Mailbox Setup"
msgstr ""
#: mod/settings.php:896
msgid ""
"If you wish to communicate with email contacts using this service "
"(optional), please specify how to connect to your mailbox."
msgstr ""
#: mod/settings.php:897
msgid "Last successful email check:"
msgstr ""
#: mod/settings.php:899
msgid "IMAP server name:"
msgstr ""
#: mod/settings.php:900
msgid "IMAP port:"
msgstr ""
#: mod/settings.php:901
msgid "Security:"
msgstr ""
#: mod/settings.php:901 mod/settings.php:906
msgid "None"
msgstr ""
#: mod/settings.php:902
msgid "Email login name:"
msgstr ""
#: mod/settings.php:903
msgid "Email password:"
msgstr ""
#: mod/settings.php:904
msgid "Reply-to address:"
msgstr ""
#: mod/settings.php:905
msgid "Send public posts to all email contacts:"
msgstr ""
#: mod/settings.php:906
msgid "Action after import:"
msgstr ""
#: mod/settings.php:906
msgid "Move to folder"
msgstr ""
#: mod/settings.php:907
msgid "Move to folder:"
msgstr ""
#: mod/settings.php:943 mod/admin.php:863
msgid "No special theme for mobile devices"
msgstr ""
#: mod/settings.php:1003
msgid "Display Settings"
msgstr ""
#: mod/settings.php:1009 mod/settings.php:1032
msgid "Display Theme:"
msgstr ""
#: mod/settings.php:1010
msgid "Mobile Theme:"
msgstr ""
#: mod/settings.php:1011
msgid "Suppress warning of insecure networks"
msgstr ""
#: mod/settings.php:1011
msgid ""
"Should the system suppress the warning that the current group contains "
"members of networks that can't receive non public postings."
msgstr ""
#: mod/settings.php:1012
msgid "Update browser every xx seconds"
msgstr ""
#: mod/settings.php:1012
msgid "Minimum of 10 seconds. Enter -1 to disable it."
msgstr ""
#: mod/settings.php:1013
msgid "Number of items to display per page:"
msgstr ""
#: mod/settings.php:1013 mod/settings.php:1014
msgid "Maximum of 100 items"
msgstr ""
#: mod/settings.php:1014
msgid "Number of items to display per page when viewed from mobile device:"
msgstr ""
#: mod/settings.php:1015
msgid "Don't show emoticons"
msgstr ""
#: mod/settings.php:1016
msgid "Calendar"
msgstr ""
#: mod/settings.php:1017
msgid "Beginning of week:"
msgstr ""
#: mod/settings.php:1018
msgid "Don't show notices"
msgstr ""
#: mod/settings.php:1019
msgid "Infinite scroll"
msgstr ""
#: mod/settings.php:1020
msgid "Automatic updates only at the top of the network page"
msgstr ""
#: mod/settings.php:1021
msgid "Bandwith Saver Mode"
msgstr ""
#: mod/settings.php:1021
msgid ""
"When enabled, embedded content is not displayed on automatic updates, they "
"only show on page reload."
msgstr ""
#: mod/settings.php:1023
msgid "General Theme Settings"
msgstr ""
#: mod/settings.php:1024
msgid "Custom Theme Settings"
msgstr ""
#: mod/settings.php:1025
msgid "Content Settings"
msgstr ""
#: mod/settings.php:1026 view/theme/quattro/config.php:69
#: view/theme/vier/config.php:114 view/theme/duepuntozero/config.php:63
#: view/theme/clean/config.php:89 view/theme/frio/config.php:66
msgid "Theme settings"
msgstr ""
#: mod/settings.php:1110
msgid "Account Types"
msgstr ""
#: mod/settings.php:1111
msgid "Personal Page Subtypes"
msgstr ""
#: mod/settings.php:1112
msgid "Community Forum Subtypes"
msgstr ""
#: mod/settings.php:1119
msgid "Personal Page"
msgstr ""
#: mod/settings.php:1120
msgid "This account is a regular personal profile"
msgstr ""
#: mod/settings.php:1123
msgid "Organisation Page"
msgstr ""
#: mod/settings.php:1124
msgid "This account is a profile for an organisation"
msgstr ""
#: mod/settings.php:1127
msgid "News Page"
msgstr ""
#: mod/settings.php:1128
msgid "This account is a news account/reflector"
msgstr ""
#: mod/settings.php:1131
msgid "Community Forum"
msgstr ""
#: mod/settings.php:1132
msgid ""
"This account is a community forum where people can discuss with each other"
msgstr ""
#: mod/settings.php:1135
msgid "Normal Account Page"
msgstr ""
#: mod/settings.php:1136
msgid "This account is a normal personal profile"
msgstr ""
#: mod/settings.php:1139
msgid "Soapbox Page"
msgstr ""
#: mod/settings.php:1140
msgid "Automatically approve all connection/friend requests as read-only fans"
msgstr ""
#: mod/settings.php:1143
msgid "Public Forum"
msgstr ""
#: mod/settings.php:1144
msgid "Automatically approve all contact requests"
msgstr ""
#: mod/settings.php:1147
msgid "Automatic Friend Page"
msgstr ""
#: mod/settings.php:1148
msgid "Automatically approve all connection/friend requests as friends"
msgstr ""
#: mod/settings.php:1151
msgid "Private Forum [Experimental]"
msgstr ""
#: mod/settings.php:1152
msgid "Private forum - approved members only"
msgstr ""
#: mod/settings.php:1163
msgid "OpenID:"
msgstr ""
#: mod/settings.php:1163
msgid "(Optional) Allow this OpenID to login to this account."
msgstr ""
#: mod/settings.php:1171
msgid "Publish your default profile in your local site directory?"
msgstr ""
#: mod/settings.php:1177
msgid "Publish your default profile in the global social directory?"
msgstr ""
#: mod/settings.php:1184
msgid "Hide your contact/friend list from viewers of your default profile?"
msgstr ""
#: mod/settings.php:1188
msgid ""
"If enabled, posting public messages to Diaspora and other networks isn't "
"possible."
msgstr ""
#: mod/settings.php:1193
msgid "Allow friends to post to your profile page?"
msgstr ""
#: mod/settings.php:1198
msgid "Allow friends to tag your posts?"
msgstr ""
#: mod/settings.php:1203
msgid "Allow us to suggest you as a potential friend to new members?"
msgstr ""
#: mod/settings.php:1208
msgid "Permit unknown people to send you private mail?"
msgstr ""
#: mod/settings.php:1216
msgid "Profile is <strong>not published</strong>."
msgstr ""
#: mod/settings.php:1224
#, php-format
msgid "Your Identity Address is <strong>'%s'</strong> or '%s'."
msgstr ""
#: mod/settings.php:1231
msgid "Automatically expire posts after this many days:"
msgstr ""
#: mod/settings.php:1231
msgid "If empty, posts will not expire. Expired posts will be deleted"
msgstr ""
#: mod/settings.php:1232
msgid "Advanced expiration settings"
msgstr ""
#: mod/settings.php:1233
msgid "Advanced Expiration"
msgstr ""
#: mod/settings.php:1234
msgid "Expire posts:"
msgstr ""
#: mod/settings.php:1235
msgid "Expire personal notes:"
msgstr ""
#: mod/settings.php:1236
msgid "Expire starred posts:"
msgstr ""
#: mod/settings.php:1237
msgid "Expire photos:"
msgstr ""
#: mod/settings.php:1238
msgid "Only expire posts by others:"
msgstr ""
#: mod/settings.php:1269
msgid "Account Settings"
msgstr ""
#: mod/settings.php:1277
msgid "Password Settings"
msgstr ""
#: mod/settings.php:1279
msgid "Leave password fields blank unless changing"
msgstr ""
#: mod/settings.php:1280
msgid "Current Password:"
msgstr ""
#: mod/settings.php:1280 mod/settings.php:1281
msgid "Your current password to confirm the changes"
msgstr ""
#: mod/settings.php:1281
msgid "Password:"
msgstr ""
#: mod/settings.php:1285
msgid "Basic Settings"
msgstr ""
#: mod/settings.php:1287
msgid "Email Address:"
msgstr ""
#: mod/settings.php:1288
msgid "Your Timezone:"
msgstr ""
#: mod/settings.php:1289
msgid "Your Language:"
msgstr ""
#: mod/settings.php:1289
msgid ""
"Set the language we use to show you friendica interface and to send you "
"emails"
msgstr ""
#: mod/settings.php:1290
msgid "Default Post Location:"
msgstr ""
#: mod/settings.php:1291
msgid "Use Browser Location:"
msgstr ""
#: mod/settings.php:1294
msgid "Security and Privacy Settings"
msgstr ""
#: mod/settings.php:1296
msgid "Maximum Friend Requests/Day:"
msgstr ""
#: mod/settings.php:1296 mod/settings.php:1326
msgid "(to prevent spam abuse)"
msgstr ""
#: mod/settings.php:1297
msgid "Default Post Permissions"
msgstr ""
#: mod/settings.php:1298
msgid "(click to open/close)"
msgstr ""
#: mod/settings.php:1307 mod/photos.php:1185 mod/photos.php:1567
msgid "Show to Groups"
msgstr ""
#: mod/settings.php:1308 mod/photos.php:1186 mod/photos.php:1568
msgid "Show to Contacts"
msgstr ""
#: mod/settings.php:1309
msgid "Default Private Post"
msgstr ""
#: mod/settings.php:1310
msgid "Default Public Post"
msgstr ""
#: mod/settings.php:1314
msgid "Default Permissions for New Posts"
msgstr ""
#: mod/settings.php:1326
msgid "Maximum private messages per day from unknown people:"
msgstr ""
#: mod/settings.php:1329
msgid "Notification Settings"
msgstr ""
#: mod/settings.php:1330
msgid "By default post a status message when:"
msgstr ""
#: mod/settings.php:1331
msgid "accepting a friend request"
msgstr ""
#: mod/settings.php:1332
msgid "joining a forum/community"
msgstr ""
#: mod/settings.php:1333
msgid "making an <em>interesting</em> profile change"
msgstr ""
#: mod/settings.php:1334
msgid "Send a notification email when:"
msgstr ""
#: mod/settings.php:1335
msgid "You receive an introduction"
msgstr ""
#: mod/settings.php:1336
msgid "Your introductions are confirmed"
msgstr ""
#: mod/settings.php:1337
msgid "Someone writes on your profile wall"
msgstr ""
#: mod/settings.php:1338
msgid "Someone writes a followup comment"
msgstr ""
#: mod/settings.php:1339
msgid "You receive a private message"
msgstr ""
#: mod/settings.php:1340
msgid "You receive a friend suggestion"
msgstr ""
#: mod/settings.php:1341
msgid "You are tagged in a post"
msgstr ""
#: mod/settings.php:1342
msgid "You are poked/prodded/etc. in a post"
msgstr ""
#: mod/settings.php:1344
msgid "Activate desktop notifications"
msgstr ""
#: mod/settings.php:1344
msgid "Show desktop popup on new notifications"
msgstr ""
#: mod/settings.php:1346
msgid "Text-only notification emails"
msgstr ""
#: mod/settings.php:1348
msgid "Send text only notification emails, without the html part"
msgstr ""
#: mod/settings.php:1350
msgid "Advanced Account/Page Type Settings"
msgstr ""
#: mod/settings.php:1351
msgid "Change the behaviour of this account for special situations"
msgstr ""
#: mod/settings.php:1354
msgid "Relocate"
msgstr ""
#: mod/settings.php:1355
msgid ""
"If you have moved this profile from another server, and some of your "
"contacts don't receive your updates, try pushing this button."
msgstr ""
#: mod/settings.php:1356
msgid "Resend relocate message to contacts"
msgstr ""
#: mod/share.php:38
msgid "link"
msgstr ""
#: mod/subthread.php:104
#, php-format
msgid "%1$s is following %2$s's %3$s"
msgstr ""
#: mod/suggest.php:27
msgid "Do you really want to delete this suggestion?"
msgstr ""
#: mod/suggest.php:71
msgid ""
"No suggestions available. If this is a new site, please try again in 24 "
"hours."
msgstr ""
#: mod/suggest.php:84 mod/suggest.php:104
msgid "Ignore/Hide"
msgstr ""
#: mod/tagrm.php:43
msgid "Tag removed"
msgstr ""
#: mod/tagrm.php:82
msgid "Remove Item Tag"
msgstr ""
#: mod/tagrm.php:84
msgid "Select a tag to remove: "
msgstr ""
#: mod/uexport.php:37
msgid "Export account"
msgstr ""
#: mod/uexport.php:37
msgid ""
"Export your account info and contacts. Use this to make a backup of your "
"account and/or to move it to another server."
msgstr ""
#: mod/uexport.php:38
msgid "Export all"
msgstr ""
#: mod/uexport.php:38
msgid ""
"Export your accout info, contacts and all your items as json. Could be a "
"very big file, and could take a lot of time. Use this to make a full backup "
"of your account (photos are not exported)"
msgstr ""
#: mod/uimport.php:68
msgid "Move account"
msgstr ""
#: mod/uimport.php:69
msgid "You can import an account from another Friendica server."
msgstr ""
#: mod/uimport.php:70
msgid ""
"You need to export your account from the old server and upload it here. We "
"will recreate your old account here with all your contacts. We will try also "
"to inform your friends that you moved here."
msgstr ""
#: mod/uimport.php:71
msgid ""
"This feature is experimental. We can't import contacts from the OStatus "
"network (GNU Social/Statusnet) or from Diaspora"
msgstr ""
#: mod/uimport.php:72
msgid "Account file"
msgstr ""
#: mod/uimport.php:72
msgid ""
"To export your account, go to \"Settings->Export your personal data\" and "
"select \"Export account\""
msgstr ""
#: mod/update_community.php:19 mod/update_display.php:23
#: mod/update_network.php:27 mod/update_notes.php:36 mod/update_profile.php:35
msgid "[Embedded content - reload page to view]"
msgstr ""
#: mod/videos.php:124
msgid "Do you really want to delete this video?"
msgstr ""
#: mod/videos.php:129
msgid "Delete Video"
msgstr ""
#: mod/videos.php:208
msgid "No videos selected"
msgstr ""
#: mod/videos.php:309 mod/photos.php:1074
msgid "Access to this item is restricted."
msgstr ""
#: mod/videos.php:391 mod/photos.php:1867
msgid "View Album"
msgstr ""
#: mod/videos.php:400
msgid "Recent Videos"
msgstr ""
#: mod/videos.php:402
msgid "Upload New Videos"
msgstr ""
#: mod/viewsrc.php:7
msgid "Access denied."
msgstr ""
#: mod/wall_attach.php:17 mod/wall_attach.php:25 mod/wall_attach.php:76
#: mod/wall_upload.php:20 mod/wall_upload.php:33 mod/wall_upload.php:86
#: mod/wall_upload.php:122 mod/wall_upload.php:125
msgid "Invalid request."
msgstr ""
#: mod/wall_attach.php:94
msgid "Sorry, maybe your upload is bigger than the PHP configuration allows"
msgstr ""
#: mod/wall_attach.php:94
msgid "Or - did you try to upload an empty file?"
msgstr ""
#: mod/wall_attach.php:105
#, php-format
msgid "File exceeds size limit of %s"
msgstr ""
#: mod/wall_attach.php:158 mod/wall_attach.php:174
msgid "File upload failed."
msgstr ""
#: mod/cal.php:271 mod/events.php:387
msgid "View"
msgstr ""
@ -5449,6 +4663,28 @@ msgstr ""
msgid "calendar"
msgstr ""
#: mod/common.php:91
msgid "No contacts in common."
msgstr ""
#: mod/common.php:141 mod/contacts.php:871
msgid "Common Friends"
msgstr ""
#: mod/community.php:22 mod/dfrn_request.php:799 mod/directory.php:37
#: mod/display.php:200 mod/photos.php:964 mod/search.php:93 mod/search.php:99
#: mod/videos.php:198 mod/viewcontacts.php:36
msgid "Public access denied."
msgstr ""
#: mod/community.php:27
msgid "Not available."
msgstr ""
#: mod/community.php:54 mod/search.php:224
msgid "No results."
msgstr ""
#: mod/contacts.php:134
#, php-format
msgid "%d contact edited."
@ -5527,10 +4763,6 @@ msgstr ""
msgid "Private communications are not available for this contact."
msgstr ""
#: mod/contacts.php:538 mod/admin.php:899
msgid "Never"
msgstr ""
#: mod/contacts.php:542
msgid "(Update was successful)"
msgstr ""
@ -5556,10 +4788,6 @@ msgstr ""
msgid "Fetch further information for feeds"
msgstr ""
#: mod/contacts.php:565 mod/admin.php:908
msgid "Disabled"
msgstr ""
#: mod/contacts.php:565
msgid "Fetch information"
msgstr ""
@ -5572,6 +4800,18 @@ msgstr ""
msgid "Contact"
msgstr ""
#: mod/contacts.php:585 mod/content.php:728 mod/crepair.php:156
#: mod/events.php:513 mod/fsuggest.php:108 mod/install.php:276
#: mod/install.php:316 mod/invite.php:142 mod/localtime.php:45
#: mod/manage.php:145 mod/message.php:338 mod/message.php:521 mod/mood.php:138
#: mod/photos.php:1124 mod/photos.php:1246 mod/photos.php:1562
#: mod/photos.php:1612 mod/photos.php:1660 mod/photos.php:1746
#: mod/poke.php:203 mod/profiles.php:680 object/Item.php:705
#: view/theme/duepuntozero/config.php:61 view/theme/frio/config.php:64
#: view/theme/quattro/config.php:67 view/theme/vier/config.php:112
msgid "Submit"
msgstr ""
#: mod/contacts.php:586
msgid "Profile Visibility"
msgstr ""
@ -5591,6 +4831,12 @@ msgstr ""
msgid "Edit contact notes"
msgstr ""
#: mod/contacts.php:594 mod/contacts.php:938 mod/nogroup.php:43
#: mod/viewcontacts.php:102
#, php-format
msgid "Visit %s's profile [%s]"
msgstr ""
#: mod/contacts.php:595
msgid "Block/Unblock contact"
msgstr ""
@ -5619,16 +4865,6 @@ msgstr ""
msgid "Update now"
msgstr ""
#: mod/contacts.php:613 mod/contacts.php:813 mod/contacts.php:991
#: mod/admin.php:1437
msgid "Unblock"
msgstr ""
#: mod/contacts.php:613 mod/contacts.php:813 mod/contacts.php:991
#: mod/admin.php:1436
msgid "Block"
msgstr ""
#: mod/contacts.php:614 mod/contacts.php:814 mod/contacts.php:999
msgid "Unignore"
msgstr ""
@ -5678,6 +4914,10 @@ msgid ""
"when \"Fetch information and keywords\" is selected"
msgstr ""
#: mod/contacts.php:632 mod/follow.php:129 mod/notifications.php:249
msgid "Profile URL"
msgstr ""
#: mod/contacts.php:643
msgid "Actions"
msgstr ""
@ -5694,6 +4934,10 @@ msgstr ""
msgid "Suggest potential friends"
msgstr ""
#: mod/contacts.php:700 mod/group.php:202
msgid "All Contacts"
msgstr ""
#: mod/contacts.php:703
msgid "Show all contacts"
msgstr ""
@ -5747,6 +4991,10 @@ msgstr ""
msgid "Results for: %s"
msgstr ""
#: mod/contacts.php:812 mod/settings.php:160 mod/settings.php:707
msgid "Update"
msgstr ""
#: mod/contacts.php:815 mod/contacts.php:1007
msgid "Archive"
msgstr ""
@ -5783,6 +5031,10 @@ msgstr ""
msgid "you are a fan of"
msgstr ""
#: mod/contacts.php:939 mod/nogroup.php:44
msgid "Edit contact"
msgstr ""
#: mod/contacts.php:993
msgid "Toggle Blocked status"
msgstr ""
@ -5799,6 +5051,307 @@ msgstr ""
msgid "Delete contact"
msgstr ""
#: mod/content.php:119 mod/network.php:468
msgid "No such group"
msgstr ""
#: mod/content.php:130 mod/group.php:203 mod/network.php:495
msgid "Group is empty"
msgstr ""
#: mod/content.php:135 mod/network.php:499
#, php-format
msgid "Group: %s"
msgstr ""
#: mod/content.php:325 object/Item.php:96
msgid "This entry was edited"
msgstr ""
#: mod/content.php:621 object/Item.php:417
#, php-format
msgid "%d comment"
msgid_plural "%d comments"
msgstr[0] ""
msgstr[1] ""
#: mod/content.php:638 mod/photos.php:1402 object/Item.php:117
msgid "Private Message"
msgstr ""
#: mod/content.php:702 mod/photos.php:1590 object/Item.php:274
msgid "I like this (toggle)"
msgstr ""
#: mod/content.php:702 object/Item.php:274
msgid "like"
msgstr ""
#: mod/content.php:703 mod/photos.php:1591 object/Item.php:275
msgid "I don't like this (toggle)"
msgstr ""
#: mod/content.php:703 object/Item.php:275
msgid "dislike"
msgstr ""
#: mod/content.php:705 object/Item.php:278
msgid "Share this"
msgstr ""
#: mod/content.php:705 object/Item.php:278
msgid "share"
msgstr ""
#: mod/content.php:725 mod/photos.php:1609 mod/photos.php:1657
#: mod/photos.php:1743 object/Item.php:702
msgid "This is you"
msgstr ""
#: mod/content.php:727 mod/content.php:950 mod/photos.php:1611
#: mod/photos.php:1659 mod/photos.php:1745 object/Item.php:392
#: object/Item.php:704
msgid "Comment"
msgstr ""
#: mod/content.php:729 object/Item.php:706
msgid "Bold"
msgstr ""
#: mod/content.php:730 object/Item.php:707
msgid "Italic"
msgstr ""
#: mod/content.php:731 object/Item.php:708
msgid "Underline"
msgstr ""
#: mod/content.php:732 object/Item.php:709
msgid "Quote"
msgstr ""
#: mod/content.php:733 object/Item.php:710
msgid "Code"
msgstr ""
#: mod/content.php:734 object/Item.php:711
msgid "Image"
msgstr ""
#: mod/content.php:735 object/Item.php:712
msgid "Link"
msgstr ""
#: mod/content.php:736 object/Item.php:713
msgid "Video"
msgstr ""
#: mod/content.php:746 mod/settings.php:743 object/Item.php:122
#: object/Item.php:124
msgid "Edit"
msgstr ""
#: mod/content.php:772 object/Item.php:238
msgid "add star"
msgstr ""
#: mod/content.php:773 object/Item.php:239
msgid "remove star"
msgstr ""
#: mod/content.php:774 object/Item.php:240
msgid "toggle star status"
msgstr ""
#: mod/content.php:777 object/Item.php:243
msgid "starred"
msgstr ""
#: mod/content.php:778 mod/content.php:800 object/Item.php:263
msgid "add tag"
msgstr ""
#: mod/content.php:789 object/Item.php:251
msgid "ignore thread"
msgstr ""
#: mod/content.php:790 object/Item.php:252
msgid "unignore thread"
msgstr ""
#: mod/content.php:791 object/Item.php:253
msgid "toggle ignore status"
msgstr ""
#: mod/content.php:794 mod/ostatus_subscribe.php:73 object/Item.php:256
msgid "ignored"
msgstr ""
#: mod/content.php:805 object/Item.php:141
msgid "save to folder"
msgstr ""
#: mod/content.php:853 object/Item.php:212
msgid "I will attend"
msgstr ""
#: mod/content.php:853 object/Item.php:212
msgid "I will not attend"
msgstr ""
#: mod/content.php:853 object/Item.php:212
msgid "I might attend"
msgstr ""
#: mod/content.php:917 object/Item.php:358
msgid "to"
msgstr ""
#: mod/content.php:918 object/Item.php:360
msgid "Wall-to-Wall"
msgstr ""
#: mod/content.php:919 object/Item.php:361
msgid "via Wall-To-Wall:"
msgstr ""
#: mod/credits.php:16
msgid "Credits"
msgstr ""
#: mod/credits.php:17
msgid ""
"Friendica is a community project, that would not be possible without the "
"help of many people. Here is a list of those who have contributed to the "
"code or the translation of Friendica. Thank you all!"
msgstr ""
#: mod/crepair.php:89
msgid "Contact settings applied."
msgstr ""
#: mod/crepair.php:91
msgid "Contact update failed."
msgstr ""
#: mod/crepair.php:116 mod/dfrn_confirm.php:126 mod/fsuggest.php:21
#: mod/fsuggest.php:93
msgid "Contact not found."
msgstr ""
#: mod/crepair.php:122
msgid ""
"<strong>WARNING: This is highly advanced</strong> and if you enter incorrect "
"information your communications with this contact may stop working."
msgstr ""
#: mod/crepair.php:123
msgid ""
"Please use your browser 'Back' button <strong>now</strong> if you are "
"uncertain what to do on this page."
msgstr ""
#: mod/crepair.php:136 mod/crepair.php:138
msgid "No mirroring"
msgstr ""
#: mod/crepair.php:136
msgid "Mirror as forwarded posting"
msgstr ""
#: mod/crepair.php:136 mod/crepair.php:138
msgid "Mirror as my own posting"
msgstr ""
#: mod/crepair.php:152
msgid "Return to contact editor"
msgstr ""
#: mod/crepair.php:154
msgid "Refetch contact data"
msgstr ""
#: mod/crepair.php:158
msgid "Remote Self"
msgstr ""
#: mod/crepair.php:161
msgid "Mirror postings from this contact"
msgstr ""
#: mod/crepair.php:163
msgid ""
"Mark this contact as remote_self, this will cause friendica to repost new "
"entries from this contact."
msgstr ""
#: mod/crepair.php:168
msgid "Account Nickname"
msgstr ""
#: mod/crepair.php:169
msgid "@Tagname - overrides Name/Nickname"
msgstr ""
#: mod/crepair.php:170
msgid "Account URL"
msgstr ""
#: mod/crepair.php:171
msgid "Friend Request URL"
msgstr ""
#: mod/crepair.php:172
msgid "Friend Confirm URL"
msgstr ""
#: mod/crepair.php:173
msgid "Notification Endpoint URL"
msgstr ""
#: mod/crepair.php:174
msgid "Poll/Feed URL"
msgstr ""
#: mod/crepair.php:175
msgid "New photo from this URL"
msgstr ""
#: mod/delegate.php:101
msgid "No potential page delegates located."
msgstr ""
#: mod/delegate.php:132
msgid ""
"Delegates are able to manage all aspects of this account/page except for "
"basic account settings. Please do not delegate your personal account to "
"anybody that you do not trust completely."
msgstr ""
#: mod/delegate.php:133
msgid "Existing Page Managers"
msgstr ""
#: mod/delegate.php:135
msgid "Existing Page Delegates"
msgstr ""
#: mod/delegate.php:137
msgid "Potential Delegates"
msgstr ""
#: mod/delegate.php:139 mod/tagrm.php:95
msgid "Remove"
msgstr ""
#: mod/delegate.php:140
msgid "Add"
msgstr ""
#: mod/delegate.php:141
msgid "No entries."
msgstr ""
#: mod/dfrn_confirm.php:70 mod/profiles.php:19 mod/profiles.php:134
#: mod/profiles.php:180 mod/profiles.php:619
msgid "Profile not found."
@ -5879,436 +5432,9 @@ msgstr ""
msgid "%1$s has joined %2$s"
msgstr ""
#: mod/editpost.php:17 mod/editpost.php:27
msgid "Item not found"
msgstr ""
#: mod/editpost.php:32
msgid "Edit post"
msgstr ""
#: mod/events.php:100 mod/events.php:102
msgid "Event can not end before it has started."
msgstr ""
#: mod/events.php:109 mod/events.php:111
msgid "Event title and start time are required."
msgstr ""
#: mod/events.php:388
msgid "Create New Event"
msgstr ""
#: mod/events.php:489
msgid "Event details"
msgstr ""
#: mod/events.php:490
msgid "Starting date and Title are required."
msgstr ""
#: mod/events.php:491 mod/events.php:492
msgid "Event Starts:"
msgstr ""
#: mod/events.php:491 mod/events.php:503 mod/profiles.php:708
msgid "Required"
msgstr ""
#: mod/events.php:493 mod/events.php:509
msgid "Finish date/time is not known or not relevant"
msgstr ""
#: mod/events.php:495 mod/events.php:496
msgid "Event Finishes:"
msgstr ""
#: mod/events.php:497 mod/events.php:510
msgid "Adjust for viewer timezone"
msgstr ""
#: mod/events.php:499
msgid "Description:"
msgstr ""
#: mod/events.php:503 mod/events.php:505
msgid "Title:"
msgstr ""
#: mod/events.php:506 mod/events.php:507
msgid "Share this event"
msgstr ""
#: mod/fbrowser.php:132
msgid "Files"
msgstr ""
#: mod/friendica.php:72
msgid "This is Friendica, version"
msgstr ""
#: mod/friendica.php:73
msgid "running at web location"
msgstr ""
#: mod/friendica.php:75
msgid ""
"Please visit <a href=\"http://friendica.com\">Friendica.com</a> to learn "
"more about the Friendica project."
msgstr ""
#: mod/friendica.php:77
msgid "Bug reports and issues: please visit"
msgstr ""
#: mod/friendica.php:77
msgid "the bugtracker at github"
msgstr ""
#: mod/friendica.php:78
msgid ""
"Suggestions, praise, donations, etc. - please email \"Info\" at Friendica - "
"dot com"
msgstr ""
#: mod/friendica.php:92
msgid "Installed plugins/addons/apps:"
msgstr ""
#: mod/friendica.php:105
msgid "No installed plugins/addons/apps"
msgstr ""
#: mod/item.php:118
msgid "Unable to locate original post."
msgstr ""
#: mod/item.php:336
msgid "Empty post discarded."
msgstr ""
#: mod/item.php:889
msgid "System error. Post not saved."
msgstr ""
#: mod/item.php:979
#: mod/dfrn_poll.php:104 mod/dfrn_poll.php:539
#, php-format
msgid ""
"This message was sent to you by %s, a member of the Friendica social network."
msgstr ""
#: mod/item.php:981
#, php-format
msgid "You may visit them online at %s"
msgstr ""
#: mod/item.php:982
msgid ""
"Please contact the sender by replying to this post if you do not wish to "
"receive these messages."
msgstr ""
#: mod/item.php:986
#, php-format
msgid "%s posted an update."
msgstr ""
#: mod/message.php:60 mod/wallmessage.php:50
msgid "No recipient selected."
msgstr ""
#: mod/message.php:64
msgid "Unable to locate contact information."
msgstr ""
#: mod/message.php:67 mod/wallmessage.php:56
msgid "Message could not be sent."
msgstr ""
#: mod/message.php:70 mod/wallmessage.php:59
msgid "Message collection failure."
msgstr ""
#: mod/message.php:73 mod/wallmessage.php:62
msgid "Message sent."
msgstr ""
#: mod/message.php:204
msgid "Do you really want to delete this message?"
msgstr ""
#: mod/message.php:224
msgid "Message deleted."
msgstr ""
#: mod/message.php:255
msgid "Conversation removed."
msgstr ""
#: mod/message.php:322 mod/wallmessage.php:126
msgid "Send Private Message"
msgstr ""
#: mod/message.php:323 mod/message.php:510 mod/wallmessage.php:128
msgid "To:"
msgstr ""
#: mod/message.php:328 mod/message.php:512 mod/wallmessage.php:129
msgid "Subject:"
msgstr ""
#: mod/message.php:364
msgid "No messages."
msgstr ""
#: mod/message.php:403
msgid "Message not available."
msgstr ""
#: mod/message.php:477
msgid "Delete message"
msgstr ""
#: mod/message.php:503 mod/message.php:583
msgid "Delete conversation"
msgstr ""
#: mod/message.php:505
msgid ""
"No secure communications available. You <strong>may</strong> be able to "
"respond from the sender's profile page."
msgstr ""
#: mod/message.php:509
msgid "Send Reply"
msgstr ""
#: mod/message.php:553
#, php-format
msgid "Unknown sender - %s"
msgstr ""
#: mod/message.php:555
#, php-format
msgid "You and %s"
msgstr ""
#: mod/message.php:557
#, php-format
msgid "%s and You"
msgstr ""
#: mod/message.php:586
msgid "D, d M Y - g:i A"
msgstr ""
#: mod/message.php:589
#, php-format
msgid "%d message"
msgid_plural "%d messages"
msgstr[0] ""
msgstr[1] ""
#: mod/p.php:9
msgid "Not Extended"
msgstr ""
#: mod/ping.php:270
msgid "{0} wants to be your friend"
msgstr ""
#: mod/ping.php:285
msgid "{0} sent you a message"
msgstr ""
#: mod/ping.php:300
msgid "{0} requested registration"
msgstr ""
#: mod/wallmessage.php:42 mod/wallmessage.php:106
#, php-format
msgid "Number of daily wall messages for %s exceeded. Message failed."
msgstr ""
#: mod/wallmessage.php:53
msgid "Unable to check your home location."
msgstr ""
#: mod/wallmessage.php:80 mod/wallmessage.php:89
msgid "No recipient."
msgstr ""
#: mod/wallmessage.php:127
#, php-format
msgid ""
"If you wish for %s to respond, please check that the privacy settings on "
"your site allow private mail from unknown senders."
msgstr ""
#: mod/photos.php:90 mod/photos.php:1876
msgid "Recent Photos"
msgstr ""
#: mod/photos.php:93 mod/photos.php:1303 mod/photos.php:1878
msgid "Upload New Photos"
msgstr ""
#: mod/photos.php:171
msgid "Contact information unavailable"
msgstr ""
#: mod/photos.php:192
msgid "Album not found."
msgstr ""
#: mod/photos.php:225 mod/photos.php:237 mod/photos.php:1247
msgid "Delete Album"
msgstr ""
#: mod/photos.php:235
msgid "Do you really want to delete this photo album and all its photos?"
msgstr ""
#: mod/photos.php:317 mod/photos.php:328 mod/photos.php:1563
msgid "Delete Photo"
msgstr ""
#: mod/photos.php:326
msgid "Do you really want to delete this photo?"
msgstr ""
#: mod/photos.php:705
#, php-format
msgid "%1$s was tagged in %2$s by %3$s"
msgstr ""
#: mod/photos.php:705
msgid "a photo"
msgstr ""
#: mod/photos.php:811
msgid "Image file is empty."
msgstr ""
#: mod/photos.php:974
msgid "No photos selected"
msgstr ""
#: mod/photos.php:1134
#, php-format
msgid "You have used %1$.2f Mbytes of %2$.2f Mbytes photo storage."
msgstr ""
#: mod/photos.php:1168
msgid "Upload Photos"
msgstr ""
#: mod/photos.php:1172 mod/photos.php:1242
msgid "New album name: "
msgstr ""
#: mod/photos.php:1173
msgid "or existing album name: "
msgstr ""
#: mod/photos.php:1174
msgid "Do not show a status post for this upload"
msgstr ""
#: mod/photos.php:1187
msgid "Private Photo"
msgstr ""
#: mod/photos.php:1188
msgid "Public Photo"
msgstr ""
#: mod/photos.php:1254
msgid "Edit Album"
msgstr ""
#: mod/photos.php:1260
msgid "Show Newest First"
msgstr ""
#: mod/photos.php:1262
msgid "Show Oldest First"
msgstr ""
#: mod/photos.php:1289 mod/photos.php:1861
msgid "View Photo"
msgstr ""
#: mod/photos.php:1335
msgid "Permission denied. Access to this item may be restricted."
msgstr ""
#: mod/photos.php:1337
msgid "Photo not available"
msgstr ""
#: mod/photos.php:1395
msgid "View photo"
msgstr ""
#: mod/photos.php:1395
msgid "Edit photo"
msgstr ""
#: mod/photos.php:1396
msgid "Use as profile photo"
msgstr ""
#: mod/photos.php:1421
msgid "View Full Size"
msgstr ""
#: mod/photos.php:1507
msgid "Tags: "
msgstr ""
#: mod/photos.php:1510
msgid "[Remove any tag]"
msgstr ""
#: mod/photos.php:1549
msgid "New album name"
msgstr ""
#: mod/photos.php:1550
msgid "Caption"
msgstr ""
#: mod/photos.php:1551
msgid "Add a Tag"
msgstr ""
#: mod/photos.php:1551
msgid "Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"
msgstr ""
#: mod/photos.php:1552
msgid "Do not rotate"
msgstr ""
#: mod/photos.php:1553
msgid "Rotate CW (right)"
msgstr ""
#: mod/photos.php:1554
msgid "Rotate CCW (left)"
msgstr ""
#: mod/photos.php:1569
msgid "Private photo"
msgstr ""
#: mod/photos.php:1570
msgid "Public photo"
msgstr ""
#: mod/photos.php:1792
msgid "Map"
msgid "%1$s welcomes %2$s"
msgstr ""
#: mod/dfrn_request.php:101
@ -6445,6 +5571,19 @@ msgid ""
"testuser@identi.ca"
msgstr ""
#: mod/dfrn_request.php:874 mod/follow.php:112
msgid "Please answer the following:"
msgstr ""
#: mod/dfrn_request.php:875 mod/follow.php:113
#, php-format
msgid "Does %s know you?"
msgstr ""
#: mod/dfrn_request.php:879 mod/follow.php:114
msgid "Add a personal note:"
msgstr ""
#: mod/dfrn_request.php:882
msgid "StatusNet/Federated Social Web"
msgstr ""
@ -6456,6 +5595,246 @@ msgid ""
"bar."
msgstr ""
#: mod/dfrn_request.php:885 mod/follow.php:120
msgid "Your Identity Address:"
msgstr ""
#: mod/dfrn_request.php:888 mod/follow.php:19
msgid "Submit Request"
msgstr ""
#: mod/directory.php:199 view/theme/vier/theme.php:196
msgid "Global Directory"
msgstr ""
#: mod/directory.php:201
msgid "Find on this site"
msgstr ""
#: mod/directory.php:203
msgid "Results for:"
msgstr ""
#: mod/directory.php:205
msgid "Site Directory"
msgstr ""
#: mod/directory.php:212
msgid "No entries (some entries may be hidden)."
msgstr ""
#: mod/dirfind.php:37
#, php-format
msgid "People Search - %s"
msgstr ""
#: mod/dirfind.php:48
#, php-format
msgid "Forum Search - %s"
msgstr ""
#: mod/dirfind.php:245 mod/match.php:109
msgid "No matches"
msgstr ""
#: mod/display.php:479
msgid "Item has been removed."
msgstr ""
#: mod/editpost.php:17 mod/editpost.php:27
msgid "Item not found"
msgstr ""
#: mod/editpost.php:32
msgid "Edit post"
msgstr ""
#: mod/events.php:100 mod/events.php:102
msgid "Event can not end before it has started."
msgstr ""
#: mod/events.php:109 mod/events.php:111
msgid "Event title and start time are required."
msgstr ""
#: mod/events.php:388
msgid "Create New Event"
msgstr ""
#: mod/events.php:489
msgid "Event details"
msgstr ""
#: mod/events.php:490
msgid "Starting date and Title are required."
msgstr ""
#: mod/events.php:491 mod/events.php:492
msgid "Event Starts:"
msgstr ""
#: mod/events.php:491 mod/events.php:503 mod/profiles.php:708
msgid "Required"
msgstr ""
#: mod/events.php:493 mod/events.php:509
msgid "Finish date/time is not known or not relevant"
msgstr ""
#: mod/events.php:495 mod/events.php:496
msgid "Event Finishes:"
msgstr ""
#: mod/events.php:497 mod/events.php:510
msgid "Adjust for viewer timezone"
msgstr ""
#: mod/events.php:499
msgid "Description:"
msgstr ""
#: mod/events.php:503 mod/events.php:505
msgid "Title:"
msgstr ""
#: mod/events.php:506 mod/events.php:507
msgid "Share this event"
msgstr ""
#: mod/fbrowser.php:132
msgid "Files"
msgstr ""
#: mod/filer.php:30
msgid "- select -"
msgstr ""
#: mod/follow.php:30
msgid "You already added this contact."
msgstr ""
#: mod/follow.php:39
msgid "Diaspora support isn't enabled. Contact can't be added."
msgstr ""
#: mod/follow.php:46
msgid "OStatus support is disabled. Contact can't be added."
msgstr ""
#: mod/follow.php:53
msgid "The network type couldn't be detected. Contact can't be added."
msgstr ""
#: mod/follow.php:186
msgid "Contact added"
msgstr ""
#: mod/friendica.php:72
msgid "This is Friendica, version"
msgstr ""
#: mod/friendica.php:73
msgid "running at web location"
msgstr ""
#: mod/friendica.php:75
msgid ""
"Please visit <a href=\"http://friendica.com\">Friendica.com</a> to learn "
"more about the Friendica project."
msgstr ""
#: mod/friendica.php:77
msgid "Bug reports and issues: please visit"
msgstr ""
#: mod/friendica.php:77
msgid "the bugtracker at github"
msgstr ""
#: mod/friendica.php:78
msgid ""
"Suggestions, praise, donations, etc. - please email \"Info\" at Friendica - "
"dot com"
msgstr ""
#: mod/friendica.php:92
msgid "Installed plugins/addons/apps:"
msgstr ""
#: mod/friendica.php:105
msgid "No installed plugins/addons/apps"
msgstr ""
#: mod/fsuggest.php:64
msgid "Friend suggestion sent."
msgstr ""
#: mod/fsuggest.php:98
msgid "Suggest Friends"
msgstr ""
#: mod/fsuggest.php:100
#, php-format
msgid "Suggest a friend for %s"
msgstr ""
#: mod/group.php:29
msgid "Group created."
msgstr ""
#: mod/group.php:35
msgid "Could not create group."
msgstr ""
#: mod/group.php:49 mod/group.php:150
msgid "Group not found."
msgstr ""
#: mod/group.php:63
msgid "Group name changed."
msgstr ""
#: mod/group.php:91
msgid "Save Group"
msgstr ""
#: mod/group.php:97
msgid "Create a group of contacts/friends."
msgstr ""
#: mod/group.php:122
msgid "Group removed."
msgstr ""
#: mod/group.php:124
msgid "Unable to remove group."
msgstr ""
#: mod/group.php:187
msgid "Group Editor"
msgstr ""
#: mod/group.php:200
msgid "Members"
msgstr ""
#: mod/group.php:233 mod/profperm.php:107
msgid "Click on a contact to add or remove."
msgstr ""
#: mod/hcard.php:11
msgid "No profile"
msgstr ""
#: mod/help.php:41
msgid "Help:"
msgstr ""
#: mod/home.php:39
#, php-format
msgid "Welcome to %s"
msgstr ""
#: mod/install.php:140
msgid "Friendica Communications Server - Setup"
msgstr ""
@ -6816,6 +6195,1138 @@ msgid ""
"IMPORTANT: You will need to [manually] setup a scheduled task for the poller."
msgstr ""
#: mod/invite.php:28
msgid "Total invitation limit exceeded."
msgstr ""
#: mod/invite.php:51
#, php-format
msgid "%s : Not a valid email address."
msgstr ""
#: mod/invite.php:76
msgid "Please join us on Friendica"
msgstr ""
#: mod/invite.php:87
msgid "Invitation limit exceeded. Please contact your site administrator."
msgstr ""
#: mod/invite.php:91
#, php-format
msgid "%s : Message delivery failed."
msgstr ""
#: mod/invite.php:95
#, php-format
msgid "%d message sent."
msgid_plural "%d messages sent."
msgstr[0] ""
msgstr[1] ""
#: mod/invite.php:114
msgid "You have no more invitations available"
msgstr ""
#: mod/invite.php:122
#, php-format
msgid ""
"Visit %s for a list of public sites that you can join. Friendica members on "
"other sites can all connect with each other, as well as with members of many "
"other social networks."
msgstr ""
#: mod/invite.php:124
#, php-format
msgid ""
"To accept this invitation, please visit and register at %s or any other "
"public Friendica website."
msgstr ""
#: mod/invite.php:125
#, php-format
msgid ""
"Friendica sites all inter-connect to create a huge privacy-enhanced social "
"web that is owned and controlled by its members. They can also connect with "
"many traditional social networks. See %s for a list of alternate Friendica "
"sites you can join."
msgstr ""
#: mod/invite.php:128
msgid ""
"Our apologies. This system is not currently configured to connect with other "
"public sites or invite members."
msgstr ""
#: mod/invite.php:134
msgid "Send invitations"
msgstr ""
#: mod/invite.php:135
msgid "Enter email addresses, one per line:"
msgstr ""
#: mod/invite.php:136 mod/message.php:332 mod/message.php:515
#: mod/wallmessage.php:135
msgid "Your message:"
msgstr ""
#: mod/invite.php:137
msgid ""
"You are cordially invited to join me and other close friends on Friendica - "
"and help us to create a better social web."
msgstr ""
#: mod/invite.php:139
msgid "You will need to supply this invitation code: $invite_code"
msgstr ""
#: mod/invite.php:139
msgid ""
"Once you have registered, please connect with me via my profile page at:"
msgstr ""
#: mod/invite.php:141
msgid ""
"For more information about the Friendica project and why we feel it is "
"important, please visit http://friendica.com"
msgstr ""
#: mod/item.php:118
msgid "Unable to locate original post."
msgstr ""
#: mod/item.php:336
msgid "Empty post discarded."
msgstr ""
#: mod/item.php:889
msgid "System error. Post not saved."
msgstr ""
#: mod/item.php:979
#, php-format
msgid ""
"This message was sent to you by %s, a member of the Friendica social network."
msgstr ""
#: mod/item.php:981
#, php-format
msgid "You may visit them online at %s"
msgstr ""
#: mod/item.php:982
msgid ""
"Please contact the sender by replying to this post if you do not wish to "
"receive these messages."
msgstr ""
#: mod/item.php:986
#, php-format
msgid "%s posted an update."
msgstr ""
#: mod/localtime.php:24
msgid "Time Conversion"
msgstr ""
#: mod/localtime.php:26
msgid ""
"Friendica provides this service for sharing events with other networks and "
"friends in unknown timezones."
msgstr ""
#: mod/localtime.php:30
#, php-format
msgid "UTC time: %s"
msgstr ""
#: mod/localtime.php:33
#, php-format
msgid "Current timezone: %s"
msgstr ""
#: mod/localtime.php:36
#, php-format
msgid "Converted localtime: %s"
msgstr ""
#: mod/localtime.php:41
msgid "Please select your timezone:"
msgstr ""
#: mod/lockview.php:32 mod/lockview.php:40
msgid "Remote privacy information not available."
msgstr ""
#: mod/lockview.php:49
msgid "Visible to:"
msgstr ""
#: mod/lostpass.php:19
msgid "No valid account found."
msgstr ""
#: mod/lostpass.php:35
msgid "Password reset request issued. Check your email."
msgstr ""
#: mod/lostpass.php:41
#, php-format
msgid ""
"\n"
"\t\tDear %1$s,\n"
"\t\t\tA request was recently received at \"%2$s\" to reset your account\n"
"\t\tpassword. In order to confirm this request, please select the "
"verification link\n"
"\t\tbelow or paste it into your web browser address bar.\n"
"\n"
"\t\tIf you did NOT request this change, please DO NOT follow the link\n"
"\t\tprovided and ignore and/or delete this email.\n"
"\n"
"\t\tYour password will not be changed unless we can verify that you\n"
"\t\tissued this request."
msgstr ""
#: mod/lostpass.php:52
#, php-format
msgid ""
"\n"
"\t\tFollow this link to verify your identity:\n"
"\n"
"\t\t%1$s\n"
"\n"
"\t\tYou will then receive a follow-up message containing the new password.\n"
"\t\tYou may change that password from your account settings page after "
"logging in.\n"
"\n"
"\t\tThe login details are as follows:\n"
"\n"
"\t\tSite Location:\t%2$s\n"
"\t\tLogin Name:\t%3$s"
msgstr ""
#: mod/lostpass.php:71
#, php-format
msgid "Password reset requested at %s"
msgstr ""
#: mod/lostpass.php:91
msgid ""
"Request could not be verified. (You may have previously submitted it.) "
"Password reset failed."
msgstr ""
#: mod/lostpass.php:111
msgid "Your password has been reset as requested."
msgstr ""
#: mod/lostpass.php:112
msgid "Your new password is"
msgstr ""
#: mod/lostpass.php:113
msgid "Save or copy your new password - and then"
msgstr ""
#: mod/lostpass.php:114
msgid "click here to login"
msgstr ""
#: mod/lostpass.php:115
msgid ""
"Your password may be changed from the <em>Settings</em> page after "
"successful login."
msgstr ""
#: mod/lostpass.php:125
#, php-format
msgid ""
"\n"
"\t\t\t\tDear %1$s,\n"
"\t\t\t\t\tYour password has been changed as requested. Please retain this\n"
"\t\t\t\tinformation for your records (or change your password immediately "
"to\n"
"\t\t\t\tsomething that you will remember).\n"
"\t\t\t"
msgstr ""
#: mod/lostpass.php:131
#, php-format
msgid ""
"\n"
"\t\t\t\tYour login details are as follows:\n"
"\n"
"\t\t\t\tSite Location:\t%1$s\n"
"\t\t\t\tLogin Name:\t%2$s\n"
"\t\t\t\tPassword:\t%3$s\n"
"\n"
"\t\t\t\tYou may change that password from your account settings page after "
"logging in.\n"
"\t\t\t"
msgstr ""
#: mod/lostpass.php:147
#, php-format
msgid "Your password has been changed at %s"
msgstr ""
#: mod/lostpass.php:159
msgid "Forgot your Password?"
msgstr ""
#: mod/lostpass.php:160
msgid ""
"Enter your email address and submit to have your password reset. Then check "
"your email for further instructions."
msgstr ""
#: mod/lostpass.php:162
msgid "Reset"
msgstr ""
#: mod/maintenance.php:20
msgid "System down for maintenance"
msgstr ""
#: mod/manage.php:141
msgid "Manage Identities and/or Pages"
msgstr ""
#: mod/manage.php:142
msgid ""
"Toggle between different identities or community/group pages which share "
"your account details or which you have been granted \"manage\" permissions"
msgstr ""
#: mod/manage.php:143
msgid "Select an identity to manage: "
msgstr ""
#: mod/match.php:35
msgid "No keywords to match. Please add keywords to your default profile."
msgstr ""
#: mod/match.php:88
msgid "is interested in:"
msgstr ""
#: mod/match.php:102
msgid "Profile Match"
msgstr ""
#: mod/message.php:60 mod/wallmessage.php:50
msgid "No recipient selected."
msgstr ""
#: mod/message.php:64
msgid "Unable to locate contact information."
msgstr ""
#: mod/message.php:67 mod/wallmessage.php:56
msgid "Message could not be sent."
msgstr ""
#: mod/message.php:70 mod/wallmessage.php:59
msgid "Message collection failure."
msgstr ""
#: mod/message.php:73 mod/wallmessage.php:62
msgid "Message sent."
msgstr ""
#: mod/message.php:204
msgid "Do you really want to delete this message?"
msgstr ""
#: mod/message.php:224
msgid "Message deleted."
msgstr ""
#: mod/message.php:255
msgid "Conversation removed."
msgstr ""
#: mod/message.php:322 mod/wallmessage.php:126
msgid "Send Private Message"
msgstr ""
#: mod/message.php:323 mod/message.php:510 mod/wallmessage.php:128
msgid "To:"
msgstr ""
#: mod/message.php:328 mod/message.php:512 mod/wallmessage.php:129
msgid "Subject:"
msgstr ""
#: mod/message.php:364
msgid "No messages."
msgstr ""
#: mod/message.php:403
msgid "Message not available."
msgstr ""
#: mod/message.php:477
msgid "Delete message"
msgstr ""
#: mod/message.php:503 mod/message.php:583
msgid "Delete conversation"
msgstr ""
#: mod/message.php:505
msgid ""
"No secure communications available. You <strong>may</strong> be able to "
"respond from the sender's profile page."
msgstr ""
#: mod/message.php:509
msgid "Send Reply"
msgstr ""
#: mod/message.php:553
#, php-format
msgid "Unknown sender - %s"
msgstr ""
#: mod/message.php:555
#, php-format
msgid "You and %s"
msgstr ""
#: mod/message.php:557
#, php-format
msgid "%s and You"
msgstr ""
#: mod/message.php:586
msgid "D, d M Y - g:i A"
msgstr ""
#: mod/message.php:589
#, php-format
msgid "%d message"
msgid_plural "%d messages"
msgstr[0] ""
msgstr[1] ""
#: mod/mood.php:134
msgid "Mood"
msgstr ""
#: mod/mood.php:135
msgid "Set your current mood and tell your friends"
msgstr ""
#: mod/network.php:190 mod/search.php:25
msgid "Remove term"
msgstr ""
#: mod/network.php:397
#, php-format
msgid ""
"Warning: This group contains %s member from a network that doesn't allow non "
"public messages."
msgid_plural ""
"Warning: This group contains %s members from a network that doesn't allow "
"non public messages."
msgstr[0] ""
msgstr[1] ""
#: mod/network.php:400
msgid "Messages in this group won't be send to these receivers."
msgstr ""
#: mod/network.php:528
msgid "Private messages to this person are at risk of public disclosure."
msgstr ""
#: mod/network.php:533
msgid "Invalid contact."
msgstr ""
#: mod/network.php:810
msgid "Commented Order"
msgstr ""
#: mod/network.php:813
msgid "Sort by Comment Date"
msgstr ""
#: mod/network.php:818
msgid "Posted Order"
msgstr ""
#: mod/network.php:821
msgid "Sort by Post Date"
msgstr ""
#: mod/network.php:832
msgid "Posts that mention or involve you"
msgstr ""
#: mod/network.php:840
msgid "New"
msgstr ""
#: mod/network.php:843
msgid "Activity Stream - by date"
msgstr ""
#: mod/network.php:851
msgid "Shared Links"
msgstr ""
#: mod/network.php:854
msgid "Interesting Links"
msgstr ""
#: mod/network.php:862
msgid "Starred"
msgstr ""
#: mod/network.php:865
msgid "Favourite Posts"
msgstr ""
#: mod/newmember.php:6
msgid "Welcome to Friendica"
msgstr ""
#: mod/newmember.php:8
msgid "New Member Checklist"
msgstr ""
#: mod/newmember.php:12
msgid ""
"We would like to offer some tips and links to help make your experience "
"enjoyable. Click any item to visit the relevant page. A link to this page "
"will be visible from your home page for two weeks after your initial "
"registration and then will quietly disappear."
msgstr ""
#: mod/newmember.php:14
msgid "Getting Started"
msgstr ""
#: mod/newmember.php:18
msgid "Friendica Walk-Through"
msgstr ""
#: mod/newmember.php:18
msgid ""
"On your <em>Quick Start</em> page - find a brief introduction to your "
"profile and network tabs, make some new connections, and find some groups to "
"join."
msgstr ""
#: mod/newmember.php:26
msgid "Go to Your Settings"
msgstr ""
#: mod/newmember.php:26
msgid ""
"On your <em>Settings</em> page - change your initial password. Also make a "
"note of your Identity Address. This looks just like an email address - and "
"will be useful in making friends on the free social web."
msgstr ""
#: mod/newmember.php:28
msgid ""
"Review the other settings, particularly the privacy settings. An unpublished "
"directory listing is like having an unlisted phone number. In general, you "
"should probably publish your listing - unless all of your friends and "
"potential friends know exactly how to find you."
msgstr ""
#: mod/newmember.php:36 mod/profile_photo.php:256 mod/profiles.php:699
msgid "Upload Profile Photo"
msgstr ""
#: mod/newmember.php:36
msgid ""
"Upload a profile photo if you have not done so already. Studies have shown "
"that people with real photos of themselves are ten times more likely to make "
"friends than people who do not."
msgstr ""
#: mod/newmember.php:38
msgid "Edit Your Profile"
msgstr ""
#: mod/newmember.php:38
msgid ""
"Edit your <strong>default</strong> profile to your liking. Review the "
"settings for hiding your list of friends and hiding the profile from unknown "
"visitors."
msgstr ""
#: mod/newmember.php:40
msgid "Profile Keywords"
msgstr ""
#: mod/newmember.php:40
msgid ""
"Set some public keywords for your default profile which describe your "
"interests. We may be able to find other people with similar interests and "
"suggest friendships."
msgstr ""
#: mod/newmember.php:44
msgid "Connecting"
msgstr ""
#: mod/newmember.php:51
msgid "Importing Emails"
msgstr ""
#: mod/newmember.php:51
msgid ""
"Enter your email access information on your Connector Settings page if you "
"wish to import and interact with friends or mailing lists from your email "
"INBOX"
msgstr ""
#: mod/newmember.php:53
msgid "Go to Your Contacts Page"
msgstr ""
#: mod/newmember.php:53
msgid ""
"Your Contacts page is your gateway to managing friendships and connecting "
"with friends on other networks. Typically you enter their address or site "
"URL in the <em>Add New Contact</em> dialog."
msgstr ""
#: mod/newmember.php:55
msgid "Go to Your Site's Directory"
msgstr ""
#: mod/newmember.php:55
msgid ""
"The Directory page lets you find other people in this network or other "
"federated sites. Look for a <em>Connect</em> or <em>Follow</em> link on "
"their profile page. Provide your own Identity Address if requested."
msgstr ""
#: mod/newmember.php:57
msgid "Finding New People"
msgstr ""
#: mod/newmember.php:57
msgid ""
"On the side panel of the Contacts page are several tools to find new "
"friends. We can match people by interest, look up people by name or "
"interest, and provide suggestions based on network relationships. On a brand "
"new site, friend suggestions will usually begin to be populated within 24 "
"hours."
msgstr ""
#: mod/newmember.php:65
msgid "Group Your Contacts"
msgstr ""
#: mod/newmember.php:65
msgid ""
"Once you have made some friends, organize them into private conversation "
"groups from the sidebar of your Contacts page and then you can interact with "
"each group privately on your Network page."
msgstr ""
#: mod/newmember.php:68
msgid "Why Aren't My Posts Public?"
msgstr ""
#: mod/newmember.php:68
msgid ""
"Friendica respects your privacy. By default, your posts will only show up to "
"people you've added as friends. For more information, see the help section "
"from the link above."
msgstr ""
#: mod/newmember.php:73
msgid "Getting Help"
msgstr ""
#: mod/newmember.php:77
msgid "Go to the Help Section"
msgstr ""
#: mod/newmember.php:77
msgid ""
"Our <strong>help</strong> pages may be consulted for detail on other program "
"features and resources."
msgstr ""
#: mod/nogroup.php:65
msgid "Contacts who are not members of a group"
msgstr ""
#: mod/notifications.php:35
msgid "Invalid request identifier."
msgstr ""
#: mod/notifications.php:44 mod/notifications.php:180
#: mod/notifications.php:258
msgid "Discard"
msgstr ""
#: mod/notifications.php:105
msgid "Network Notifications"
msgstr ""
#: mod/notifications.php:111 mod/notify.php:69
msgid "System Notifications"
msgstr ""
#: mod/notifications.php:117
msgid "Personal Notifications"
msgstr ""
#: mod/notifications.php:123
msgid "Home Notifications"
msgstr ""
#: mod/notifications.php:152
msgid "Show Ignored Requests"
msgstr ""
#: mod/notifications.php:152
msgid "Hide Ignored Requests"
msgstr ""
#: mod/notifications.php:164 mod/notifications.php:228
msgid "Notification type: "
msgstr ""
#: mod/notifications.php:167
#, php-format
msgid "suggested by %s"
msgstr ""
#: mod/notifications.php:173 mod/notifications.php:246
msgid "Post a new friend activity"
msgstr ""
#: mod/notifications.php:173 mod/notifications.php:246
msgid "if applicable"
msgstr ""
#: mod/notifications.php:195
msgid "Claims to be known to you: "
msgstr ""
#: mod/notifications.php:196
msgid "yes"
msgstr ""
#: mod/notifications.php:196
msgid "no"
msgstr ""
#: mod/notifications.php:197 mod/notifications.php:202
msgid "Shall your connection be bidirectional or not?"
msgstr ""
#: mod/notifications.php:198 mod/notifications.php:203
#, php-format
msgid ""
"Accepting %s as a friend allows %s to subscribe to your posts, and you will "
"also receive updates from them in your news feed."
msgstr ""
#: mod/notifications.php:199
#, php-format
msgid ""
"Accepting %s as a subscriber allows them to subscribe to your posts, but you "
"will not receive updates from them in your news feed."
msgstr ""
#: mod/notifications.php:204
#, php-format
msgid ""
"Accepting %s as a sharer allows them to subscribe to your posts, but you "
"will not receive updates from them in your news feed."
msgstr ""
#: mod/notifications.php:215
msgid "Friend"
msgstr ""
#: mod/notifications.php:216
msgid "Sharer"
msgstr ""
#: mod/notifications.php:216
msgid "Subscriber"
msgstr ""
#: mod/notifications.php:266
msgid "No introductions."
msgstr ""
#: mod/notifications.php:307
msgid "Show unread"
msgstr ""
#: mod/notifications.php:307
msgid "Show all"
msgstr ""
#: mod/notifications.php:313
#, php-format
msgid "No more %s notifications."
msgstr ""
#: mod/notify.php:65
msgid "No more system notifications."
msgstr ""
#: mod/oexchange.php:21
msgid "Post successful."
msgstr ""
#: mod/openid.php:24
msgid "OpenID protocol error. No ID returned."
msgstr ""
#: mod/openid.php:60
msgid ""
"Account not found and OpenID registration is not permitted on this site."
msgstr ""
#: mod/ostatus_subscribe.php:14
msgid "Subscribing to OStatus contacts"
msgstr ""
#: mod/ostatus_subscribe.php:25
msgid "No contact provided."
msgstr ""
#: mod/ostatus_subscribe.php:31
msgid "Couldn't fetch information for contact."
msgstr ""
#: mod/ostatus_subscribe.php:40
msgid "Couldn't fetch friends for contact."
msgstr ""
#: mod/ostatus_subscribe.php:54 mod/repair_ostatus.php:44
msgid "Done"
msgstr ""
#: mod/ostatus_subscribe.php:68
msgid "success"
msgstr ""
#: mod/ostatus_subscribe.php:70
msgid "failed"
msgstr ""
#: mod/ostatus_subscribe.php:78 mod/repair_ostatus.php:50
msgid "Keep this window open until done."
msgstr ""
#: mod/p.php:9
msgid "Not Extended"
msgstr ""
#: mod/photos.php:90 mod/photos.php:1876
msgid "Recent Photos"
msgstr ""
#: mod/photos.php:93 mod/photos.php:1303 mod/photos.php:1878
msgid "Upload New Photos"
msgstr ""
#: mod/photos.php:107 mod/settings.php:36
msgid "everybody"
msgstr ""
#: mod/photos.php:171
msgid "Contact information unavailable"
msgstr ""
#: mod/photos.php:192
msgid "Album not found."
msgstr ""
#: mod/photos.php:225 mod/photos.php:237 mod/photos.php:1247
msgid "Delete Album"
msgstr ""
#: mod/photos.php:235
msgid "Do you really want to delete this photo album and all its photos?"
msgstr ""
#: mod/photos.php:317 mod/photos.php:328 mod/photos.php:1563
msgid "Delete Photo"
msgstr ""
#: mod/photos.php:326
msgid "Do you really want to delete this photo?"
msgstr ""
#: mod/photos.php:705
#, php-format
msgid "%1$s was tagged in %2$s by %3$s"
msgstr ""
#: mod/photos.php:705
msgid "a photo"
msgstr ""
#: mod/photos.php:803 mod/profile_photo.php:156 mod/wall_upload.php:151
#, php-format
msgid "Image exceeds size limit of %s"
msgstr ""
#: mod/photos.php:811
msgid "Image file is empty."
msgstr ""
#: mod/photos.php:844 mod/profile_photo.php:165 mod/wall_upload.php:186
msgid "Unable to process image."
msgstr ""
#: mod/photos.php:871 mod/profile_photo.php:315 mod/wall_upload.php:219
msgid "Image upload failed."
msgstr ""
#: mod/photos.php:974
msgid "No photos selected"
msgstr ""
#: mod/photos.php:1074 mod/videos.php:309
msgid "Access to this item is restricted."
msgstr ""
#: mod/photos.php:1134
#, php-format
msgid "You have used %1$.2f Mbytes of %2$.2f Mbytes photo storage."
msgstr ""
#: mod/photos.php:1168
msgid "Upload Photos"
msgstr ""
#: mod/photos.php:1172 mod/photos.php:1242
msgid "New album name: "
msgstr ""
#: mod/photos.php:1173
msgid "or existing album name: "
msgstr ""
#: mod/photos.php:1174
msgid "Do not show a status post for this upload"
msgstr ""
#: mod/photos.php:1185 mod/photos.php:1567 mod/settings.php:1307
msgid "Show to Groups"
msgstr ""
#: mod/photos.php:1186 mod/photos.php:1568 mod/settings.php:1308
msgid "Show to Contacts"
msgstr ""
#: mod/photos.php:1187
msgid "Private Photo"
msgstr ""
#: mod/photos.php:1188
msgid "Public Photo"
msgstr ""
#: mod/photos.php:1254
msgid "Edit Album"
msgstr ""
#: mod/photos.php:1260
msgid "Show Newest First"
msgstr ""
#: mod/photos.php:1262
msgid "Show Oldest First"
msgstr ""
#: mod/photos.php:1289 mod/photos.php:1861
msgid "View Photo"
msgstr ""
#: mod/photos.php:1335
msgid "Permission denied. Access to this item may be restricted."
msgstr ""
#: mod/photos.php:1337
msgid "Photo not available"
msgstr ""
#: mod/photos.php:1395
msgid "View photo"
msgstr ""
#: mod/photos.php:1395
msgid "Edit photo"
msgstr ""
#: mod/photos.php:1396
msgid "Use as profile photo"
msgstr ""
#: mod/photos.php:1421
msgid "View Full Size"
msgstr ""
#: mod/photos.php:1507
msgid "Tags: "
msgstr ""
#: mod/photos.php:1510
msgid "[Remove any tag]"
msgstr ""
#: mod/photos.php:1549
msgid "New album name"
msgstr ""
#: mod/photos.php:1550
msgid "Caption"
msgstr ""
#: mod/photos.php:1551
msgid "Add a Tag"
msgstr ""
#: mod/photos.php:1551
msgid "Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"
msgstr ""
#: mod/photos.php:1552
msgid "Do not rotate"
msgstr ""
#: mod/photos.php:1553
msgid "Rotate CW (right)"
msgstr ""
#: mod/photos.php:1554
msgid "Rotate CCW (left)"
msgstr ""
#: mod/photos.php:1569
msgid "Private photo"
msgstr ""
#: mod/photos.php:1570
msgid "Public photo"
msgstr ""
#: mod/photos.php:1792
msgid "Map"
msgstr ""
#: mod/photos.php:1867 mod/videos.php:391
msgid "View Album"
msgstr ""
#: mod/ping.php:270
msgid "{0} wants to be your friend"
msgstr ""
#: mod/ping.php:285
msgid "{0} sent you a message"
msgstr ""
#: mod/ping.php:300
msgid "{0} requested registration"
msgstr ""
#: mod/poke.php:196
msgid "Poke/Prod"
msgstr ""
#: mod/poke.php:197
msgid "poke, prod or do other things to somebody"
msgstr ""
#: mod/poke.php:198
msgid "Recipient"
msgstr ""
#: mod/poke.php:199
msgid "Choose what you wish to do to recipient"
msgstr ""
#: mod/poke.php:202
msgid "Make this post private"
msgstr ""
#: mod/profile.php:174
msgid "Tips for New Members"
msgstr ""
#: mod/profile_photo.php:44
msgid "Image uploaded but image cropping failed."
msgstr ""
#: mod/profile_photo.php:77 mod/profile_photo.php:85 mod/profile_photo.php:93
#: mod/profile_photo.php:323
#, php-format
msgid "Image size reduction [%s] failed."
msgstr ""
#: mod/profile_photo.php:127
msgid ""
"Shift-reload the page or clear browser cache if the new photo does not "
"display immediately."
msgstr ""
#: mod/profile_photo.php:137
msgid "Unable to process image"
msgstr ""
#: mod/profile_photo.php:254
msgid "Upload File:"
msgstr ""
#: mod/profile_photo.php:255
msgid "Select a profile:"
msgstr ""
#: mod/profile_photo.php:257
msgid "Upload"
msgstr ""
#: mod/profile_photo.php:260
msgid "or"
msgstr ""
#: mod/profile_photo.php:260
msgid "skip this step"
msgstr ""
#: mod/profile_photo.php:260
msgid "select a photo from your photo albums"
msgstr ""
#: mod/profile_photo.php:274
msgid "Crop Image"
msgstr ""
#: mod/profile_photo.php:275
msgid "Please adjust the image cropping for optimum viewing."
msgstr ""
#: mod/profile_photo.php:277
msgid "Done Editing"
msgstr ""
#: mod/profile_photo.php:313
msgid "Image uploaded successfully."
msgstr ""
#: mod/profiles.php:38
msgid "Profile deleted."
msgstr ""
@ -7115,1453 +7626,160 @@ msgstr ""
msgid "Edit/Manage Profiles"
msgstr ""
#: mod/display.php:479
msgid "Item has been removed."
#: mod/profperm.php:26 mod/profperm.php:57
msgid "Invalid profile identifier."
msgstr ""
#: mod/admin.php:92
msgid "Theme settings updated."
#: mod/profperm.php:103
msgid "Profile Visibility Editor"
msgstr ""
#: mod/admin.php:157 mod/admin.php:975
msgid "Site"
#: mod/profperm.php:116
msgid "Visible To"
msgstr ""
#: mod/admin.php:158 mod/admin.php:909 mod/admin.php:1425 mod/admin.php:1441
msgid "Users"
#: mod/profperm.php:132
msgid "All Contacts (with secure profile access)"
msgstr ""
#: mod/admin.php:160 mod/admin.php:1813 mod/admin.php:1863
msgid "Themes"
msgstr ""
#: mod/admin.php:162
msgid "DB updates"
msgstr ""
#: mod/admin.php:163 mod/admin.php:407
msgid "Inspect Queue"
msgstr ""
#: mod/admin.php:164 mod/admin.php:373
msgid "Federation Statistics"
msgstr ""
#: mod/admin.php:178 mod/admin.php:189 mod/admin.php:1937
msgid "Logs"
msgstr ""
#: mod/admin.php:179 mod/admin.php:2005
msgid "View Logs"
msgstr ""
#: mod/admin.php:180
msgid "probe address"
msgstr ""
#: mod/admin.php:181
msgid "check webfinger"
msgstr ""
#: mod/admin.php:188
msgid "Plugin Features"
msgstr ""
#: mod/admin.php:190
msgid "diagnostics"
msgstr ""
#: mod/admin.php:191
msgid "User registrations waiting for confirmation"
msgstr ""
#: mod/admin.php:307
msgid "unknown"
msgstr ""
#: mod/admin.php:366
#: mod/register.php:93
msgid ""
"This page offers you some numbers to the known part of the federated social "
"network your Friendica node is part of. These numbers are not complete but "
"only reflect the part of the network your node is aware of."
"Registration successful. Please check your email for further instructions."
msgstr ""
#: mod/admin.php:367
msgid ""
"The <em>Auto Discovered Contact Directory</em> feature is not enabled, it "
"will improve the data displayed here."
msgstr ""
#: mod/admin.php:372 mod/admin.php:406 mod/admin.php:485 mod/admin.php:974
#: mod/admin.php:1424 mod/admin.php:1542 mod/admin.php:1605 mod/admin.php:1812
#: mod/admin.php:1862 mod/admin.php:1936 mod/admin.php:2004
msgid "Administration"
msgstr ""
#: mod/admin.php:379
#, php-format
msgid "Currently this node is aware of %d nodes from the following platforms:"
msgstr ""
#: mod/admin.php:409
msgid "ID"
msgstr ""
#: mod/admin.php:410
msgid "Recipient Name"
msgstr ""
#: mod/admin.php:411
msgid "Recipient Profile"
msgstr ""
#: mod/admin.php:413
msgid "Created"
msgstr ""
#: mod/admin.php:414
msgid "Last Tried"
msgstr ""
#: mod/admin.php:415
msgid ""
"This page lists the content of the queue for outgoing postings. These are "
"postings the initial delivery failed for. They will be resend later and "
"eventually deleted if the delivery fails permanently."
msgstr ""
#: mod/admin.php:440
#: mod/register.php:98
#, php-format
msgid ""
"Your DB still runs with MyISAM tables. You should change the engine type to "
"InnoDB. As Friendica will use InnoDB only features in the future, you should "
"change this! See <a href=\"%s\">here</a> for a guide that may be helpful "
"converting the table engines. You may also use the <tt>convert_innodb.sql</"
"tt> in the <tt>/util</tt> directory of your Friendica installation.<br />"
"Failed to send email message. Here your accout details:<br> login: %s<br> "
"password: %s<br><br>You can change your password after login."
msgstr ""
#: mod/admin.php:445
#: mod/register.php:105
msgid "Registration successful."
msgstr ""
#: mod/register.php:111
msgid "Your registration can not be processed."
msgstr ""
#: mod/register.php:160
msgid "Your registration is pending approval by the site owner."
msgstr ""
#: mod/register.php:198 mod/uimport.php:51
msgid ""
"You are using a MySQL version which does not support all features that "
"Friendica uses. You should consider switching to MariaDB."
"This site has exceeded the number of allowed daily account registrations. "
"Please try again tomorrow."
msgstr ""
#: mod/admin.php:449 mod/admin.php:1373
msgid "Normal Account"
msgstr ""
#: mod/admin.php:450 mod/admin.php:1374
msgid "Soapbox Account"
msgstr ""
#: mod/admin.php:451 mod/admin.php:1375
msgid "Community/Celebrity Account"
msgstr ""
#: mod/admin.php:452 mod/admin.php:1376
msgid "Automatic Friend Account"
msgstr ""
#: mod/admin.php:453
msgid "Blog Account"
msgstr ""
#: mod/admin.php:454
msgid "Private Forum"
msgstr ""
#: mod/admin.php:480
msgid "Message queues"
msgstr ""
#: mod/admin.php:486
msgid "Summary"
msgstr ""
#: mod/admin.php:489
msgid "Registered users"
msgstr ""
#: mod/admin.php:491
msgid "Pending registrations"
msgstr ""
#: mod/admin.php:492
msgid "Version"
msgstr ""
#: mod/admin.php:497
msgid "Active plugins"
msgstr ""
#: mod/admin.php:522
msgid "Can not parse base url. Must have at least <scheme>://<domain>"
msgstr ""
#: mod/admin.php:827
msgid "RINO2 needs mcrypt php extension to work."
msgstr ""
#: mod/admin.php:835
msgid "Site settings updated."
msgstr ""
#: mod/admin.php:892
msgid "No community page"
msgstr ""
#: mod/admin.php:893
msgid "Public postings from users of this site"
msgstr ""
#: mod/admin.php:894
msgid "Global community page"
msgstr ""
#: mod/admin.php:900
msgid "At post arrival"
msgstr ""
#: mod/admin.php:910
msgid "Users, Global Contacts"
msgstr ""
#: mod/admin.php:911
msgid "Users, Global Contacts/fallback"
msgstr ""
#: mod/admin.php:915
msgid "One month"
msgstr ""
#: mod/admin.php:916
msgid "Three months"
msgstr ""
#: mod/admin.php:917
msgid "Half a year"
msgstr ""
#: mod/admin.php:918
msgid "One year"
msgstr ""
#: mod/admin.php:923
msgid "Multi user instance"
msgstr ""
#: mod/admin.php:946
msgid "Closed"
msgstr ""
#: mod/admin.php:947
msgid "Requires approval"
msgstr ""
#: mod/admin.php:948
msgid "Open"
msgstr ""
#: mod/admin.php:952
msgid "No SSL policy, links will track page SSL state"
msgstr ""
#: mod/admin.php:953
msgid "Force all links to use SSL"
msgstr ""
#: mod/admin.php:954
msgid "Self-signed certificate, use SSL for local links only (discouraged)"
msgstr ""
#: mod/admin.php:978
msgid "File upload"
msgstr ""
#: mod/admin.php:979
msgid "Policies"
msgstr ""
#: mod/admin.php:981
msgid "Auto Discovered Contact Directory"
msgstr ""
#: mod/admin.php:982
msgid "Performance"
msgstr ""
#: mod/admin.php:983
msgid "Worker"
msgstr ""
#: mod/admin.php:984
#: mod/register.php:226
msgid ""
"Relocate - WARNING: advanced function. Could make this server unreachable."
"You may (optionally) fill in this form via OpenID by supplying your OpenID "
"and clicking 'Register'."
msgstr ""
#: mod/admin.php:987
msgid "Site name"
msgstr ""
#: mod/admin.php:988
msgid "Host name"
msgstr ""
#: mod/admin.php:989
msgid "Sender Email"
msgstr ""
#: mod/admin.php:989
#: mod/register.php:227
msgid ""
"The email address your server shall use to send notification emails from."
"If you are not familiar with OpenID, please leave that field blank and fill "
"in the rest of the items."
msgstr ""
#: mod/admin.php:990
msgid "Banner/Logo"
#: mod/register.php:228
msgid "Your OpenID (optional): "
msgstr ""
#: mod/admin.php:991
msgid "Shortcut icon"
#: mod/register.php:242
msgid "Include your profile in member directory?"
msgstr ""
#: mod/admin.php:991
msgid "Link to an icon that will be used for browsers."
#: mod/register.php:267
msgid "Note for the admin"
msgstr ""
#: mod/admin.php:992
msgid "Touch icon"
#: mod/register.php:267
msgid "Leave a message for the admin, why you want to join this node"
msgstr ""
#: mod/admin.php:992
msgid "Link to an icon that will be used for tablets and mobiles."
#: mod/register.php:268
msgid "Membership on this site is by invitation only."
msgstr ""
#: mod/admin.php:993
msgid "Additional Info"
#: mod/register.php:269
msgid "Your invitation ID: "
msgstr ""
#: mod/admin.php:993
#: mod/register.php:280
msgid "Your Full Name (e.g. Joe Smith, real or real-looking): "
msgstr ""
#: mod/register.php:281
msgid "Your Email Address: "
msgstr ""
#: mod/register.php:283 mod/settings.php:1278
msgid "New Password:"
msgstr ""
#: mod/register.php:283
msgid "Leave empty for an auto generated password."
msgstr ""
#: mod/register.php:284 mod/settings.php:1279
msgid "Confirm:"
msgstr ""
#: mod/register.php:285
msgid ""
"Choose a profile nickname. This must begin with a text character. Your "
"profile address on this site will then be '<strong>nickname@$sitename</"
"strong>'."
msgstr ""
#: mod/register.php:286
msgid "Choose a nickname: "
msgstr ""
#: mod/register.php:295 mod/uimport.php:66
msgid "Import"
msgstr ""
#: mod/register.php:296
msgid "Import your profile to this friendica instance"
msgstr ""
#: mod/regmod.php:58
msgid "Account approved."
msgstr ""
#: mod/regmod.php:95
#, php-format
msgid "Registration revoked for %s"
msgstr ""
#: mod/regmod.php:107
msgid "Please login."
msgstr ""
#: mod/removeme.php:52 mod/removeme.php:55
msgid "Remove My Account"
msgstr ""
#: mod/removeme.php:53
msgid ""
"For public servers: you can add additional information here that will be "
"listed at %s/siteinfo."
"This will completely remove your account. Once this has been done it is not "
"recoverable."
msgstr ""
#: mod/admin.php:994
msgid "System language"
#: mod/removeme.php:54
msgid "Please enter your password for verification:"
msgstr ""
#: mod/admin.php:995
msgid "System theme"
#: mod/repair_ostatus.php:14
msgid "Resubscribing to OStatus contacts"
msgstr ""
#: mod/admin.php:995
msgid ""
"Default system theme - may be over-ridden by user profiles - <a href='#' "
"id='cnftheme'>change theme settings</a>"
msgstr ""
#: mod/admin.php:996
msgid "Mobile system theme"
msgstr ""
#: mod/admin.php:996
msgid "Theme for mobile devices"
msgstr ""
#: mod/admin.php:997
msgid "SSL link policy"
msgstr ""
#: mod/admin.php:997
msgid "Determines whether generated links should be forced to use SSL"
msgstr ""
#: mod/admin.php:998
msgid "Force SSL"
msgstr ""
#: mod/admin.php:998
msgid ""
"Force all Non-SSL requests to SSL - Attention: on some systems it could lead "
"to endless loops."
msgstr ""
#: mod/admin.php:999
msgid "Old style 'Share'"
msgstr ""
#: mod/admin.php:999
msgid "Deactivates the bbcode element 'share' for repeating items."
msgstr ""
#: mod/admin.php:1000
msgid "Hide help entry from navigation menu"
msgstr ""
#: mod/admin.php:1000
msgid ""
"Hides the menu entry for the Help pages from the navigation menu. You can "
"still access it calling /help directly."
msgstr ""
#: mod/admin.php:1001
msgid "Single user instance"
msgstr ""
#: mod/admin.php:1001
msgid "Make this instance multi-user or single-user for the named user"
msgstr ""
#: mod/admin.php:1002
msgid "Maximum image size"
msgstr ""
#: mod/admin.php:1002
msgid ""
"Maximum size in bytes of uploaded images. Default is 0, which means no "
"limits."
msgstr ""
#: mod/admin.php:1003
msgid "Maximum image length"
msgstr ""
#: mod/admin.php:1003
msgid ""
"Maximum length in pixels of the longest side of uploaded images. Default is "
"-1, which means no limits."
msgstr ""
#: mod/admin.php:1004
msgid "JPEG image quality"
msgstr ""
#: mod/admin.php:1004
msgid ""
"Uploaded JPEGS will be saved at this quality setting [0-100]. Default is "
"100, which is full quality."
msgstr ""
#: mod/admin.php:1006
msgid "Register policy"
msgstr ""
#: mod/admin.php:1007
msgid "Maximum Daily Registrations"
msgstr ""
#: mod/admin.php:1007
msgid ""
"If registration is permitted above, this sets the maximum number of new user "
"registrations to accept per day. If register is set to closed, this setting "
"has no effect."
msgstr ""
#: mod/admin.php:1008
msgid "Register text"
msgstr ""
#: mod/admin.php:1008
msgid "Will be displayed prominently on the registration page."
msgstr ""
#: mod/admin.php:1009
msgid "Accounts abandoned after x days"
msgstr ""
#: mod/admin.php:1009
msgid ""
"Will not waste system resources polling external sites for abandonded "
"accounts. Enter 0 for no time limit."
msgstr ""
#: mod/admin.php:1010
msgid "Allowed friend domains"
msgstr ""
#: mod/admin.php:1010
msgid ""
"Comma separated list of domains which are allowed to establish friendships "
"with this site. Wildcards are accepted. Empty to allow any domains"
msgstr ""
#: mod/admin.php:1011
msgid "Allowed email domains"
msgstr ""
#: mod/admin.php:1011
msgid ""
"Comma separated list of domains which are allowed in email addresses for "
"registrations to this site. Wildcards are accepted. Empty to allow any "
"domains"
msgstr ""
#: mod/admin.php:1012
msgid "Block public"
msgstr ""
#: mod/admin.php:1012
msgid ""
"Check to block public access to all otherwise public personal pages on this "
"site unless you are currently logged in."
msgstr ""
#: mod/admin.php:1013
msgid "Force publish"
msgstr ""
#: mod/admin.php:1013
msgid ""
"Check to force all profiles on this site to be listed in the site directory."
msgstr ""
#: mod/admin.php:1014
msgid "Global directory URL"
msgstr ""
#: mod/admin.php:1014
msgid ""
"URL to the global directory. If this is not set, the global directory is "
"completely unavailable to the application."
msgstr ""
#: mod/admin.php:1015
msgid "Allow threaded items"
msgstr ""
#: mod/admin.php:1015
msgid "Allow infinite level threading for items on this site."
msgstr ""
#: mod/admin.php:1016
msgid "Private posts by default for new users"
msgstr ""
#: mod/admin.php:1016
msgid ""
"Set default post permissions for all new members to the default privacy "
"group rather than public."
msgstr ""
#: mod/admin.php:1017
msgid "Don't include post content in email notifications"
msgstr ""
#: mod/admin.php:1017
msgid ""
"Don't include the content of a post/comment/private message/etc. in the "
"email notifications that are sent out from this site, as a privacy measure."
msgstr ""
#: mod/admin.php:1018
msgid "Disallow public access to addons listed in the apps menu."
msgstr ""
#: mod/admin.php:1018
msgid ""
"Checking this box will restrict addons listed in the apps menu to members "
"only."
msgstr ""
#: mod/admin.php:1019
msgid "Don't embed private images in posts"
msgstr ""
#: mod/admin.php:1019
msgid ""
"Don't replace locally-hosted private photos in posts with an embedded copy "
"of the image. This means that contacts who receive posts containing private "
"photos will have to authenticate and load each image, which may take a while."
msgstr ""
#: mod/admin.php:1020
msgid "Allow Users to set remote_self"
msgstr ""
#: mod/admin.php:1020
msgid ""
"With checking this, every user is allowed to mark every contact as a "
"remote_self in the repair contact dialog. Setting this flag on a contact "
"causes mirroring every posting of that contact in the users stream."
msgstr ""
#: mod/admin.php:1021
msgid "Block multiple registrations"
msgstr ""
#: mod/admin.php:1021
msgid "Disallow users to register additional accounts for use as pages."
msgstr ""
#: mod/admin.php:1022
msgid "OpenID support"
msgstr ""
#: mod/admin.php:1022
msgid "OpenID support for registration and logins."
msgstr ""
#: mod/admin.php:1023
msgid "Fullname check"
msgstr ""
#: mod/admin.php:1023
msgid ""
"Force users to register with a space between firstname and lastname in Full "
"name, as an antispam measure"
msgstr ""
#: mod/admin.php:1024
msgid "UTF-8 Regular expressions"
msgstr ""
#: mod/admin.php:1024
msgid "Use PHP UTF8 regular expressions"
msgstr ""
#: mod/admin.php:1025
msgid "Community Page Style"
msgstr ""
#: mod/admin.php:1025
msgid ""
"Type of community page to show. 'Global community' shows every public "
"posting from an open distributed network that arrived on this server."
msgstr ""
#: mod/admin.php:1026
msgid "Posts per user on community page"
msgstr ""
#: mod/admin.php:1026
msgid ""
"The maximum number of posts per user on the community page. (Not valid for "
"'Global Community')"
msgstr ""
#: mod/admin.php:1027
msgid "Enable OStatus support"
msgstr ""
#: mod/admin.php:1027
msgid ""
"Provide built-in OStatus (StatusNet, GNU Social etc.) compatibility. All "
"communications in OStatus are public, so privacy warnings will be "
"occasionally displayed."
msgstr ""
#: mod/admin.php:1028
msgid "OStatus conversation completion interval"
msgstr ""
#: mod/admin.php:1028
msgid ""
"How often shall the poller check for new entries in OStatus conversations? "
"This can be a very ressource task."
msgstr ""
#: mod/admin.php:1029
msgid "Only import OStatus threads from our contacts"
msgstr ""
#: mod/admin.php:1029
msgid ""
"Normally we import every content from our OStatus contacts. With this option "
"we only store threads that are started by a contact that is known on our "
"system."
msgstr ""
#: mod/admin.php:1030
msgid "OStatus support can only be enabled if threading is enabled."
msgstr ""
#: mod/admin.php:1032
msgid ""
"Diaspora support can't be enabled because Friendica was installed into a sub "
"directory."
msgstr ""
#: mod/admin.php:1033
msgid "Enable Diaspora support"
msgstr ""
#: mod/admin.php:1033
msgid "Provide built-in Diaspora network compatibility."
msgstr ""
#: mod/admin.php:1034
msgid "Only allow Friendica contacts"
msgstr ""
#: mod/admin.php:1034
msgid ""
"All contacts must use Friendica protocols. All other built-in communication "
"protocols disabled."
msgstr ""
#: mod/admin.php:1035
msgid "Verify SSL"
msgstr ""
#: mod/admin.php:1035
msgid ""
"If you wish, you can turn on strict certificate checking. This will mean you "
"cannot connect (at all) to self-signed SSL sites."
msgstr ""
#: mod/admin.php:1036
msgid "Proxy user"
msgstr ""
#: mod/admin.php:1037
msgid "Proxy URL"
msgstr ""
#: mod/admin.php:1038
msgid "Network timeout"
msgstr ""
#: mod/admin.php:1038
msgid "Value is in seconds. Set to 0 for unlimited (not recommended)."
msgstr ""
#: mod/admin.php:1039
msgid "Delivery interval"
msgstr ""
#: mod/admin.php:1039
msgid ""
"Delay background delivery processes by this many seconds to reduce system "
"load. Recommend: 4-5 for shared hosts, 2-3 for virtual private servers. 0-1 "
"for large dedicated servers."
msgstr ""
#: mod/admin.php:1040
msgid "Poll interval"
msgstr ""
#: mod/admin.php:1040
msgid ""
"Delay background polling processes by this many seconds to reduce system "
"load. If 0, use delivery interval."
msgstr ""
#: mod/admin.php:1041
msgid "Maximum Load Average"
msgstr ""
#: mod/admin.php:1041
msgid ""
"Maximum system load before delivery and poll processes are deferred - "
"default 50."
msgstr ""
#: mod/admin.php:1042
msgid "Maximum Load Average (Frontend)"
msgstr ""
#: mod/admin.php:1042
msgid "Maximum system load before the frontend quits service - default 50."
msgstr ""
#: mod/admin.php:1043
msgid "Maximum table size for optimization"
msgstr ""
#: mod/admin.php:1043
msgid ""
"Maximum table size (in MB) for the automatic optimization - default 100 MB. "
"Enter -1 to disable it."
msgstr ""
#: mod/admin.php:1044
msgid "Minimum level of fragmentation"
msgstr ""
#: mod/admin.php:1044
msgid ""
"Minimum fragmenation level to start the automatic optimization - default "
"value is 30%."
msgstr ""
#: mod/admin.php:1046
msgid "Periodical check of global contacts"
msgstr ""
#: mod/admin.php:1046
msgid ""
"If enabled, the global contacts are checked periodically for missing or "
"outdated data and the vitality of the contacts and servers."
msgstr ""
#: mod/admin.php:1047
msgid "Days between requery"
msgstr ""
#: mod/admin.php:1047
msgid "Number of days after which a server is requeried for his contacts."
msgstr ""
#: mod/admin.php:1048
msgid "Discover contacts from other servers"
msgstr ""
#: mod/admin.php:1048
msgid ""
"Periodically query other servers for contacts. You can choose between "
"'users': the users on the remote system, 'Global Contacts': active contacts "
"that are known on the system. The fallback is meant for Redmatrix servers "
"and older friendica servers, where global contacts weren't available. The "
"fallback increases the server load, so the recommened setting is 'Users, "
"Global Contacts'."
msgstr ""
#: mod/admin.php:1049
msgid "Timeframe for fetching global contacts"
msgstr ""
#: mod/admin.php:1049
msgid ""
"When the discovery is activated, this value defines the timeframe for the "
"activity of the global contacts that are fetched from other servers."
msgstr ""
#: mod/admin.php:1050
msgid "Search the local directory"
msgstr ""
#: mod/admin.php:1050
msgid ""
"Search the local directory instead of the global directory. When searching "
"locally, every search will be executed on the global directory in the "
"background. This improves the search results when the search is repeated."
msgstr ""
#: mod/admin.php:1052
msgid "Publish server information"
msgstr ""
#: mod/admin.php:1052
msgid ""
"If enabled, general server and usage data will be published. The data "
"contains the name and version of the server, number of users with public "
"profiles, number of posts and the activated protocols and connectors. See <a "
"href='http://the-federation.info/'>the-federation.info</a> for details."
msgstr ""
#: mod/admin.php:1054
msgid "Use MySQL full text engine"
msgstr ""
#: mod/admin.php:1054
msgid ""
"Activates the full text engine. Speeds up search - but can only search for "
"four and more characters."
msgstr ""
#: mod/admin.php:1055
msgid "Suppress Language"
msgstr ""
#: mod/admin.php:1055
msgid "Suppress language information in meta information about a posting."
msgstr ""
#: mod/admin.php:1056
msgid "Suppress Tags"
msgstr ""
#: mod/admin.php:1056
msgid "Suppress showing a list of hashtags at the end of the posting."
msgstr ""
#: mod/admin.php:1057
msgid "Path to item cache"
msgstr ""
#: mod/admin.php:1057
msgid "The item caches buffers generated bbcode and external images."
msgstr ""
#: mod/admin.php:1058
msgid "Cache duration in seconds"
msgstr ""
#: mod/admin.php:1058
msgid ""
"How long should the cache files be hold? Default value is 86400 seconds (One "
"day). To disable the item cache, set the value to -1."
msgstr ""
#: mod/admin.php:1059
msgid "Maximum numbers of comments per post"
msgstr ""
#: mod/admin.php:1059
msgid "How much comments should be shown for each post? Default value is 100."
msgstr ""
#: mod/admin.php:1060
msgid "Path for lock file"
msgstr ""
#: mod/admin.php:1060
msgid ""
"The lock file is used to avoid multiple pollers at one time. Only define a "
"folder here."
msgstr ""
#: mod/admin.php:1061
msgid "Temp path"
msgstr ""
#: mod/admin.php:1061
msgid ""
"If you have a restricted system where the webserver can't access the system "
"temp path, enter another path here."
msgstr ""
#: mod/admin.php:1062
msgid "Base path to installation"
msgstr ""
#: mod/admin.php:1062
msgid ""
"If the system cannot detect the correct path to your installation, enter the "
"correct path here. This setting should only be set if you are using a "
"restricted system and symbolic links to your webroot."
msgstr ""
#: mod/admin.php:1063
msgid "Disable picture proxy"
msgstr ""
#: mod/admin.php:1063
msgid ""
"The picture proxy increases performance and privacy. It shouldn't be used on "
"systems with very low bandwith."
msgstr ""
#: mod/admin.php:1064
msgid "Enable old style pager"
msgstr ""
#: mod/admin.php:1064
msgid ""
"The old style pager has page numbers but slows down massively the page speed."
msgstr ""
#: mod/admin.php:1065
msgid "Only search in tags"
msgstr ""
#: mod/admin.php:1065
msgid "On large systems the text search can slow down the system extremely."
msgstr ""
#: mod/admin.php:1067
msgid "New base url"
msgstr ""
#: mod/admin.php:1067
msgid ""
"Change base url for this server. Sends relocate message to all DFRN contacts "
"of all users."
msgstr ""
#: mod/admin.php:1069
msgid "RINO Encryption"
msgstr ""
#: mod/admin.php:1069
msgid "Encryption layer between nodes."
msgstr ""
#: mod/admin.php:1070
msgid "Embedly API key"
msgstr ""
#: mod/admin.php:1070
msgid ""
"<a href='http://embed.ly'>Embedly</a> is used to fetch additional data for "
"web pages. This is an optional parameter."
msgstr ""
#: mod/admin.php:1072
msgid "Enable 'worker' background processing"
msgstr ""
#: mod/admin.php:1072
msgid ""
"The worker background processing limits the number of parallel background "
"jobs to a maximum number and respects the system load."
msgstr ""
#: mod/admin.php:1073
msgid "Maximum number of parallel workers"
msgstr ""
#: mod/admin.php:1073
msgid ""
"On shared hosters set this to 2. On larger systems, values of 10 are great. "
"Default value is 4."
msgstr ""
#: mod/admin.php:1074
msgid "Don't use 'proc_open' with the worker"
msgstr ""
#: mod/admin.php:1074
msgid ""
"Enable this if your system doesn't allow the use of 'proc_open'. This can "
"happen on shared hosters. If this is enabled you should increase the "
"frequency of poller calls in your crontab."
msgstr ""
#: mod/admin.php:1075
msgid "Enable fastlane"
msgstr ""
#: mod/admin.php:1075
msgid ""
"When enabed, the fastlane mechanism starts an additional worker if processes "
"with higher priority are blocked by processes of lower priority."
msgstr ""
#: mod/admin.php:1076
msgid "Enable frontend worker"
msgstr ""
#: mod/admin.php:1076
msgid ""
"When enabled the Worker process is triggered when backend access is "
"performed (e.g. messages being delivered). On smaller sites you might want "
"to call yourdomain.tld/worker on a regular basis via an external cron job. "
"You should only enable this option if you cannot utilize cron/scheduled jobs "
"on your server. The worker background process needs to be activated for this."
msgstr ""
#: mod/admin.php:1105
msgid "Update has been marked successful"
msgstr ""
#: mod/admin.php:1113
#, php-format
msgid "Database structure update %s was successfully applied."
msgstr ""
#: mod/admin.php:1116
#, php-format
msgid "Executing of database structure update %s failed with error: %s"
msgstr ""
#: mod/admin.php:1128
#, php-format
msgid "Executing %s failed with error: %s"
msgstr ""
#: mod/admin.php:1131
#, php-format
msgid "Update %s was successfully applied."
msgstr ""
#: mod/admin.php:1135
#, php-format
msgid "Update %s did not return a status. Unknown if it succeeded."
msgstr ""
#: mod/admin.php:1137
#, php-format
msgid "There was no additional update function %s that needed to be called."
msgstr ""
#: mod/admin.php:1156
msgid "No failed updates."
msgstr ""
#: mod/admin.php:1157
msgid "Check database structure"
msgstr ""
#: mod/admin.php:1162
msgid "Failed Updates"
msgstr ""
#: mod/admin.php:1163
msgid ""
"This does not include updates prior to 1139, which did not return a status."
msgstr ""
#: mod/admin.php:1164
msgid "Mark success (if update was manually applied)"
msgstr ""
#: mod/admin.php:1165
msgid "Attempt to execute this update step automatically"
msgstr ""
#: mod/admin.php:1199
#, php-format
msgid ""
"\n"
"\t\t\tDear %1$s,\n"
"\t\t\t\tthe administrator of %2$s has set up an account for you."
msgstr ""
#: mod/admin.php:1202
#, php-format
msgid ""
"\n"
"\t\t\tThe login details are as follows:\n"
"\n"
"\t\t\tSite Location:\t%1$s\n"
"\t\t\tLogin Name:\t\t%2$s\n"
"\t\t\tPassword:\t\t%3$s\n"
"\n"
"\t\t\tYou may change your password from your account \"Settings\" page after "
"logging\n"
"\t\t\tin.\n"
"\n"
"\t\t\tPlease take a few moments to review the other account settings on that "
"page.\n"
"\n"
"\t\t\tYou may also wish to add some basic information to your default "
"profile\n"
"\t\t\t(on the \"Profiles\" page) so that other people can easily find you.\n"
"\n"
"\t\t\tWe recommend setting your full name, adding a profile photo,\n"
"\t\t\tadding some profile \"keywords\" (very useful in making new friends) - "
"and\n"
"\t\t\tperhaps what country you live in; if you do not wish to be more "
"specific\n"
"\t\t\tthan that.\n"
"\n"
"\t\t\tWe fully respect your right to privacy, and none of these items are "
"necessary.\n"
"\t\t\tIf you are new and do not know anybody here, they may help\n"
"\t\t\tyou to make some new and interesting friends.\n"
"\n"
"\t\t\tThank you and welcome to %4$s."
msgstr ""
#: mod/admin.php:1246
#, php-format
msgid "%s user blocked/unblocked"
msgid_plural "%s users blocked/unblocked"
msgstr[0] ""
msgstr[1] ""
#: mod/admin.php:1253
#, php-format
msgid "%s user deleted"
msgid_plural "%s users deleted"
msgstr[0] ""
msgstr[1] ""
#: mod/admin.php:1300
#, php-format
msgid "User '%s' deleted"
msgstr ""
#: mod/admin.php:1308
#, php-format
msgid "User '%s' unblocked"
msgstr ""
#: mod/admin.php:1308
#, php-format
msgid "User '%s' blocked"
msgstr ""
#: mod/admin.php:1417 mod/admin.php:1443
msgid "Register date"
msgstr ""
#: mod/admin.php:1417 mod/admin.php:1443
msgid "Last login"
msgstr ""
#: mod/admin.php:1417 mod/admin.php:1443
msgid "Last item"
msgstr ""
#: mod/admin.php:1426
msgid "Add User"
msgstr ""
#: mod/admin.php:1427
msgid "select all"
msgstr ""
#: mod/admin.php:1428
msgid "User registrations waiting for confirm"
msgstr ""
#: mod/admin.php:1429
msgid "User waiting for permanent deletion"
msgstr ""
#: mod/admin.php:1430
msgid "Request date"
msgstr ""
#: mod/admin.php:1431
msgid "No registrations."
msgstr ""
#: mod/admin.php:1432
msgid "Note from the user"
msgstr ""
#: mod/admin.php:1433 mod/notifications.php:176 mod/notifications.php:255
msgid "Approve"
msgstr ""
#: mod/admin.php:1434
msgid "Deny"
msgstr ""
#: mod/admin.php:1438
msgid "Site admin"
msgstr ""
#: mod/admin.php:1439
msgid "Account expired"
msgstr ""
#: mod/admin.php:1442
msgid "New User"
msgstr ""
#: mod/admin.php:1443
msgid "Deleted since"
msgstr ""
#: mod/admin.php:1448
msgid ""
"Selected users will be deleted!\\n\\nEverything these users had posted on "
"this site will be permanently deleted!\\n\\nAre you sure?"
msgstr ""
#: mod/admin.php:1449
msgid ""
"The user {0} will be deleted!\\n\\nEverything this user has posted on this "
"site will be permanently deleted!\\n\\nAre you sure?"
msgstr ""
#: mod/admin.php:1459
msgid "Name of the new user."
msgstr ""
#: mod/admin.php:1460
msgid "Nickname"
msgstr ""
#: mod/admin.php:1460
msgid "Nickname of the new user."
msgstr ""
#: mod/admin.php:1461
msgid "Email address of the new user."
msgstr ""
#: mod/admin.php:1504
#, php-format
msgid "Plugin %s disabled."
msgstr ""
#: mod/admin.php:1508
#, php-format
msgid "Plugin %s enabled."
msgstr ""
#: mod/admin.php:1519 mod/admin.php:1767
msgid "Disable"
msgstr ""
#: mod/admin.php:1521 mod/admin.php:1769
msgid "Enable"
msgstr ""
#: mod/admin.php:1544 mod/admin.php:1814
msgid "Toggle"
msgstr ""
#: mod/admin.php:1552 mod/admin.php:1823
msgid "Author: "
msgstr ""
#: mod/admin.php:1553 mod/admin.php:1824
msgid "Maintainer: "
msgstr ""
#: mod/admin.php:1608
msgid "Reload active plugins"
msgstr ""
#: mod/admin.php:1613
#, php-format
msgid ""
"There are currently no plugins available on your node. You can find the "
"official plugin repository at %1$s and might find other interesting plugins "
"in the open plugin registry at %2$s"
msgstr ""
#: mod/admin.php:1727
msgid "No themes found."
msgstr ""
#: mod/admin.php:1805
msgid "Screenshot"
msgstr ""
#: mod/admin.php:1865
msgid "Reload active themes"
msgstr ""
#: mod/admin.php:1870
#, php-format
msgid "No themes found on the system. They should be paced in %1$s"
msgstr ""
#: mod/admin.php:1871
msgid "[Experimental]"
msgstr ""
#: mod/admin.php:1872
msgid "[Unsupported]"
msgstr ""
#: mod/admin.php:1896
msgid "Log settings updated."
msgstr ""
#: mod/admin.php:1928
msgid "PHP log currently enabled."
msgstr ""
#: mod/admin.php:1930
msgid "PHP log currently disabled."
msgstr ""
#: mod/admin.php:1939
msgid "Clear"
msgstr ""
#: mod/admin.php:1944
msgid "Enable Debugging"
msgstr ""
#: mod/admin.php:1945
msgid "Log file"
msgstr ""
#: mod/admin.php:1945
msgid ""
"Must be writable by web server. Relative to your Friendica top-level "
"directory."
msgstr ""
#: mod/admin.php:1946
msgid "Log level"
msgstr ""
#: mod/admin.php:1949
msgid "PHP logging"
msgstr ""
#: mod/admin.php:1950
msgid ""
"To enable logging of PHP errors and warnings you can add the following to "
"the .htconfig.php file of your installation. The filename set in the "
"'error_log' line is relative to the friendica top-level directory and must "
"be writeable by the web server. The option '1' for 'log_errors' and "
"'display_errors' is to enable these options, set to '0' to disable them."
msgstr ""
#: mod/admin.php:2078
#, php-format
msgid "Lock feature %s"
msgstr ""
#: mod/admin.php:2086
msgid "Manage Additional Features"
msgstr ""
#: mod/viewcontacts.php:75
msgid "No contacts."
msgstr ""
#: mod/network.php:190 mod/search.php:25
msgid "Remove term"
msgstr ""
#: mod/network.php:397
#, php-format
msgid ""
"Warning: This group contains %s member from a network that doesn't allow non "
"public messages."
msgid_plural ""
"Warning: This group contains %s members from a network that doesn't allow "
"non public messages."
msgstr[0] ""
msgstr[1] ""
#: mod/network.php:400
msgid "Messages in this group won't be send to these receivers."
msgstr ""
#: mod/network.php:528
msgid "Private messages to this person are at risk of public disclosure."
msgstr ""
#: mod/network.php:533
msgid "Invalid contact."
msgstr ""
#: mod/network.php:827
msgid "Commented Order"
msgstr ""
#: mod/network.php:830
msgid "Sort by Comment Date"
msgstr ""
#: mod/network.php:835
msgid "Posted Order"
msgstr ""
#: mod/network.php:838
msgid "Sort by Post Date"
msgstr ""
#: mod/network.php:849
msgid "Posts that mention or involve you"
msgstr ""
#: mod/network.php:857
msgid "New"
msgstr ""
#: mod/network.php:860
msgid "Activity Stream - by date"
msgstr ""
#: mod/network.php:868
msgid "Shared Links"
msgstr ""
#: mod/network.php:871
msgid "Interesting Links"
msgstr ""
#: mod/network.php:879
msgid "Starred"
msgstr ""
#: mod/network.php:882
msgid "Favourite Posts"
#: mod/repair_ostatus.php:30
msgid "Error"
msgstr ""
#: mod/search.php:100
@ -8581,122 +7799,991 @@ msgstr ""
msgid "Items tagged with: %s"
msgstr ""
#: mod/notifications.php:35
msgid "Invalid request identifier."
#: mod/settings.php:60
msgid "Display"
msgstr ""
#: mod/notifications.php:44 mod/notifications.php:180
#: mod/notifications.php:258
msgid "Discard"
#: mod/settings.php:67 mod/settings.php:890
msgid "Social Networks"
msgstr ""
#: mod/notifications.php:105
msgid "Network Notifications"
#: mod/settings.php:88
msgid "Connected apps"
msgstr ""
#: mod/notifications.php:117
msgid "Personal Notifications"
#: mod/settings.php:95 mod/uexport.php:45
msgid "Export personal data"
msgstr ""
#: mod/notifications.php:123
msgid "Home Notifications"
#: mod/settings.php:102
msgid "Remove account"
msgstr ""
#: mod/notifications.php:152
msgid "Show Ignored Requests"
#: mod/settings.php:157
msgid "Missing some important data!"
msgstr ""
#: mod/notifications.php:152
msgid "Hide Ignored Requests"
#: mod/settings.php:271
msgid "Failed to connect with email account using the settings provided."
msgstr ""
#: mod/notifications.php:164 mod/notifications.php:228
msgid "Notification type: "
#: mod/settings.php:276
msgid "Email settings updated."
msgstr ""
#: mod/notifications.php:167
#: mod/settings.php:291
msgid "Features updated"
msgstr ""
#: mod/settings.php:361
msgid "Relocate message has been send to your contacts"
msgstr ""
#: mod/settings.php:380
msgid "Empty passwords are not allowed. Password unchanged."
msgstr ""
#: mod/settings.php:388
msgid "Wrong password."
msgstr ""
#: mod/settings.php:399
msgid "Password changed."
msgstr ""
#: mod/settings.php:401
msgid "Password update failed. Please try again."
msgstr ""
#: mod/settings.php:481
msgid " Please use a shorter name."
msgstr ""
#: mod/settings.php:483
msgid " Name too short."
msgstr ""
#: mod/settings.php:492
msgid "Wrong Password"
msgstr ""
#: mod/settings.php:497
msgid " Not valid email."
msgstr ""
#: mod/settings.php:503
msgid " Cannot change to that email."
msgstr ""
#: mod/settings.php:559
msgid "Private forum has no privacy permissions. Using default privacy group."
msgstr ""
#: mod/settings.php:563
msgid "Private forum has no privacy permissions and no default privacy group."
msgstr ""
#: mod/settings.php:603
msgid "Settings updated."
msgstr ""
#: mod/settings.php:680 mod/settings.php:706 mod/settings.php:742
msgid "Add application"
msgstr ""
#: mod/settings.php:684 mod/settings.php:710
msgid "Consumer Key"
msgstr ""
#: mod/settings.php:685 mod/settings.php:711
msgid "Consumer Secret"
msgstr ""
#: mod/settings.php:686 mod/settings.php:712
msgid "Redirect"
msgstr ""
#: mod/settings.php:687 mod/settings.php:713
msgid "Icon url"
msgstr ""
#: mod/settings.php:698
msgid "You can't edit this application."
msgstr ""
#: mod/settings.php:741
msgid "Connected Apps"
msgstr ""
#: mod/settings.php:745
msgid "Client key starts with"
msgstr ""
#: mod/settings.php:746
msgid "No name"
msgstr ""
#: mod/settings.php:747
msgid "Remove authorization"
msgstr ""
#: mod/settings.php:759
msgid "No Plugin settings configured"
msgstr ""
#: mod/settings.php:768
msgid "Plugin Settings"
msgstr ""
#: mod/settings.php:790
msgid "Additional Features"
msgstr ""
#: mod/settings.php:800 mod/settings.php:804
msgid "General Social Media Settings"
msgstr ""
#: mod/settings.php:810
msgid "Disable intelligent shortening"
msgstr ""
#: mod/settings.php:812
msgid ""
"Normally the system tries to find the best link to add to shortened posts. "
"If this option is enabled then every shortened post will always point to the "
"original friendica post."
msgstr ""
#: mod/settings.php:818
msgid "Automatically follow any GNU Social (OStatus) followers/mentioners"
msgstr ""
#: mod/settings.php:820
msgid ""
"If you receive a message from an unknown OStatus user, this option decides "
"what to do. If it is checked, a new contact will be created for every "
"unknown user."
msgstr ""
#: mod/settings.php:826
msgid "Default group for OStatus contacts"
msgstr ""
#: mod/settings.php:834
msgid "Your legacy GNU Social account"
msgstr ""
#: mod/settings.php:836
msgid ""
"If you enter your old GNU Social/Statusnet account name here (in the format "
"user@domain.tld), your contacts will be added automatically. The field will "
"be emptied when done."
msgstr ""
#: mod/settings.php:839
msgid "Repair OStatus subscriptions"
msgstr ""
#: mod/settings.php:848 mod/settings.php:849
#, php-format
msgid "suggested by %s"
msgid "Built-in support for %s connectivity is %s"
msgstr ""
#: mod/notifications.php:173 mod/notifications.php:246
msgid "Post a new friend activity"
#: mod/settings.php:848 mod/settings.php:849
msgid "enabled"
msgstr ""
#: mod/notifications.php:173 mod/notifications.php:246
msgid "if applicable"
#: mod/settings.php:848 mod/settings.php:849
msgid "disabled"
msgstr ""
#: mod/notifications.php:195
msgid "Claims to be known to you: "
#: mod/settings.php:849
msgid "GNU Social (OStatus)"
msgstr ""
#: mod/notifications.php:196
msgid "yes"
#: mod/settings.php:883
msgid "Email access is disabled on this site."
msgstr ""
#: mod/notifications.php:196
msgid "no"
#: mod/settings.php:895
msgid "Email/Mailbox Setup"
msgstr ""
#: mod/notifications.php:197 mod/notifications.php:202
msgid "Shall your connection be bidirectional or not?"
#: mod/settings.php:896
msgid ""
"If you wish to communicate with email contacts using this service "
"(optional), please specify how to connect to your mailbox."
msgstr ""
#: mod/notifications.php:198 mod/notifications.php:203
#: mod/settings.php:897
msgid "Last successful email check:"
msgstr ""
#: mod/settings.php:899
msgid "IMAP server name:"
msgstr ""
#: mod/settings.php:900
msgid "IMAP port:"
msgstr ""
#: mod/settings.php:901
msgid "Security:"
msgstr ""
#: mod/settings.php:901 mod/settings.php:906
msgid "None"
msgstr ""
#: mod/settings.php:902
msgid "Email login name:"
msgstr ""
#: mod/settings.php:903
msgid "Email password:"
msgstr ""
#: mod/settings.php:904
msgid "Reply-to address:"
msgstr ""
#: mod/settings.php:905
msgid "Send public posts to all email contacts:"
msgstr ""
#: mod/settings.php:906
msgid "Action after import:"
msgstr ""
#: mod/settings.php:906
msgid "Move to folder"
msgstr ""
#: mod/settings.php:907
msgid "Move to folder:"
msgstr ""
#: mod/settings.php:1003
msgid "Display Settings"
msgstr ""
#: mod/settings.php:1009 mod/settings.php:1032
msgid "Display Theme:"
msgstr ""
#: mod/settings.php:1010
msgid "Mobile Theme:"
msgstr ""
#: mod/settings.php:1011
msgid "Suppress warning of insecure networks"
msgstr ""
#: mod/settings.php:1011
msgid ""
"Should the system suppress the warning that the current group contains "
"members of networks that can't receive non public postings."
msgstr ""
#: mod/settings.php:1012
msgid "Update browser every xx seconds"
msgstr ""
#: mod/settings.php:1012
msgid "Minimum of 10 seconds. Enter -1 to disable it."
msgstr ""
#: mod/settings.php:1013
msgid "Number of items to display per page:"
msgstr ""
#: mod/settings.php:1013 mod/settings.php:1014
msgid "Maximum of 100 items"
msgstr ""
#: mod/settings.php:1014
msgid "Number of items to display per page when viewed from mobile device:"
msgstr ""
#: mod/settings.php:1015
msgid "Don't show emoticons"
msgstr ""
#: mod/settings.php:1016
msgid "Calendar"
msgstr ""
#: mod/settings.php:1017
msgid "Beginning of week:"
msgstr ""
#: mod/settings.php:1018
msgid "Don't show notices"
msgstr ""
#: mod/settings.php:1019
msgid "Infinite scroll"
msgstr ""
#: mod/settings.php:1020
msgid "Automatic updates only at the top of the network page"
msgstr ""
#: mod/settings.php:1021
msgid "Bandwith Saver Mode"
msgstr ""
#: mod/settings.php:1021
msgid ""
"When enabled, embedded content is not displayed on automatic updates, they "
"only show on page reload."
msgstr ""
#: mod/settings.php:1023
msgid "General Theme Settings"
msgstr ""
#: mod/settings.php:1024
msgid "Custom Theme Settings"
msgstr ""
#: mod/settings.php:1025
msgid "Content Settings"
msgstr ""
#: mod/settings.php:1026 view/theme/duepuntozero/config.php:63
#: view/theme/frio/config.php:66 view/theme/quattro/config.php:69
#: view/theme/vier/config.php:114
msgid "Theme settings"
msgstr ""
#: mod/settings.php:1110
msgid "Account Types"
msgstr ""
#: mod/settings.php:1111
msgid "Personal Page Subtypes"
msgstr ""
#: mod/settings.php:1112
msgid "Community Forum Subtypes"
msgstr ""
#: mod/settings.php:1119
msgid "Personal Page"
msgstr ""
#: mod/settings.php:1120
msgid "This account is a regular personal profile"
msgstr ""
#: mod/settings.php:1123
msgid "Organisation Page"
msgstr ""
#: mod/settings.php:1124
msgid "This account is a profile for an organisation"
msgstr ""
#: mod/settings.php:1127
msgid "News Page"
msgstr ""
#: mod/settings.php:1128
msgid "This account is a news account/reflector"
msgstr ""
#: mod/settings.php:1131
msgid "Community Forum"
msgstr ""
#: mod/settings.php:1132
msgid ""
"This account is a community forum where people can discuss with each other"
msgstr ""
#: mod/settings.php:1135
msgid "Normal Account Page"
msgstr ""
#: mod/settings.php:1136
msgid "This account is a normal personal profile"
msgstr ""
#: mod/settings.php:1139
msgid "Soapbox Page"
msgstr ""
#: mod/settings.php:1140
msgid "Automatically approve all connection/friend requests as read-only fans"
msgstr ""
#: mod/settings.php:1143
msgid "Public Forum"
msgstr ""
#: mod/settings.php:1144
msgid "Automatically approve all contact requests"
msgstr ""
#: mod/settings.php:1147
msgid "Automatic Friend Page"
msgstr ""
#: mod/settings.php:1148
msgid "Automatically approve all connection/friend requests as friends"
msgstr ""
#: mod/settings.php:1151
msgid "Private Forum [Experimental]"
msgstr ""
#: mod/settings.php:1152
msgid "Private forum - approved members only"
msgstr ""
#: mod/settings.php:1163
msgid "OpenID:"
msgstr ""
#: mod/settings.php:1163
msgid "(Optional) Allow this OpenID to login to this account."
msgstr ""
#: mod/settings.php:1171
msgid "Publish your default profile in your local site directory?"
msgstr ""
#: mod/settings.php:1177
msgid "Publish your default profile in the global social directory?"
msgstr ""
#: mod/settings.php:1184
msgid "Hide your contact/friend list from viewers of your default profile?"
msgstr ""
#: mod/settings.php:1188
msgid ""
"If enabled, posting public messages to Diaspora and other networks isn't "
"possible."
msgstr ""
#: mod/settings.php:1193
msgid "Allow friends to post to your profile page?"
msgstr ""
#: mod/settings.php:1198
msgid "Allow friends to tag your posts?"
msgstr ""
#: mod/settings.php:1203
msgid "Allow us to suggest you as a potential friend to new members?"
msgstr ""
#: mod/settings.php:1208
msgid "Permit unknown people to send you private mail?"
msgstr ""
#: mod/settings.php:1216
msgid "Profile is <strong>not published</strong>."
msgstr ""
#: mod/settings.php:1224
#, php-format
msgid "Your Identity Address is <strong>'%s'</strong> or '%s'."
msgstr ""
#: mod/settings.php:1231
msgid "Automatically expire posts after this many days:"
msgstr ""
#: mod/settings.php:1231
msgid "If empty, posts will not expire. Expired posts will be deleted"
msgstr ""
#: mod/settings.php:1232
msgid "Advanced expiration settings"
msgstr ""
#: mod/settings.php:1233
msgid "Advanced Expiration"
msgstr ""
#: mod/settings.php:1234
msgid "Expire posts:"
msgstr ""
#: mod/settings.php:1235
msgid "Expire personal notes:"
msgstr ""
#: mod/settings.php:1236
msgid "Expire starred posts:"
msgstr ""
#: mod/settings.php:1237
msgid "Expire photos:"
msgstr ""
#: mod/settings.php:1238
msgid "Only expire posts by others:"
msgstr ""
#: mod/settings.php:1269
msgid "Account Settings"
msgstr ""
#: mod/settings.php:1277
msgid "Password Settings"
msgstr ""
#: mod/settings.php:1279
msgid "Leave password fields blank unless changing"
msgstr ""
#: mod/settings.php:1280
msgid "Current Password:"
msgstr ""
#: mod/settings.php:1280 mod/settings.php:1281
msgid "Your current password to confirm the changes"
msgstr ""
#: mod/settings.php:1281
msgid "Password:"
msgstr ""
#: mod/settings.php:1285
msgid "Basic Settings"
msgstr ""
#: mod/settings.php:1287
msgid "Email Address:"
msgstr ""
#: mod/settings.php:1288
msgid "Your Timezone:"
msgstr ""
#: mod/settings.php:1289
msgid "Your Language:"
msgstr ""
#: mod/settings.php:1289
msgid ""
"Set the language we use to show you friendica interface and to send you "
"emails"
msgstr ""
#: mod/settings.php:1290
msgid "Default Post Location:"
msgstr ""
#: mod/settings.php:1291
msgid "Use Browser Location:"
msgstr ""
#: mod/settings.php:1294
msgid "Security and Privacy Settings"
msgstr ""
#: mod/settings.php:1296
msgid "Maximum Friend Requests/Day:"
msgstr ""
#: mod/settings.php:1296 mod/settings.php:1326
msgid "(to prevent spam abuse)"
msgstr ""
#: mod/settings.php:1297
msgid "Default Post Permissions"
msgstr ""
#: mod/settings.php:1298
msgid "(click to open/close)"
msgstr ""
#: mod/settings.php:1309
msgid "Default Private Post"
msgstr ""
#: mod/settings.php:1310
msgid "Default Public Post"
msgstr ""
#: mod/settings.php:1314
msgid "Default Permissions for New Posts"
msgstr ""
#: mod/settings.php:1326
msgid "Maximum private messages per day from unknown people:"
msgstr ""
#: mod/settings.php:1329
msgid "Notification Settings"
msgstr ""
#: mod/settings.php:1330
msgid "By default post a status message when:"
msgstr ""
#: mod/settings.php:1331
msgid "accepting a friend request"
msgstr ""
#: mod/settings.php:1332
msgid "joining a forum/community"
msgstr ""
#: mod/settings.php:1333
msgid "making an <em>interesting</em> profile change"
msgstr ""
#: mod/settings.php:1334
msgid "Send a notification email when:"
msgstr ""
#: mod/settings.php:1335
msgid "You receive an introduction"
msgstr ""
#: mod/settings.php:1336
msgid "Your introductions are confirmed"
msgstr ""
#: mod/settings.php:1337
msgid "Someone writes on your profile wall"
msgstr ""
#: mod/settings.php:1338
msgid "Someone writes a followup comment"
msgstr ""
#: mod/settings.php:1339
msgid "You receive a private message"
msgstr ""
#: mod/settings.php:1340
msgid "You receive a friend suggestion"
msgstr ""
#: mod/settings.php:1341
msgid "You are tagged in a post"
msgstr ""
#: mod/settings.php:1342
msgid "You are poked/prodded/etc. in a post"
msgstr ""
#: mod/settings.php:1344
msgid "Activate desktop notifications"
msgstr ""
#: mod/settings.php:1344
msgid "Show desktop popup on new notifications"
msgstr ""
#: mod/settings.php:1346
msgid "Text-only notification emails"
msgstr ""
#: mod/settings.php:1348
msgid "Send text only notification emails, without the html part"
msgstr ""
#: mod/settings.php:1350
msgid "Advanced Account/Page Type Settings"
msgstr ""
#: mod/settings.php:1351
msgid "Change the behaviour of this account for special situations"
msgstr ""
#: mod/settings.php:1354
msgid "Relocate"
msgstr ""
#: mod/settings.php:1355
msgid ""
"If you have moved this profile from another server, and some of your "
"contacts don't receive your updates, try pushing this button."
msgstr ""
#: mod/settings.php:1356
msgid "Resend relocate message to contacts"
msgstr ""
#: mod/subthread.php:104
#, php-format
msgid "%1$s is following %2$s's %3$s"
msgstr ""
#: mod/suggest.php:27
msgid "Do you really want to delete this suggestion?"
msgstr ""
#: mod/suggest.php:71
msgid ""
"No suggestions available. If this is a new site, please try again in 24 "
"hours."
msgstr ""
#: mod/suggest.php:84 mod/suggest.php:104
msgid "Ignore/Hide"
msgstr ""
#: mod/tagrm.php:43
msgid "Tag removed"
msgstr ""
#: mod/tagrm.php:82
msgid "Remove Item Tag"
msgstr ""
#: mod/tagrm.php:84
msgid "Select a tag to remove: "
msgstr ""
#: mod/uexport.php:37
msgid "Export account"
msgstr ""
#: mod/uexport.php:37
msgid ""
"Export your account info and contacts. Use this to make a backup of your "
"account and/or to move it to another server."
msgstr ""
#: mod/uexport.php:38
msgid "Export all"
msgstr ""
#: mod/uexport.php:38
msgid ""
"Export your accout info, contacts and all your items as json. Could be a "
"very big file, and could take a lot of time. Use this to make a full backup "
"of your account (photos are not exported)"
msgstr ""
#: mod/uimport.php:68
msgid "Move account"
msgstr ""
#: mod/uimport.php:69
msgid "You can import an account from another Friendica server."
msgstr ""
#: mod/uimport.php:70
msgid ""
"You need to export your account from the old server and upload it here. We "
"will recreate your old account here with all your contacts. We will try also "
"to inform your friends that you moved here."
msgstr ""
#: mod/uimport.php:71
msgid ""
"This feature is experimental. We can't import contacts from the OStatus "
"network (GNU Social/Statusnet) or from Diaspora"
msgstr ""
#: mod/uimport.php:72
msgid "Account file"
msgstr ""
#: mod/uimport.php:72
msgid ""
"To export your account, go to \"Settings->Export your personal data\" and "
"select \"Export account\""
msgstr ""
#: mod/update_community.php:19 mod/update_display.php:23
#: mod/update_network.php:27 mod/update_notes.php:36 mod/update_profile.php:35
msgid "[Embedded content - reload page to view]"
msgstr ""
#: mod/videos.php:124
msgid "Do you really want to delete this video?"
msgstr ""
#: mod/videos.php:129
msgid "Delete Video"
msgstr ""
#: mod/videos.php:208
msgid "No videos selected"
msgstr ""
#: mod/videos.php:400
msgid "Recent Videos"
msgstr ""
#: mod/videos.php:402
msgid "Upload New Videos"
msgstr ""
#: mod/viewcontacts.php:75
msgid "No contacts."
msgstr ""
#: mod/viewsrc.php:7
msgid "Access denied."
msgstr ""
#: mod/wall_attach.php:17 mod/wall_attach.php:25 mod/wall_attach.php:76
#: mod/wall_upload.php:20 mod/wall_upload.php:33 mod/wall_upload.php:86
#: mod/wall_upload.php:122 mod/wall_upload.php:125
msgid "Invalid request."
msgstr ""
#: mod/wall_attach.php:94
msgid "Sorry, maybe your upload is bigger than the PHP configuration allows"
msgstr ""
#: mod/wall_attach.php:94
msgid "Or - did you try to upload an empty file?"
msgstr ""
#: mod/wall_attach.php:105
#, php-format
msgid "File exceeds size limit of %s"
msgstr ""
#: mod/wall_attach.php:158 mod/wall_attach.php:174
msgid "File upload failed."
msgstr ""
#: mod/wallmessage.php:42 mod/wallmessage.php:106
#, php-format
msgid "Number of daily wall messages for %s exceeded. Message failed."
msgstr ""
#: mod/wallmessage.php:53
msgid "Unable to check your home location."
msgstr ""
#: mod/wallmessage.php:80 mod/wallmessage.php:89
msgid "No recipient."
msgstr ""
#: mod/wallmessage.php:127
#, php-format
msgid ""
"Accepting %s as a friend allows %s to subscribe to your posts, and you will "
"also receive updates from them in your news feed."
"If you wish for %s to respond, please check that the privacy settings on "
"your site allow private mail from unknown senders."
msgstr ""
#: mod/notifications.php:199
#, php-format
msgid ""
"Accepting %s as a subscriber allows them to subscribe to your posts, but you "
"will not receive updates from them in your news feed."
msgstr ""
#: mod/notifications.php:204
#, php-format
msgid ""
"Accepting %s as a sharer allows them to subscribe to your posts, but you "
"will not receive updates from them in your news feed."
msgstr ""
#: mod/notifications.php:215
msgid "Friend"
msgstr ""
#: mod/notifications.php:216
msgid "Sharer"
msgstr ""
#: mod/notifications.php:216
msgid "Subscriber"
msgstr ""
#: mod/notifications.php:266
msgid "No introductions."
msgstr ""
#: mod/notifications.php:307
msgid "Show unread"
msgstr ""
#: mod/notifications.php:307
msgid "Show all"
msgstr ""
#: mod/notifications.php:313
#, php-format
msgid "No more %s notifications."
msgstr ""
#: object/Item.php:385
#: object/Item.php:359
msgid "via"
msgstr ""
#: view/theme/duepuntozero/config.php:44
msgid "greenzero"
msgstr ""
#: view/theme/duepuntozero/config.php:45
msgid "purplezero"
msgstr ""
#: view/theme/duepuntozero/config.php:46
msgid "easterbunny"
msgstr ""
#: view/theme/duepuntozero/config.php:47
msgid "darkzero"
msgstr ""
#: view/theme/duepuntozero/config.php:48
msgid "comix"
msgstr ""
#: view/theme/duepuntozero/config.php:49
msgid "slackr"
msgstr ""
#: view/theme/duepuntozero/config.php:64
msgid "Variations"
msgstr ""
#: view/theme/frio/config.php:47
msgid "Default"
msgstr ""
#: view/theme/frio/config.php:59
msgid "Note: "
msgstr ""
#: view/theme/frio/config.php:59
msgid "Check image permissions if all users are allowed to visit the image"
msgstr ""
#: view/theme/frio/config.php:67
msgid "Select scheme"
msgstr ""
#: view/theme/frio/config.php:68
msgid "Navigation bar background color"
msgstr ""
#: view/theme/frio/config.php:69
msgid "Navigation bar icon color "
msgstr ""
#: view/theme/frio/config.php:70
msgid "Link color"
msgstr ""
#: view/theme/frio/config.php:71
msgid "Set the background color"
msgstr ""
#: view/theme/frio/config.php:72
msgid "Content background transparency"
msgstr ""
#: view/theme/frio/config.php:73
msgid "Set the background image"
msgstr ""
#: view/theme/frio/php/Image.php:23
msgid "Repeat the image"
msgstr ""
#: view/theme/frio/php/Image.php:23
msgid "Will repeat your image to fill the background."
msgstr ""
#: view/theme/frio/php/Image.php:25
msgid "Stretch"
msgstr ""
#: view/theme/frio/php/Image.php:25
msgid "Will stretch to width/height of the image."
msgstr ""
#: view/theme/frio/php/Image.php:27
msgid "Resize fill and-clip"
msgstr ""
#: view/theme/frio/php/Image.php:27
msgid "Resize to fill and retain aspect ratio."
msgstr ""
#: view/theme/frio/php/Image.php:29
msgid "Resize best fit"
msgstr ""
#: view/theme/frio/php/Image.php:29
msgid "Resize to best fit and retain aspect ratio."
msgstr ""
#: view/theme/frio/theme.php:226
msgid "Guest"
msgstr ""
#: view/theme/frio/theme.php:232
msgid "Visitor"
msgstr ""
#: view/theme/quattro/config.php:70
msgid "Alignment"
msgstr ""
@ -8709,7 +8796,7 @@ msgstr ""
msgid "Center"
msgstr ""
#: view/theme/quattro/config.php:71 view/theme/clean/config.php:108
#: view/theme/quattro/config.php:71
msgid "Color scheme"
msgstr ""
@ -8760,223 +8847,3 @@ msgstr ""
#: view/theme/vier/theme.php:286
msgid "Quick Start"
msgstr ""
#: view/theme/duepuntozero/config.php:44
msgid "greenzero"
msgstr ""
#: view/theme/duepuntozero/config.php:45
msgid "purplezero"
msgstr ""
#: view/theme/duepuntozero/config.php:46
msgid "easterbunny"
msgstr ""
#: view/theme/duepuntozero/config.php:47
msgid "darkzero"
msgstr ""
#: view/theme/duepuntozero/config.php:48
msgid "comix"
msgstr ""
#: view/theme/duepuntozero/config.php:49
msgid "slackr"
msgstr ""
#: view/theme/duepuntozero/config.php:64
msgid "Variations"
msgstr ""
#: view/theme/clean/config.php:61
msgid "Midnight"
msgstr ""
#: view/theme/clean/config.php:62
msgid "Zenburn"
msgstr ""
#: view/theme/clean/config.php:63
msgid "Bootstrap"
msgstr ""
#: view/theme/clean/config.php:64
msgid "Shades of Pink"
msgstr ""
#: view/theme/clean/config.php:65
msgid "Lime and Orange"
msgstr ""
#: view/theme/clean/config.php:66
msgid "GeoCities Retro"
msgstr ""
#: view/theme/clean/config.php:92
msgid "Background Image"
msgstr ""
#: view/theme/clean/config.php:94
msgid ""
"The URL to a picture (e.g. from your photo album) that should be used as "
"background image."
msgstr ""
#: view/theme/clean/config.php:99
msgid "Background Color"
msgstr ""
#: view/theme/clean/config.php:101
msgid "HEX value for the background color. Don't include the #"
msgstr ""
#: view/theme/clean/config.php:115
msgid "font size"
msgstr ""
#: view/theme/clean/config.php:117
msgid "base font size for your interface"
msgstr ""
#: view/theme/clean/config.php:122
msgid "Display Accesskeys"
msgstr ""
#: view/theme/clean/config.php:124
msgid ""
"Diaplay the access keys assigned to some menu element in the web interface."
msgstr ""
#: view/theme/frio/php/Image.php:23
msgid "Repeat the image"
msgstr ""
#: view/theme/frio/php/Image.php:23
msgid "Will repeat your image to fill the background."
msgstr ""
#: view/theme/frio/php/Image.php:25
msgid "Stretch"
msgstr ""
#: view/theme/frio/php/Image.php:25
msgid "Will stretch to width/height of the image."
msgstr ""
#: view/theme/frio/php/Image.php:27
msgid "Resize fill and-clip"
msgstr ""
#: view/theme/frio/php/Image.php:27
msgid "Resize to fill and retain aspect ratio."
msgstr ""
#: view/theme/frio/php/Image.php:29
msgid "Resize best fit"
msgstr ""
#: view/theme/frio/php/Image.php:29
msgid "Resize to best fit and retain aspect ratio."
msgstr ""
#: view/theme/frio/config.php:47
msgid "Default"
msgstr ""
#: view/theme/frio/config.php:59
msgid "Note: "
msgstr ""
#: view/theme/frio/config.php:59
msgid "Check image permissions if all users are allowed to visit the image"
msgstr ""
#: view/theme/frio/config.php:67
msgid "Select scheme"
msgstr ""
#: view/theme/frio/config.php:68
msgid "Navigation bar background color"
msgstr ""
#: view/theme/frio/config.php:69
msgid "Navigation bar icon color "
msgstr ""
#: view/theme/frio/config.php:70
msgid "Link color"
msgstr ""
#: view/theme/frio/config.php:71
msgid "Set the background color"
msgstr ""
#: view/theme/frio/config.php:72
msgid "Content background transparency"
msgstr ""
#: view/theme/frio/config.php:73
msgid "Set the background image"
msgstr ""
#: view/theme/frio/theme.php:226
msgid "Guest"
msgstr ""
#: view/theme/frio/theme.php:232
msgid "Visitor"
msgstr ""
#: index.php:457
msgid "toggle mobile"
msgstr ""
#: boot.php:970
msgid "Delete this item?"
msgstr ""
#: boot.php:972
msgid "show fewer"
msgstr ""
#: boot.php:1696
#, php-format
msgid "Update %s failed. See error logs."
msgstr ""
#: boot.php:1808
msgid "Create a New Account"
msgstr ""
#: boot.php:1837
msgid "Password: "
msgstr ""
#: boot.php:1838
msgid "Remember me"
msgstr ""
#: boot.php:1841
msgid "Or login using OpenID: "
msgstr ""
#: boot.php:1847
msgid "Forgot your password?"
msgstr ""
#: boot.php:1850
msgid "Website Terms of Service"
msgstr ""
#: boot.php:1851
msgid "terms of service"
msgstr ""
#: boot.php:1853
msgid "Website Privacy Policy"
msgstr ""
#: boot.php:1854
msgid "privacy policy"
msgstr ""

View file

@ -1,6 +1,6 @@
<script>
$(function(){
$("#cnftheme").click(function(){
$.colorbox({
width: 800,
@ -22,16 +22,16 @@
data[$(this).attr('name')] = $(this).children(":selected").val();
});
console.log(":)", url, data);
$.post(url, data, function(data) {
if(timer) clearTimeout(timer);
NavUpdate();
$.colorbox.close();
})
return false;
});
}
});
return false;
@ -40,7 +40,7 @@
</script>
<div id='adminpage'>
<h1>{{$title}} - {{$page}}</h1>
<form action="{{$baseurl}}/admin/site" method="post">
<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
@ -59,7 +59,7 @@
{{include file="field_checkbox.tpl" field=$hide_help}}
{{include file="field_select.tpl" field=$singleuser}}
<div class="submit"><input type="submit" name="page_site" value="{{$submit|escape:'html'}}" /></div>
<h3>{{$registration}}</h3>
{{include file="field_input.tpl" field=$register_text}}
{{include file="field_select.tpl" field=$register_policy}}
@ -74,7 +74,7 @@
{{include file="field_input.tpl" field=$maximagelength}}
{{include file="field_input.tpl" field=$jpegimagequality}}
<div class="submit"><input type="submit" name="page_site" value="{{$submit|escape:'html'}}" /></div>
<h3>{{$corporate}}</h3>
{{include file="field_input.tpl" field=$allowed_sites}}
{{include file="field_input.tpl" field=$allowed_email}}
@ -107,33 +107,26 @@
{{include file="field_checkbox.tpl" field=$thread_allow}}
{{include file="field_checkbox.tpl" field=$newuser_private}}
{{include file="field_checkbox.tpl" field=$enotify_no_content}}
{{include file="field_checkbox.tpl" field=$private_addons}}
{{include file="field_checkbox.tpl" field=$private_addons}}
{{include file="field_checkbox.tpl" field=$disable_embedded}}
{{include file="field_checkbox.tpl" field=$allow_users_remote_self}}
<div class="submit"><input type="submit" name="page_site" value="{{$submit|escape:'html'}}" /></div>
<h3>{{$advanced}}</h3>
{{include file="field_select.tpl" field=$rino}}
{{include file="field_checkbox.tpl" field=$no_utf}}
{{include file="field_checkbox.tpl" field=$verifyssl}}
{{include file="field_input.tpl" field=$proxy}}
{{include file="field_input.tpl" field=$proxyuser}}
{{include file="field_input.tpl" field=$timeout}}
{{if NOT $worker.2}}
{{include file="field_input.tpl" field=$delivery_interval}}
{{include file="field_input.tpl" field=$poll_interval}}
{{/if}}
{{include file="field_input.tpl" field=$maxloadavg}}
{{include file="field_input.tpl" field=$maxloadavg_frontend}}
{{include file="field_input.tpl" field=$optimize_max_tablesize}}
{{include file="field_input.tpl" field=$optimize_fragmentation}}
{{include file="field_input.tpl" field=$abandon_days}}
{{include file="field_input.tpl" field=$lockpath}}
{{include file="field_input.tpl" field=$temppath}}
{{include file="field_input.tpl" field=$basepath}}
{{include file="field_checkbox.tpl" field=$suppress_tags}}
{{include file="field_checkbox.tpl" field=$nodeinfo}}
{{include file="field_input.tpl" field=$embedly}}
<div class="submit"><input type="submit" name="page_site" value="{{$submit|escape:'html'}}" /></div>
<h3>{{$portable_contacts}}</h3>
@ -154,17 +147,14 @@
<div class="submit"><input type="submit" name="page_site" value="{{$submit|escape:'html'}}" /></div>
<h3>{{$worker_title}}</h3>
{{include file="field_checkbox.tpl" field=$worker}}
{{if $worker.2}}
{{include file="field_input.tpl" field=$worker_queues}}
{{include file="field_checkbox.tpl" field=$worker_dont_fork}}
{{include file="field_checkbox.tpl" field=$worker_fastlane}}
{{include file="field_checkbox.tpl" field=$worker_frontend}}
{{/if}}
{{include file="field_input.tpl" field=$worker_queues}}
{{include file="field_checkbox.tpl" field=$worker_dont_fork}}
{{include file="field_checkbox.tpl" field=$worker_fastlane}}
{{include file="field_checkbox.tpl" field=$worker_frontend}}
<div class="submit"><input type="submit" name="page_site" value="{{$submit|escape:'html'}}" /></div>
</form>
{{* separate form for relocate... *}}
<form action="{{$baseurl}}/admin/site" method="post">
<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
@ -173,5 +163,5 @@
<input type="hidden" name="page_site" value="{{$submit|escape:'html'}}">
<div class="submit"><input type="submit" name="relocate" value="{{$submit|escape:'html'}}" /></div>
</form>
</div>

View file

@ -11,7 +11,7 @@
<dl>
<dt>{{$queues.label}}</dt>
<dd>{{$queues.deliverq}} - <a href="{{$baseurl}}/admin/queue">{{$queues.queue}}</a>{{if $workeractive}} - {{$queues.workerq}}{{/if}}</dd>
<dd>{{$queues.deliverq}} - <a href="{{$baseurl}}/admin/queue">{{$queues.queue}}</a> - {{$queues.workerq}}</dd>
</dl>
<dl>
<dt>{{$pending.0}}</dt>

View file

@ -6,6 +6,7 @@
{{$event.html}}
{{if $event.item.plink}}<a href="{{$event.plink.0}}" title="{{$event.plink.1}}" target="_blank" class="plink-event-link icon s22 remote-link"></a>{{/if}}
{{if $event.edit}}<a href="{{$event.edit.0}}" title="{{$event.edit.1}}" class="edit-event-link icon s22 pencil"></a>{{/if}}
{{if $event.drop}}<a href="{{$event.drop.0}}" onclick="return confirmDelete();" title="{{$event.drop.1}}" class="drop-event-link icon s22 delete"></a>{{/if}}
</div>
<div class="clear"></div>
{{/foreach}}

View file

@ -1,2 +1,3 @@
<div id="maintenance-message">{{$sysdown}}</div>
<h1 id="maintenance-message">{{$sysdown}}</h1>
<div id="maintenance-reason">{{$reason}}</div>

View file

@ -2193,6 +2193,9 @@ ul li:hover .contact-wrapper a.contact-action-link:hover {
#event-edit-form-wrapper #event-edit-time {
padding: 10px 0;
}
.event-buttons .plink-event-link {
margin-left: 20px;
}
/* Profiles Page */
.profile-listing-table {
display: table;

View file

@ -181,7 +181,7 @@ function dropItem(url, elementId) {
$el.fadeTo('fast', 0.33, function () {
$.get(url).then(function() {
$el.remove();
}).error(function() {
}).fail(function() {
// @todo Show related error message
$el.show();
}).always(function() {

View file

@ -17,8 +17,9 @@
</div>
<div class="event-buttons pull-right">
{{if $event.item.plink}}<a href="{{$event.plink.0}}" title="{{$event.plink.1}}" class="btn "><i class="fa fa-external-link" aria-hidden="true"></i></a>{{/if}}
{{if $event.edit}}<a onclick="eventEdit('{{$event.edit.0}}')" title="{{$event.edit.1}}" class="btn"><i class="fa fa-pencil" aria-hidden="true"></i></a>{{/if}}
{{if $event.edit}}<a onclick="eventEdit('{{$event.edit.0}}')" title="{{$event.edit.1}}" class="edit-event-link btn"><i class="fa fa-pencil" aria-hidden="true"></i></a>{{/if}}
{{if $event.drop}}<a href="{{$event.drop.0}}" onclick="return confirmDelete();" title="{{$event.drop.1}}" class="drop-event-link btn"><i class="fa fa-trash-o" aria-hidden="true"></i></a>{{/if}}
{{if $event.item.plink}}<a href="{{$event.plink.0}}" title="{{$event.plink.1}}" class="plink-event-link btn "><i class="fa fa-external-link" aria-hidden="true"></i></a>{{/if}}
</div>
<div class="clear"></div>
</div>

View file

@ -52,7 +52,6 @@
<div class="submit"><input type="submit" name="page_site" value="{{$submit}}" /></div>
<h3>{{$advanced}}</h3>
{{include file="field_checkbox.tpl" field=$no_utf}}
{{include file="field_checkbox.tpl" field=$verifyssl}}
{{include file="field_input.tpl" field=$proxy}}
{{include file="field_input.tpl" field=$proxyuser}}

View file

@ -52,7 +52,6 @@
<div class="submit"><input type="submit" name="page_site" value="{{$submit}}" /></div>
<h3>{{$advanced}}</h3>
{{include file="field_checkbox.tpl" field=$no_utf}}
{{include file="field_checkbox.tpl" field=$verifyssl}}
{{include file="field_input.tpl" field=$proxy}}
{{include file="field_input.tpl" field=$proxyuser}}