This merge brings back dbm::is_result() where I could find it.

Merge branch 'develop' of github.com:friendica/friendica into rhaeder-develop

Signed-off-by: Roland Haeder <roland@mxchange.org>
This commit is contained in:
Roland Häder 2016-09-18 23:21:18 +02:00
commit c825cc8d0d
No known key found for this signature in database
GPG key ID: B72F8185C6C7BD78
691 changed files with 128914 additions and 43052 deletions

View file

@ -4,7 +4,14 @@ AddType audio/ogg .oga
#AddHandler php53-cgi .php
<FilesMatch "\.(out|log)$">
<IfModule authz_host_module>
#Apache 2.4
Require all denied
</IfModule>
<IfModule !authz_host_module>
#Apache 2.2
Deny from all
</IfModule>
</FilesMatch>
<IfModule mod_rewrite.c>

View file

@ -1,3 +1,63 @@
Version 3.5
Friendica Core:
NEW Optional local directory with possible federated contacts [heluecht]
NEW Autocompletion for @-mentions and BBCode tags [rabuzarus]
NEW Added a composer derived autoloader which allows composer autoloaders in addons/libraries [fabrixxm]
NEW theme: frio [rabuzarus, heluecht, fabrixxm]
Enhance .htaccess file (nerdoc, dissolve)
Updates to the translations (DE, ES, IS, IT, RU) [translation teams]
Updates to the documentation [tobiasd, heluecht, mexcon, silke, rabuzarus, fabrixxm, Olivier Mehani, gerhard6380, ben utzer]
Extended the BBCode by [abstract] tag used for bridged postings to networks with limited character length [heluecht]
Code cleanup [heluecht, QuixOr]
Improvements to the API and Friendica specific extensions [heluecht, fabrixxm, gerhard6380]
Improvements to the RSS/Atom feed import [mexcon]
Improvements to the communication with federated networks (Diaspora, Hubzilla, OStatus) [heluecht]
Improvements on the themes (quattro, vier, frost) [rabuzarus, fabrixxm, stieben, heluecht, Quix0r, tobiasd]
Improvements to the ACL dialog [fabrixxm, rabuzarus]
Improvements to the database structure and optimization of queries [heluecht]
Improvements to the UI (contacts, hotkeys, remember me, ARIA, code hightlighting) [rabuzarus, heluecht, tobiasd]
Improvements to the background process (poller, worker) [heluecht]
Improvements to the admin panel [tobiasd, heluecht, fabrixxm]
Improvements to the performance [heluecht]
Improvements to the installation wizzard (language selection, RINO version, check required PHP modules, default theme is now vier) [tobiasd]
Improvements to the relocation of nodes and accounts [heluecht]
Improvements to the DDoS detection [heluecht]
Improvements to the calendar/events module [heluecht, rabuzarus]
Improvements to OpenID login [strk]
Improvements to the ShaShape font [andi]
Reworked the implementation of the DFRN, Diaspora protocols [heluecht]
Reworked the notifications code [fabrixxm, rabuzarus, heluecht]
Reworked the p/config code [fabrixxm, rabuzarus]
Reworked XML generation [heluecht]
Removed now unused simplepie from library [heluecht]
Friendica Addons
Updated to the translations (DE, ES, IS, NL, PT BR), [translation teams]
Piwik [tobiasd]
Twitter Connector [heluecht]
Pumpio Connector [heluecht]
Rendertime [heluecht]
wppost [heluecht]
showmore [rabuzarus]
fromgplus [heluecht]
app.net Connector [heluecht]
GNU Social Connector [heluecht]
LDAP [Olivier Mehani]
smileybutton [rabuzarus]
retriver [mexon]
mailstream [mexon]
forumdirectory [tobiasd]
NEW notifyall (port from Hubzilla) [rabuzarus, tobiasd]
DEPRECATED cal (now in core), FB Connector, FB Post Connector, FB Sync
Closed Issues
683, 786, 796, 922, 1261, 1576, 1701, 1769, 1970, 1145, 1494,
1728, 1877, 2063, 2059, 2078, 2079, 2133, 2165, 2194, 2229, 2230,
2241, 2254, 2242, 2270, 2277, 2339, 2320, 2345, 2352, 2358, 2367,
2373, 2376, 2378, 2385, 2395, 2402, 2406, 2433, 2472, 2485, 2492,
2506, 2512, 2516, 2539, 2540, 2893, 2597, 2611, 2617, 2629, 2645,
2687, 2716, 2757, 2764
Version 3.4.3
What's new for the users:
Updates to the documentation (silke, tobiasd, annando, rebeka-catalina)

View file

@ -32,8 +32,7 @@ link if your cert is self-signed).
- Apache with mod-rewrite enabled and "Options All" so you can use a
local .htaccess file
- PHP 5.2+. The later the better. PHP 5.3 is required for communications
with the Diaspora network and improved security.
- PHP 5.4+.
- PHP *command line* access with register_argc_argv set to true in the
php.ini file [or see 'poormancron' in section 8]
@ -42,7 +41,7 @@ php.ini file [or see 'poormancron' in section 8]
- some form of email server or email gateway such that PHP mail() works
- Mysql 5.x
- Mysql 5.5.3+ or an equivalant alternative for MySQL (MariaDB, Percona Server etc.)
- ability to schedule jobs with cron (Linux/Mac) or Scheduled Tasks
(Windows) [Note: other options are presented in Section 8 of this document]
@ -136,7 +135,24 @@ $a->config['system']['addon'] = 'js_upload,poormancron';
and save your changes.
9. (Optional) Reverse-proxying and HTTPS
Friendica looks for some well-known HTTP headers indicating a reverse-proxy
terminating an HTTPS connection. While the standard from RFC 7239 specifies
the use of the `Forwaded` header.
Forwarded: for=192.0.2.1; proto=https; by=192.0.2.2
Friendica also supports a number on non-standard headers in common use.
X-Forwarded-Proto: https
Front-End-Https: on
X-Forwarded-Ssl: on
It is however preferable to use the standard approach if configuring a new server.
#####################################################################

323
boot.php
View file

@ -36,9 +36,9 @@ require_once('include/dbstructure.php');
define ( 'FRIENDICA_PLATFORM', 'Friendica');
define ( 'FRIENDICA_CODENAME', 'Asparagus');
define ( 'FRIENDICA_VERSION', '3.5-dev' );
define ( 'FRIENDICA_VERSION', '3.5.1-dev' );
define ( 'DFRN_PROTOCOL_VERSION', '2.23' );
define ( 'DB_UPDATE_VERSION', 1195 );
define ( 'DB_UPDATE_VERSION', 1202 );
/**
* @brief Constant with a HTML line break.
@ -386,6 +386,24 @@ define ( 'GRAVITY_LIKE', 3);
define ( 'GRAVITY_COMMENT', 6);
/* @}*/
/**
* @name Priority
*
* Process priority for the worker
* @{
*/
define('PRIORITY_UNDEFINED', 0);
define('PRIORITY_CRITICAL', 10);
define('PRIORITY_HIGH', 20);
define('PRIORITY_MEDIUM', 30);
define('PRIORITY_LOW', 40);
define('PRIORITY_NEGLIGIBLE',50);
/* @}*/
// Normally this constant is defined - but not if "pcntl" isn't installed
if (!defined("SIGTERM"))
define("SIGTERM", 15);
/**
*
@ -471,6 +489,7 @@ class App {
public $performance = array();
public $callstack = array();
public $theme_info = array();
public $backend = true;
public $nav_sel;
@ -512,6 +531,8 @@ class App {
*/
public $template_engine_instance = array();
public $process_id;
private $ldelim = array(
'internal' => '',
'smarty3' => '{{'
@ -553,6 +574,7 @@ class App {
$this->performance["start"] = microtime(true);
$this->performance["database"] = 0;
$this->performance["database_write"] = 0;
$this->performance["network"] = 0;
$this->performance["file"] = 0;
$this->performance["rendering"] = 0;
@ -572,6 +594,8 @@ class App {
$this->query_string = '';
$this->process_id = uniqid("log", true);
startup();
set_include_path(
@ -583,10 +607,15 @@ class App {
$this->scheme = 'http';
if(x($_SERVER,'HTTPS') && $_SERVER['HTTPS'])
$this->scheme = 'https';
elseif(x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443))
if((x($_SERVER,'HTTPS') && $_SERVER['HTTPS']) ||
(x($_SERVER['HTTP_FORWARDED']) && preg_match("/proto=https/", $_SERVER['HTTP_FORWARDED'])) ||
(x($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') ||
(x($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') ||
(x($_SERVER['FRONT_END_HTTPS']) && $_SERVER['FRONT_END_HTTPS'] == 'on') ||
(x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443)) // XXX: reasonable assumption, but isn't this hardcoding too much?
) {
$this->scheme = 'https';
}
if(x($_SERVER,'SERVER_NAME')) {
$this->hostname = $_SERVER['SERVER_NAME'];
@ -862,6 +891,9 @@ class App {
if ($touch_icon == "")
$touch_icon = "images/friendica-128.png";
// get data wich is needed for infinite scroll on the network page
$invinite_scroll = infinite_scroll_data($this->module);
$tpl = get_markup_template('head.tpl');
$this->page['htmlhead'] = replace_macros($tpl,array(
'$baseurl' => $this->get_baseurl(), // FIXME for z_path!!!!
@ -874,7 +906,8 @@ class App {
'$update_interval' => $interval,
'$shortcut_icon' => $shortcut_icon,
'$touch_icon' => $touch_icon,
'$stylesheet' => $stylesheet
'$stylesheet' => $stylesheet,
'$infinite_scroll' => $invinite_scroll,
)) . $this->page['htmlhead'];
}
@ -927,7 +960,7 @@ class App {
} else {
$r = q("SELECT `contact`.`avatar-date` AS picdate FROM `contact` WHERE `contact`.`thumb` like '%%/%s'",
$common_filename);
if(! dba::is_result($r)){
if(! dbm::is_result($r)){
$this->cached_profile_image[$avatar_image] = $avatar_image;
} else {
$this->cached_profile_picdate[$common_filename] = "?rev=".urlencode($r[0]['picdate']);
@ -1066,6 +1099,42 @@ class App {
}
/**
* @brief Log active processes into the "process" table
*/
function start_process() {
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
$command = basename($trace[0]["file"]);
$this->remove_inactive_processes();
$r = q("SELECT `pid` FROM `process` WHERE `pid` = %d", intval(getmypid()));
if(!dbm::is_result($r))
q("INSERT INTO `process` (`pid`,`command`,`created`) VALUES (%d, '%s', '%s')",
intval(getmypid()),
dbesc($command),
dbesc(datetime_convert()));
}
/**
* @brief Remove inactive processes
*/
function remove_inactive_processes() {
$r = q("SELECT `pid` FROM `process`");
if(dbm::is_result($r))
foreach ($r AS $process)
if (!posix_kill($process["pid"], 0))
q("DELETE FROM `process` WHERE `pid` = %d", intval($process["pid"]));
}
/**
* @brief Remove the active process from the "process" table
*/
function end_process() {
q("DELETE FROM `process` WHERE `pid` = %d", intval(getmypid()));
}
/**
* @brief Returns a string with a callstack. Can be used for logging.
*
@ -1098,6 +1167,77 @@ class App {
return($this->is_friendica_app);
}
/**
* @brief Checks if the site is called via a backend process
*
* This isn't a perfect solution. But we need this check very early.
* So we cannot wait until the modules are loaded.
*
* @return bool Is it a known backend?
*/
function is_backend() {
$backend = array();
$backend[] = "_well_known";
$backend[] = "api";
$backend[] = "dfrn_notify";
$backend[] = "fetch";
$backend[] = "hcard";
$backend[] = "hostxrd";
$backend[] = "nodeinfo";
$backend[] = "noscrape";
$backend[] = "p";
$backend[] = "poco";
$backend[] = "post";
$backend[] = "proxy";
$backend[] = "pubsub";
$backend[] = "pubsubhubbub";
$backend[] = "receive";
$backend[] = "rsd_xml";
$backend[] = "salmon";
$backend[] = "statistics_json";
$backend[] = "xrd";
if (in_array($this->module, $backend))
return(true);
else
return($this->backend);
}
/**
* @brief Checks if the maximum number of database processes is reached
*
* @return bool Is the limit reached?
*/
function max_processes_reached() {
// Is the function called statically?
if (!is_object($this))
return(self::$a->max_processes_reached());
if ($this->is_backend()) {
$process = "backend";
$max_processes = get_config('system', 'max_processes_backend');
if (intval($max_processes) == 0)
$max_processes = 5;
} else {
$process = "frontend";
$max_processes = get_config('system', 'max_processes_frontend');
if (intval($max_processes) == 0)
$max_processes = 20;
}
$processlist = dbm::processlist();
if ($processlist["list"] != "") {
logger("Processcheck: Processes: ".$processlist["amount"]." - Processlist: ".$processlist["list"], LOGGER_DEBUG);
if ($processlist["amount"] > $max_processes) {
logger("Processcheck: Maximum number of processes for ".$process." tasks (".$max_processes.") reached.", LOGGER_DEBUG);
return true;
}
}
return false;
}
/**
* @brief Checks if the maximum load is reached
*
@ -1105,14 +1245,26 @@ class App {
*/
function maxload_reached() {
// Is the function called statically?
if (!is_object($this))
return(self::$a->maxload_reached());
if ($this->is_backend()) {
$process = "backend";
$maxsysload = intval(get_config('system', 'maxloadavg'));
if ($maxsysload < 1)
$maxsysload = 50;
} else {
$process = "frontend";
$maxsysload = intval(get_config('system','maxloadavg_frontend'));
if ($maxsysload < 1)
$maxsysload = 50;
}
$load = current_load();
if ($load) {
if (intval($load) > $maxsysload) {
logger('system: load '.$load.' too high.');
logger('system: load '.$load.' for '.$process.' tasks ('.$maxsysload.') too high.');
return true;
}
}
@ -1140,13 +1292,46 @@ class App {
logger("killed stale process");
// Calling a new instance
if ($task != "")
proc_run('php', $task);
proc_run(PRIORITY_MEDIUM, $task);
}
return true;
}
}
return false;
}
function proc_run($args) {
// Add the php path if it is a php call
if (count($args) && ($args[0] === 'php' OR is_int($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")) {
if ((time() - get_config("system", "proc_run_started")) < 10)
return;
// Set the timestamp of the last proc_run
set_config("system", "proc_run_started", time());
}
$args[0] = ((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();
for($x = 0; $x < count($args); $x ++)
$args[$x] = escapeshellarg($args[$x]);
$cmdline = implode($args," ");
if(get_config('system','proc_windows'))
proc_close(proc_open('cmd /c start /b ' . $cmdline,array(),$foo,dirname(__FILE__)));
else
proc_close(proc_open($cmdline." &",array(),$foo,dirname(__FILE__)));
}
}
/**
@ -1262,7 +1447,7 @@ function check_db() {
$build = DB_UPDATE_VERSION;
}
if($build != DB_UPDATE_VERSION)
proc_run('php', 'include/dbupdate.php');
proc_run(PRIORITY_CRITICAL, 'include/dbupdate.php');
}
@ -1412,7 +1597,7 @@ function run_update_function($x) {
function check_plugins(&$a) {
$r = q("SELECT * FROM `addon` WHERE `installed` = 1");
if(dba::is_result($r))
if(dbm::is_result($r))
$installed = $r;
else
$installed = array();
@ -1519,7 +1704,7 @@ function login($register = false, $hiddens=false) {
'$logout' => t('Logout'),
'$login' => t('Login'),
'$lname' => array('username', t('Nickname or Email address: ') , '', ''),
'$lname' => array('username', t('Nickname or Email: ') , '', ''),
'$lpassword' => array('password', t('Password: '), '', ''),
'$lremember' => array('remember', t('Remember me'), 0, ''),
@ -1550,7 +1735,10 @@ function login($register = false, $hiddens=false) {
* @brief Used to end the current process, after saving session state.
*/
function killme() {
if (!get_app()->is_backend())
session_write_close();
exit;
}
@ -1635,10 +1823,11 @@ 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 $cmd program to run
* @param (string|integer) $cmd program to run or priority
*
* 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);
*
* @note $cmd and string args are surrounded with ""
*
@ -1662,8 +1851,7 @@ function proc_run($cmd){
foreach($arg as $n) {
$newargs[] = $n;
}
}
else
} else
$newargs[] = $arg;
}
@ -1672,12 +1860,20 @@ function proc_run($cmd){
$arr = array('args' => $args, 'run_cmd' => true);
call_hooks("proc_run", $arr);
if(! $arr['run_cmd'])
if (!$arr['run_cmd'] OR !count($args))
return;
if(count($args) && $args[0] === 'php') {
if (!get_config("system", "worker") OR
(($args[0] != 'php') AND !is_int($args[0]))) {
$a->proc_run($args);
return;
}
if (is_int($args[0]))
$priority = $args[0];
else
$priority = PRIORITY_MEDIUM;
if (get_config("system", "worker")) {
$argv = $args;
array_shift($argv);
@ -1690,7 +1886,7 @@ function proc_run($cmd){
VALUES ('%s', '%s', %d)",
dbesc($parameters),
dbesc(datetime_convert()),
intval(0));
intval($priority));
// Should we quit and wait for the poller to be called as a cronjob?
if (get_config("system", "worker_dont_fork"))
@ -1711,23 +1907,8 @@ function proc_run($cmd){
// Now call the poller to execute the jobs that we just added to the queue
$args = array("php", "include/poller.php", "no_cron");
}
$args[0] = ((x($a->config,'php_path')) && (strlen($a->config['php_path'])) ? $a->config['php_path'] : 'php');
}
// add baseurl to args. cli scripts can't construct it
$args[] = $a->get_baseurl();
for($x = 0; $x < count($args); $x ++)
$args[$x] = escapeshellarg($args[$x]);
$cmdline = implode($args," ");
if(get_config('system','proc_windows'))
proc_close(proc_open('cmd /c start /b ' . $cmdline,array(),$foo,dirname(__FILE__)));
else
proc_close(proc_open($cmdline." &",array(),$foo,dirname(__FILE__)));
$a->proc_run($args);
}
function current_theme(){
@ -1743,7 +1924,7 @@ function current_theme(){
$r = q("select theme from user where uid = %d limit 1",
intval($a->profile_uid)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$page_theme = $r[0]['theme'];
}
@ -1856,7 +2037,7 @@ function feed_birthday($uid,$tz) {
intval($uid)
);
if(dba::is_result($p)) {
if(dbm::is_result($p)) {
$tmp_dob = substr($p[0]['dob'],5);
if(intval($tmp_dob)) {
$y = datetime_convert($tz,$tz,'now','Y');
@ -1888,32 +2069,6 @@ function is_site_admin() {
return false;
}
function load_contact_links($uid) {
$a = get_app();
$ret = array();
if(! $uid || x($a->contacts,'empty'))
return;
$r = q("SELECT `id`,`network`,`url`,`thumb`, `rel` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `thumb` != ''",
intval($uid)
);
if(dba::is_result($r)) {
foreach($r as $rr){
$url = normalise_link($rr['url']);
$ret[$url] = $rr;
}
} else
$ret['empty'] = true;
$a->contacts = $ret;
return;
}
/**
* @brief Returns querystring as string from a mapped array.
*
@ -2178,7 +2333,7 @@ function current_load() {
if (!is_array($load_arr))
return false;
return max($load_arr);
return max($load_arr[0], $load_arr[1]);
}
/**
@ -2202,3 +2357,43 @@ function argv($x) {
return '';
}
/**
* @brief Get the data which is needed for infinite scroll
*
* For invinite scroll we need the page number of the actual page
* and the the URI where the content of the next page comes from.
* This data is needed for the js part in main.js.
* Note: infinite scroll does only work for the network page (module)
*
* @param string $module The name of the module (e.g. "network")
* @return array Of infinite scroll data
* 'pageno' => $pageno The number of the actual page
* 'reload_uri' => $reload_uri The URI of the content we have to load
*/
function infinite_scroll_data($module) {
if (get_pconfig(local_user(),'system','infinite_scroll')
AND ($module == "network") AND ($_GET["mode"] != "minimal")) {
// get the page number
if (is_string($_GET["page"]))
$pageno = $_GET["page"];
else
$pageno = 1;
$reload_uri = "";
// try to get the uri from which we load the content
foreach ($_GET AS $param => $value)
if (($param != "page") AND ($param != "q"))
$reload_uri .= "&".$param."=".urlencode($value);
if (($a->page_offset != "") AND !strstr($reload_uri, "&offset="))
$reload_uri .= "&offset=".urlencode($a->page_offset);
$arr = array("pageno" => $pageno, "reload_uri" => $reload_uri);
return $arr;
}
}

View file

@ -1,6 +1,6 @@
-- ------------------------------------------
-- Friendica 3.5-dev (Asparagus)
-- DB_UPDATE_VERSION 1195
-- DB_UPDATE_VERSION 1200
-- ------------------------------------------
@ -16,7 +16,7 @@ CREATE TABLE IF NOT EXISTS `addon` (
`timestamp` bigint(20) NOT NULL DEFAULT 0,
`plugin_admin` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE attach
@ -31,12 +31,12 @@ CREATE TABLE IF NOT EXISTS `attach` (
`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',
`allow_cid` mediumtext NOT NULL,
`allow_gid` mediumtext NOT NULL,
`deny_cid` mediumtext NOT NULL,
`deny_gid` mediumtext NOT NULL,
`allow_cid` mediumtext,
`allow_gid` mediumtext,
`deny_cid` mediumtext,
`deny_gid` mediumtext,
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE auth_codes
@ -48,19 +48,19 @@ CREATE TABLE IF NOT EXISTS `auth_codes` (
`expires` int(11) NOT NULL DEFAULT 0,
`scope` varchar(250) NOT NULL DEFAULT '',
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE cache
--
CREATE TABLE IF NOT EXISTS `cache` (
`k` varchar(255) NOT NULL,
`v` text NOT NULL,
`v` text,
`expire_mode` int(11) NOT NULL DEFAULT 0,
`updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY(`k`),
INDEX `updated` (`updated`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE challenge
@ -73,7 +73,7 @@ CREATE TABLE IF NOT EXISTS `challenge` (
`type` varchar(255) NOT NULL DEFAULT '',
`last_update` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE clients
@ -86,7 +86,7 @@ CREATE TABLE IF NOT EXISTS `clients` (
`icon` text,
`uid` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY(`client_id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE config
@ -95,10 +95,10 @@ CREATE TABLE IF NOT EXISTS `config` (
`id` int(10) unsigned NOT NULL auto_increment,
`cat` varchar(255) NOT NULL DEFAULT '',
`k` varchar(255) NOT NULL DEFAULT '',
`v` text NOT NULL,
`v` text,
PRIMARY KEY(`id`),
INDEX `cat_k` (`cat`(30),`k`(30))
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE contact
@ -115,29 +115,29 @@ CREATE TABLE IF NOT EXISTS `contact` (
`name` varchar(255) NOT NULL DEFAULT '',
`nick` varchar(255) NOT NULL DEFAULT '',
`location` varchar(255) NOT NULL DEFAULT '',
`about` text NOT NULL,
`keywords` text NOT NULL,
`about` text,
`keywords` text,
`gender` varchar(32) NOT NULL DEFAULT '',
`attag` varchar(255) NOT NULL DEFAULT '',
`avatar` varchar(255) NOT NULL DEFAULT '',
`photo` text NOT NULL,
`thumb` text NOT NULL,
`micro` text NOT NULL,
`site-pubkey` text NOT NULL,
`photo` text,
`thumb` text,
`micro` text,
`site-pubkey` text,
`issued-id` varchar(255) NOT NULL DEFAULT '',
`dfrn-id` varchar(255) NOT NULL DEFAULT '',
`url` varchar(255) NOT NULL DEFAULT '',
`nurl` varchar(255) NOT NULL DEFAULT '',
`addr` varchar(255) NOT NULL DEFAULT '',
`alias` varchar(255) NOT NULL DEFAULT '',
`pubkey` text NOT NULL,
`prvkey` text NOT NULL,
`pubkey` text,
`prvkey` text,
`batch` varchar(255) NOT NULL DEFAULT '',
`request` text NOT NULL,
`notify` text NOT NULL,
`poll` text NOT NULL,
`confirm` text NOT NULL,
`poco` text NOT NULL,
`request` text,
`notify` text,
`poll` text,
`confirm` text,
`poco` text,
`aes_allow` tinyint(1) NOT NULL DEFAULT 0,
`ret-aes` tinyint(1) NOT NULL DEFAULT 0,
`usehub` tinyint(1) NOT NULL DEFAULT 0,
@ -161,19 +161,19 @@ CREATE TABLE IF NOT EXISTS `contact` (
`archive` tinyint(1) NOT NULL DEFAULT 0,
`pending` tinyint(1) NOT NULL DEFAULT 1,
`rating` tinyint(1) NOT NULL DEFAULT 0,
`reason` text NOT NULL,
`reason` text,
`closeness` tinyint(2) NOT NULL DEFAULT 99,
`info` mediumtext NOT NULL,
`info` mediumtext,
`profile-id` int(11) NOT NULL DEFAULT 0,
`bdyear` varchar(4) NOT NULL DEFAULT '',
`bd` date NOT NULL DEFAULT '0000-00-00',
`notify_new_posts` tinyint(1) NOT NULL DEFAULT 0,
`fetch_further_information` tinyint(1) NOT NULL DEFAULT 0,
`ffi_keyword_blacklist` mediumtext NOT NULL,
`ffi_keyword_blacklist` mediumtext,
PRIMARY KEY(`id`),
INDEX `uid` (`uid`),
INDEX `nurl` (`nurl`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE conv
@ -181,15 +181,15 @@ CREATE TABLE IF NOT EXISTS `contact` (
CREATE TABLE IF NOT EXISTS `conv` (
`id` int(10) unsigned NOT NULL auto_increment,
`guid` varchar(64) NOT NULL DEFAULT '',
`recips` mediumtext NOT NULL,
`recips` mediumtext,
`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',
`subject` mediumtext NOT NULL,
`subject` mediumtext,
PRIMARY KEY(`id`),
INDEX `uid` (`uid`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE deliverq
@ -200,7 +200,7 @@ CREATE TABLE IF NOT EXISTS `deliverq` (
`item` int(11) NOT NULL DEFAULT 0,
`contact` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE event
@ -214,26 +214,27 @@ CREATE TABLE IF NOT EXISTS `event` (
`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',
`summary` text NOT NULL,
`desc` text NOT NULL,
`location` text NOT NULL,
`summary` text,
`desc` text,
`location` text,
`type` varchar(255) NOT NULL DEFAULT '',
`nofinish` tinyint(1) NOT NULL DEFAULT 0,
`adjust` tinyint(1) NOT NULL DEFAULT 1,
`ignore` tinyint(1) unsigned NOT NULL DEFAULT 0,
`allow_cid` mediumtext NOT NULL,
`allow_gid` mediumtext NOT NULL,
`deny_cid` mediumtext NOT NULL,
`deny_gid` mediumtext NOT NULL,
`allow_cid` mediumtext,
`allow_gid` mediumtext,
`deny_cid` mediumtext,
`deny_gid` mediumtext,
PRIMARY KEY(`id`),
INDEX `uid` (`uid`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE fcontact
--
CREATE TABLE IF NOT EXISTS `fcontact` (
`id` int(10) unsigned NOT NULL auto_increment,
`guid` varchar(255) NOT NULL DEFAULT '',
`url` varchar(255) NOT NULL DEFAULT '',
`name` varchar(255) NOT NULL DEFAULT '',
`photo` varchar(255) NOT NULL DEFAULT '',
@ -247,11 +248,11 @@ CREATE TABLE IF NOT EXISTS `fcontact` (
`priority` tinyint(1) NOT NULL DEFAULT 0,
`network` varchar(32) NOT NULL DEFAULT '',
`alias` varchar(255) NOT NULL DEFAULT '',
`pubkey` text NOT NULL,
`pubkey` text,
`updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY(`id`),
INDEX `addr` (`addr`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE ffinder
@ -262,7 +263,7 @@ CREATE TABLE IF NOT EXISTS `ffinder` (
`cid` int(10) unsigned NOT NULL DEFAULT 0,
`fid` int(10) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE fserver
@ -271,10 +272,10 @@ CREATE TABLE IF NOT EXISTS `fserver` (
`id` int(11) NOT NULL auto_increment,
`server` varchar(255) NOT NULL DEFAULT '',
`posturl` varchar(255) NOT NULL DEFAULT '',
`key` text NOT NULL,
`key` text,
PRIMARY KEY(`id`),
INDEX `server` (`server`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE fsuggest
@ -287,10 +288,10 @@ CREATE TABLE IF NOT EXISTS `fsuggest` (
`url` varchar(255) NOT NULL DEFAULT '',
`request` varchar(255) NOT NULL DEFAULT '',
`photo` varchar(255) NOT NULL DEFAULT '',
`note` text NOT NULL,
`note` text,
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE gcign
@ -302,7 +303,7 @@ CREATE TABLE IF NOT EXISTS `gcign` (
PRIMARY KEY(`id`),
INDEX `uid` (`uid`),
INDEX `gcid` (`gcid`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE gcontact
@ -320,8 +321,8 @@ CREATE TABLE IF NOT EXISTS `gcontact` (
`last_contact` datetime DEFAULT '0000-00-00 00:00:00',
`last_failure` datetime DEFAULT '0000-00-00 00:00:00',
`location` varchar(255) NOT NULL DEFAULT '',
`about` text NOT NULL,
`keywords` text NOT NULL,
`about` text,
`keywords` text,
`gender` varchar(32) NOT NULL DEFAULT '',
`birthday` varchar(32) NOT NULL DEFAULT '0000-00-00',
`community` tinyint(1) NOT NULL DEFAULT 0,
@ -329,7 +330,7 @@ CREATE TABLE IF NOT EXISTS `gcontact` (
`nsfw` tinyint(1) NOT NULL DEFAULT 0,
`network` varchar(255) NOT NULL DEFAULT '',
`addr` varchar(255) NOT NULL DEFAULT '',
`notify` text NOT NULL,
`notify` text,
`alias` varchar(255) NOT NULL DEFAULT '',
`generation` tinyint(3) NOT NULL DEFAULT 0,
`server_url` varchar(255) NOT NULL DEFAULT '',
@ -339,7 +340,7 @@ CREATE TABLE IF NOT EXISTS `gcontact` (
INDEX `nick` (`nick`),
INDEX `addr` (`addr`),
INDEX `updated` (`updated`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE glink
@ -355,7 +356,7 @@ CREATE TABLE IF NOT EXISTS `glink` (
INDEX `cid_uid_gcid_zcid` (`cid`,`uid`,`gcid`,`zcid`),
INDEX `gcid` (`gcid`),
INDEX `zcid` (`zcid`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE group
@ -368,7 +369,7 @@ CREATE TABLE IF NOT EXISTS `group` (
`name` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY(`id`),
INDEX `uid` (`uid`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE group_member
@ -380,7 +381,7 @@ CREATE TABLE IF NOT EXISTS `group_member` (
`contact-id` int(10) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY(`id`),
INDEX `uid_gid_contactid` (`uid`,`gid`,`contact-id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE gserver
@ -391,7 +392,7 @@ CREATE TABLE IF NOT EXISTS `gserver` (
`nurl` varchar(255) NOT NULL DEFAULT '',
`version` varchar(255) NOT NULL DEFAULT '',
`site_name` varchar(255) NOT NULL DEFAULT '',
`info` text NOT NULL,
`info` text,
`register_policy` tinyint(1) NOT NULL DEFAULT 0,
`poco` varchar(255) NOT NULL DEFAULT '',
`noscrape` varchar(255) NOT NULL DEFAULT '',
@ -403,7 +404,7 @@ CREATE TABLE IF NOT EXISTS `gserver` (
`last_failure` datetime DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY(`id`),
INDEX `nurl` (`nurl`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE hook
@ -416,7 +417,7 @@ CREATE TABLE IF NOT EXISTS `hook` (
`priority` int(11) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY(`id`),
INDEX `hook_file_function` (`hook`(30),`file`(60),`function`(30))
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE intro
@ -428,13 +429,13 @@ CREATE TABLE IF NOT EXISTS `intro` (
`contact-id` int(11) NOT NULL DEFAULT 0,
`knowyou` tinyint(1) NOT NULL DEFAULT 0,
`duplex` tinyint(1) NOT NULL DEFAULT 0,
`note` text NOT NULL,
`note` text,
`hash` varchar(255) NOT NULL DEFAULT '',
`datetime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`blocked` tinyint(1) NOT NULL DEFAULT 1,
`ignore` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE item
@ -458,34 +459,36 @@ CREATE TABLE IF NOT EXISTS `item` (
`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',
`owner-id` int(11) NOT NULL DEFAULT 0,
`owner-name` varchar(255) NOT NULL DEFAULT '',
`owner-link` varchar(255) NOT NULL DEFAULT '',
`owner-avatar` varchar(255) NOT NULL DEFAULT '',
`author-id` int(11) NOT NULL DEFAULT 0,
`author-name` varchar(255) NOT NULL DEFAULT '',
`author-link` varchar(255) NOT NULL DEFAULT '',
`author-avatar` varchar(255) NOT NULL DEFAULT '',
`title` varchar(255) NOT NULL DEFAULT '',
`body` mediumtext NOT NULL,
`body` mediumtext,
`app` varchar(255) NOT NULL DEFAULT '',
`verb` varchar(255) NOT NULL DEFAULT '',
`object-type` varchar(255) NOT NULL DEFAULT '',
`object` text NOT NULL,
`object` text,
`target-type` varchar(255) NOT NULL DEFAULT '',
`target` text NOT NULL,
`postopts` text NOT NULL,
`target` text,
`postopts` text,
`plink` varchar(255) NOT NULL DEFAULT '',
`resource-id` varchar(255) NOT NULL DEFAULT '',
`event-id` int(11) NOT NULL DEFAULT 0,
`tag` mediumtext NOT NULL,
`attach` mediumtext NOT NULL,
`inform` mediumtext NOT NULL,
`file` mediumtext NOT NULL,
`tag` mediumtext,
`attach` mediumtext,
`inform` mediumtext,
`file` mediumtext,
`location` varchar(255) NOT NULL DEFAULT '',
`coord` varchar(255) NOT NULL DEFAULT '',
`allow_cid` mediumtext NOT NULL,
`allow_gid` mediumtext NOT NULL,
`deny_cid` mediumtext NOT NULL,
`deny_gid` mediumtext NOT NULL,
`allow_cid` mediumtext,
`allow_gid` mediumtext,
`deny_cid` mediumtext,
`deny_gid` mediumtext,
`private` tinyint(1) NOT NULL DEFAULT 0,
`pubmail` tinyint(1) NOT NULL DEFAULT 0,
`moderated` tinyint(1) NOT NULL DEFAULT 0,
@ -501,7 +504,7 @@ CREATE TABLE IF NOT EXISTS `item` (
`mention` tinyint(1) NOT NULL DEFAULT 0,
`network` varchar(32) NOT NULL DEFAULT '',
`rendered-hash` varchar(32) NOT NULL DEFAULT '',
`rendered-html` mediumtext NOT NULL,
`rendered-html` mediumtext,
`global` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY(`id`),
INDEX `guid` (`guid`),
@ -511,7 +514,7 @@ CREATE TABLE IF NOT EXISTS `item` (
INDEX `extid` (`extid`),
INDEX `uid_id` (`uid`,`id`),
INDEX `uid_created` (`uid`,`created`),
INDEX `uid_unseen` (`uid`,`unseen`),
INDEX `uid_unseen_contactid` (`uid`,`unseen`,`contact-id`),
INDEX `uid_network_received` (`uid`,`network`,`received`),
INDEX `uid_received` (`uid`,`received`),
INDEX `uid_network_commented` (`uid`,`network`,`commented`),
@ -519,15 +522,18 @@ CREATE TABLE IF NOT EXISTS `item` (
INDEX `uid_title` (`uid`,`title`),
INDEX `uid_thrparent` (`uid`,`thr-parent`),
INDEX `uid_parenturi` (`uid`,`parent-uri`),
INDEX `uid_contactid_id` (`uid`,`contact-id`,`id`),
INDEX `uid_contactid_created` (`uid`,`contact-id`,`created`),
INDEX `gcontactid_uid_created` (`gcontact-id`,`uid`,`created`),
INDEX `authorid_created` (`author-id`,`created`),
INDEX `ownerid_created` (`owner-id`,`created`),
INDEX `wall_body` (`wall`,`body`(6)),
INDEX `uid_visible_moderated_created` (`uid`,`visible`,`moderated`,`created`),
INDEX `uid_uri` (`uid`,`uri`),
INDEX `uid_wall_created` (`uid`,`wall`,`created`),
INDEX `resource-id` (`resource-id`),
INDEX `uid_type` (`uid`,`type`),
INDEX `uid_starred` (`uid`,`starred`),
INDEX `uid_starred_id` (`uid`,`starred`,`id`),
INDEX `contactid_allowcid_allowpid_denycid_denygid` (`contact-id`,`allow_cid`(10),`allow_gid`(10),`deny_cid`(10),`deny_gid`(10)),
INDEX `uid_wall_parent_created` (`uid`,`wall`,`parent`,`created`),
INDEX `uid_type_changed` (`uid`,`type`,`changed`),
@ -537,7 +543,7 @@ CREATE TABLE IF NOT EXISTS `item` (
INDEX `uid_eventid` (`uid`,`event-id`),
INDEX `uid_authorlink` (`uid`,`author-link`),
INDEX `uid_ownerlink` (`uid`,`owner-link`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE item_id
@ -553,7 +559,7 @@ CREATE TABLE IF NOT EXISTS `item_id` (
INDEX `sid` (`sid`),
INDEX `service` (`service`),
INDEX `iid` (`iid`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE locks
@ -564,7 +570,7 @@ CREATE TABLE IF NOT EXISTS `locks` (
`locked` tinyint(1) NOT NULL DEFAULT 0,
`created` datetime DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE mail
@ -579,7 +585,7 @@ CREATE TABLE IF NOT EXISTS `mail` (
`contact-id` varchar(255) NOT NULL DEFAULT '',
`convid` int(11) unsigned NOT NULL DEFAULT 0,
`title` varchar(255) NOT NULL DEFAULT '',
`body` mediumtext NOT NULL,
`body` mediumtext,
`seen` tinyint(1) NOT NULL DEFAULT 0,
`reply` tinyint(1) NOT NULL DEFAULT 0,
`replied` tinyint(1) NOT NULL DEFAULT 0,
@ -594,7 +600,7 @@ CREATE TABLE IF NOT EXISTS `mail` (
INDEX `reply` (`reply`),
INDEX `uri` (`uri`),
INDEX `parent-uri` (`parent-uri`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE mailacct
@ -607,14 +613,14 @@ CREATE TABLE IF NOT EXISTS `mailacct` (
`ssltype` varchar(16) NOT NULL DEFAULT '',
`mailbox` varchar(255) NOT NULL DEFAULT '',
`user` varchar(255) NOT NULL DEFAULT '',
`pass` text NOT NULL,
`pass` text,
`reply_to` varchar(255) NOT NULL DEFAULT '',
`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',
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE manage
@ -625,7 +631,7 @@ CREATE TABLE IF NOT EXISTS `manage` (
`mid` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY(`id`),
INDEX `uid_mid` (`uid`,`mid`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE notify
@ -638,7 +644,7 @@ CREATE TABLE IF NOT EXISTS `notify` (
`url` varchar(255) NOT NULL DEFAULT '',
`photo` varchar(255) NOT NULL DEFAULT '',
`date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`msg` mediumtext NOT NULL,
`msg` mediumtext,
`uid` int(11) NOT NULL DEFAULT 0,
`link` varchar(255) NOT NULL DEFAULT '',
`iid` int(11) NOT NULL DEFAULT 0,
@ -648,7 +654,7 @@ CREATE TABLE IF NOT EXISTS `notify` (
`otype` varchar(16) NOT NULL DEFAULT '',
PRIMARY KEY(`id`),
INDEX `uid` (`uid`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE notify-threads
@ -662,18 +668,18 @@ CREATE TABLE IF NOT EXISTS `notify-threads` (
PRIMARY KEY(`id`),
INDEX `master-parent-item` (`master-parent-item`),
INDEX `receiver-uid` (`receiver-uid`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE oembed
--
CREATE TABLE IF NOT EXISTS `oembed` (
`url` varchar(255) NOT NULL,
`content` text NOT NULL,
`content` text,
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY(`url`),
INDEX `created` (`created`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE parsed_url
@ -682,11 +688,11 @@ CREATE TABLE IF NOT EXISTS `parsed_url` (
`url` varchar(255) NOT NULL,
`guessing` tinyint(1) NOT NULL DEFAULT 0,
`oembed` tinyint(1) NOT NULL DEFAULT 0,
`content` text NOT NULL,
`content` text,
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY(`url`,`guessing`,`oembed`),
INDEX `created` (`created`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE pconfig
@ -696,10 +702,10 @@ CREATE TABLE IF NOT EXISTS `pconfig` (
`uid` int(11) NOT NULL DEFAULT 0,
`cat` varchar(255) NOT NULL DEFAULT '',
`k` varchar(255) NOT NULL DEFAULT '',
`v` mediumtext NOT NULL,
`v` mediumtext,
PRIMARY KEY(`id`),
INDEX `uid_cat_k` (`uid`,`cat`(30),`k`(30))
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE photo
@ -713,7 +719,7 @@ CREATE TABLE IF NOT EXISTS `photo` (
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`edited` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`title` varchar(255) NOT NULL DEFAULT '',
`desc` text NOT NULL,
`desc` text,
`album` varchar(255) NOT NULL DEFAULT '',
`filename` varchar(255) NOT NULL DEFAULT '',
`type` varchar(128) NOT NULL DEFAULT 'image/jpeg',
@ -723,15 +729,15 @@ CREATE TABLE IF NOT EXISTS `photo` (
`data` mediumblob NOT NULL,
`scale` tinyint(3) NOT NULL DEFAULT 0,
`profile` tinyint(1) NOT NULL DEFAULT 0,
`allow_cid` mediumtext NOT NULL,
`allow_gid` mediumtext NOT NULL,
`deny_cid` mediumtext NOT NULL,
`deny_gid` mediumtext NOT NULL,
`allow_cid` mediumtext,
`allow_gid` mediumtext,
`deny_cid` mediumtext,
`deny_gid` mediumtext,
PRIMARY KEY(`id`),
INDEX `uid` (`uid`),
INDEX `resource-id` (`resource-id`),
INDEX `guid` (`guid`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE poll
@ -739,19 +745,19 @@ CREATE TABLE IF NOT EXISTS `photo` (
CREATE TABLE IF NOT EXISTS `poll` (
`id` int(11) NOT NULL auto_increment,
`uid` int(11) NOT NULL DEFAULT 0,
`q0` mediumtext NOT NULL,
`q1` mediumtext NOT NULL,
`q2` mediumtext NOT NULL,
`q3` mediumtext NOT NULL,
`q4` mediumtext NOT NULL,
`q5` mediumtext NOT NULL,
`q6` mediumtext NOT NULL,
`q7` mediumtext NOT NULL,
`q8` mediumtext NOT NULL,
`q9` mediumtext NOT NULL,
`q0` mediumtext,
`q1` mediumtext,
`q2` mediumtext,
`q3` mediumtext,
`q4` mediumtext,
`q5` mediumtext,
`q6` mediumtext,
`q7` mediumtext,
`q8` mediumtext,
`q9` mediumtext,
PRIMARY KEY(`id`),
INDEX `uid` (`uid`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE poll_result
@ -763,7 +769,7 @@ CREATE TABLE IF NOT EXISTS `poll_result` (
PRIMARY KEY(`id`),
INDEX `poll_id` (`poll_id`),
INDEX `choice` (`choice`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE profile
@ -785,26 +791,26 @@ CREATE TABLE IF NOT EXISTS `profile` (
`hometown` varchar(255) NOT NULL DEFAULT '',
`gender` varchar(32) NOT NULL DEFAULT '',
`marital` varchar(255) NOT NULL DEFAULT '',
`with` text NOT NULL,
`with` text,
`howlong` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`sexual` varchar(255) NOT NULL DEFAULT '',
`politic` varchar(255) NOT NULL DEFAULT '',
`religion` varchar(255) NOT NULL DEFAULT '',
`pub_keywords` text NOT NULL,
`prv_keywords` text NOT NULL,
`likes` text NOT NULL,
`dislikes` text NOT NULL,
`about` text NOT NULL,
`pub_keywords` text,
`prv_keywords` text,
`likes` text,
`dislikes` text,
`about` text,
`summary` varchar(255) NOT NULL DEFAULT '',
`music` text NOT NULL,
`book` text NOT NULL,
`tv` text NOT NULL,
`film` text NOT NULL,
`interest` text NOT NULL,
`romance` text NOT NULL,
`work` text NOT NULL,
`education` text NOT NULL,
`contact` text NOT NULL,
`music` text,
`book` text,
`tv` text,
`film` text,
`interest` text,
`romance` text,
`work` text,
`education` text,
`contact` text,
`homepage` varchar(255) NOT NULL DEFAULT '',
`photo` varchar(255) NOT NULL DEFAULT '',
`thumb` varchar(255) NOT NULL DEFAULT '',
@ -812,7 +818,7 @@ CREATE TABLE IF NOT EXISTS `profile` (
`net-publish` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY(`id`),
INDEX `hometown` (`hometown`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE profile_check
@ -825,7 +831,7 @@ CREATE TABLE IF NOT EXISTS `profile_check` (
`sec` varchar(255) NOT NULL DEFAULT '',
`expire` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE push_subscriber
@ -840,7 +846,7 @@ CREATE TABLE IF NOT EXISTS `push_subscriber` (
`last_update` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`secret` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE queue
@ -851,7 +857,7 @@ CREATE TABLE IF NOT EXISTS `queue` (
`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',
`content` mediumtext NOT NULL,
`content` mediumtext,
`batch` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY(`id`),
INDEX `cid` (`cid`),
@ -859,7 +865,7 @@ CREATE TABLE IF NOT EXISTS `queue` (
INDEX `last` (`last`),
INDEX `network` (`network`),
INDEX `batch` (`batch`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE register
@ -872,7 +878,7 @@ CREATE TABLE IF NOT EXISTS `register` (
`password` varchar(255) NOT NULL DEFAULT '',
`language` varchar(16) NOT NULL DEFAULT '',
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE search
@ -884,7 +890,7 @@ CREATE TABLE IF NOT EXISTS `search` (
PRIMARY KEY(`id`),
INDEX `uid` (`uid`),
INDEX `term` (`term`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE session
@ -892,12 +898,12 @@ CREATE TABLE IF NOT EXISTS `search` (
CREATE TABLE IF NOT EXISTS `session` (
`id` bigint(20) unsigned NOT NULL auto_increment,
`sid` varchar(255) NOT NULL DEFAULT '',
`data` text NOT NULL,
`data` text,
`expire` int(10) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY(`id`),
INDEX `sid` (`sid`),
INDEX `expire` (`expire`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE sign
@ -905,12 +911,12 @@ CREATE TABLE IF NOT EXISTS `session` (
CREATE TABLE IF NOT EXISTS `sign` (
`id` int(10) unsigned NOT NULL auto_increment,
`iid` int(10) unsigned NOT NULL DEFAULT 0,
`signed_text` mediumtext NOT NULL,
`signature` text NOT NULL,
`signed_text` mediumtext,
`signature` text,
`signer` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY(`id`),
INDEX `iid` (`iid`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE spam
@ -927,7 +933,7 @@ CREATE TABLE IF NOT EXISTS `spam` (
INDEX `spam` (`spam`),
INDEX `ham` (`ham`),
INDEX `term` (`term`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE term
@ -952,7 +958,7 @@ CREATE TABLE IF NOT EXISTS `term` (
INDEX `uid_otype_type_term_global_created` (`uid`,`otype`,`type`,`term`,`global`,`created`),
INDEX `otype_type_term_tid` (`otype`,`type`,`term`,`tid`),
INDEX `guid` (`guid`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE thread
@ -962,6 +968,8 @@ CREATE TABLE IF NOT EXISTS `thread` (
`uid` int(10) unsigned NOT NULL DEFAULT 0,
`contact-id` int(11) unsigned NOT NULL DEFAULT 0,
`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',
@ -994,20 +1002,20 @@ CREATE TABLE IF NOT EXISTS `thread` (
INDEX `wall_private_received` (`wall`,`private`,`received`),
INDEX `uid_created` (`uid`,`created`),
INDEX `uid_commented` (`uid`,`commented`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE tokens
--
CREATE TABLE IF NOT EXISTS `tokens` (
`id` varchar(40) NOT NULL,
`secret` text NOT NULL,
`secret` text,
`client_id` varchar(20) NOT NULL DEFAULT '',
`expires` int(11) NOT NULL DEFAULT 0,
`scope` varchar(200) NOT NULL DEFAULT '',
`uid` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE user
@ -1027,10 +1035,10 @@ CREATE TABLE IF NOT EXISTS `user` (
`default-location` varchar(255) NOT NULL DEFAULT '',
`allow_location` tinyint(1) NOT NULL DEFAULT 0,
`theme` varchar(255) NOT NULL DEFAULT '',
`pubkey` text NOT NULL,
`prvkey` text NOT NULL,
`spubkey` text NOT NULL,
`sprvkey` text NOT NULL,
`pubkey` text,
`prvkey` text,
`spubkey` text,
`sprvkey` text,
`verified` tinyint(1) unsigned NOT NULL DEFAULT 0,
`blocked` tinyint(1) unsigned NOT NULL DEFAULT 0,
`blockwall` tinyint(1) unsigned NOT NULL DEFAULT 0,
@ -1050,14 +1058,14 @@ CREATE TABLE IF NOT EXISTS `user` (
`expire_notification_sent` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`service_class` varchar(32) NOT NULL DEFAULT '',
`def_gid` int(11) NOT NULL DEFAULT 0,
`allow_cid` mediumtext NOT NULL,
`allow_gid` mediumtext NOT NULL,
`deny_cid` mediumtext NOT NULL,
`deny_gid` mediumtext NOT NULL,
`openidserver` text NOT NULL,
`allow_cid` mediumtext,
`allow_gid` mediumtext,
`deny_cid` mediumtext,
`deny_gid` mediumtext,
`openidserver` text,
PRIMARY KEY(`uid`),
INDEX `nickname` (`nickname`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE userd
@ -1067,19 +1075,19 @@ CREATE TABLE IF NOT EXISTS `userd` (
`username` varchar(255) NOT NULL,
PRIMARY KEY(`id`),
INDEX `username` (`username`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;
--
-- TABLE workerqueue
--
CREATE TABLE IF NOT EXISTS `workerqueue` (
`id` int(11) NOT NULL auto_increment,
`parameter` text NOT NULL,
`parameter` text,
`priority` tinyint(3) unsigned NOT NULL DEFAULT 0,
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`pid` int(11) NOT NULL DEFAULT 0,
`executed` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY(`id`),
INDEX `created` (`created`)
) DEFAULT CHARSET=utf8;
) DEFAULT CHARSET=utf8mb4;

View file

@ -42,6 +42,12 @@ Block
<p style="clear:both;">&nbsp;</p>
<pre>[code=php]function text_highlight($s,$lang)[/code]</pre>
<code><div class="hl-main"><ol class="hl-main"><li><span class="hl-code">&nbsp;</span><span class="hl-reserved">function</span><span class="hl-code"> </span><span class="hl-identifier">text_highlight</span><span class="hl-brackets">(</span><span class="hl-var">$s</span><span class="hl-code">,</span><span class="hl-var">$lang</span><span class="hl-brackets">)</span></li></ol></div></code>
<p style="clear:both;">&nbsp;</p>
<pre>[quote]quote[/quote]</pre>
<blockquote>quote</blockquote>

View file

@ -16,7 +16,7 @@ Contact us
The discussion of Friendica development takes place in the following Friendica forums:
* The main [forum for Friendica development](https://friendika.openmindspace.org/profile/friendicadevelopers)
* The main [forum for Friendica development](https://helpers.pyxis.uberspace.de/profile/developers)
* The [forum for Friendica theme development](https://friendica.eu/profile/ftdevs)
Help other users
@ -79,7 +79,7 @@ If you want to get involved here:
* Look at the first steps that were made (e.g. the clean theme).
Ask us to find out whom to talk to about their experiences.
* Talk to design people if you know any.
* Let us know about your plans [in the dev forum](https://friendika.openmindspace.org/profile/friendicadevelopers) and the [theme developer forum](https://friendica.eu/profile/ftdevs).
* Let us know about your plans [in the dev forum](https://helpers.pyxis.uberspace.de/profile/developers) and the [theme developer forum](https://friendica.eu/profile/ftdevs).
Do not worry about cross-posting.
###Client software

View file

@ -28,7 +28,7 @@ Friendica Documentation and Resources
**Admin Manual**
* [Install](help/Install)
* [Settings](help/Settings)
* [Settings & Admin Panel](help/Settings)
* [Installing Connectors (Twitter/GNU Social)](help/Installing-Connectors)
* [Install an ejabberd server (XMPP chat) with synchronized credentials](help/install-ejabberd)
* [Message Flow](help/Message-Flow)

View file

@ -10,7 +10,7 @@ Not every PHP/MySQL hosting provider will be able to support Friendica.
Many will.
But **please** review the requirements and confirm these with your hosting provider prior to installation.
Also if you encounter installation issues, please let us know via the [helper](http://helpers.pyxis.uberspace.de/profile/helpers) or the [developer](https://friendika.openmindspace.org/profile/friendicadevelopers) forum or [file an issue](https://github.com/friendica/friendica/issues).
Also if you encounter installation issues, please let us know via the [helper](http://helpers.pyxis.uberspace.de/profile/helpers) or the [developer](https://helpers.pyxis.uberspace.de/profile/developers) forum or [file an issue](https://github.com/friendica/friendica/issues).
Please be as clear as you can about your operating environment and provide as much detail as possible about any error messages you may see, so that we can prevent it from happening in the future.
Due to the large variety of operating systems and PHP platforms in existence we may have only limited ability to debug your PHP installation or acquire any missing modules - but we will do our best to solve any general code issues.
If you do not have a Friendica account yet, you can register a temporary one at [tryfriendica.de](https://tryfriendica.de) and join the forums mentioned above from there.
@ -26,12 +26,12 @@ Requirements
---
* Apache with mod-rewrite enabled and "Options All" so you can use a local .htaccess file
* PHP 5.2+. The later the better. You'll need 5.3 for encryption of key exchange conversations. On a Windows environment, 5.2+ might not work as the function dns_get_record() is only available with version 5.3.
* PHP 5.4+.
* PHP *command line* access with register_argc_argv set to true in the php.ini file
* curl, gd, mysql, hash and openssl extensions
* some form of email server or email gateway such that PHP mail() works
* mcrypt (optional; used for server-to-server message encryption)
* Mysql 5.x or an equivalant alternative for MySQL (MariaDB etc.)
* Mysql 5.5.3+ or an equivalant alternative for MySQL (MariaDB, Percona Server etc.)
* the ability to schedule jobs with cron (Linux/Mac) or Scheduled Tasks (Windows) (Note: other options are presented in Section 7 of this document.)
* Installation into a top-level domain or sub-domain (without a directory/path component in the URL) is preferred. Directory paths will not be as convenient to use and have not been thoroughly tested.
* If your hosting provider doesn't allow Unix shell access, you might have trouble getting everything to work.

View file

@ -1,176 +1,105 @@
Settings
===
Here are some of the built-in features which don't have an exposed interface or are otherwise undocumented.
Configuration settings are stored in the file ".htconfig.php".
Edit this file with a text editor to make the desired changes.
Several system settings are already documented in that file and will not be covered here.
# Settings
Hot Keys
---
If you are the admin of a Friendica node, you have access to the so called **Admin Panel** where you can configure your Friendica node.
Friendica traps the following keyboard events:
On the front page of the admin panel you will see a summary of information about your node.
These information include the amount of messages currently being processed in the queues.
The first number is the number of messages being actively sent.
This number should decrease quickly.
The second is the messages which could for various reasons not being delivered.
They will be resend later.
You can have a quick glance into that second queus in the "Inspect Queue" section of the admin panel.
If you have activated the background workers, there might be a third number representing the count of jobs queued for the workers.
* [Pause] - Pauses "Ajax" update activity. This is the process that provides updates without reloading the page. You may wish to pause it to reduce network usage and/or as a debugging aid for javascript developers. A pause indicator will appear at the lower right hand corner of the page. Hit the [pause] key once again to resume.
Then you get an overview of the accounts on your node, which can be moderated in the "Users" section of the panel.
As well as an overview of the currently active addons
The list is linked, so you can have quick access to the plugin settings.
And finally you are informed about the version of Friendica you have installed.
If you contact the devs with a bug or problem, please also mention the version of your node.
Birthday Notifications
---
The admin panel is seperated into subsections accessible from the side bar of the panel.
Birthday events are published on your Home page for any friends having a birthday in the coming 6 days.
In order for your birthday to be discoverable by all of your friends, you must set your birthday (at least the month and day) in your default profile.
You are not required to provide the year.
## Site
System settings
---
This section of the admin panel contains the main configuration of your Friendica node.
It is separated into several sub-section beginning with the basic settings at the top, advancing towards the bottom of the page.
**Settings should be done in the admin panel** (/admin).
Those settings found in the database, will always override the settings added to the ``.htconfig.php`` file.
Most configuration options have a help text in the admin panel.
Therefore this document does not yet cover all the options
###Language
### Basic Settings
Please see util/README for information on creating language translations.
Config:
$a->config['system']['language'] = 'name';
###System Theme
Choose a theme to be the default system theme. This can be over-ridden by user profiles.
Default theme is "default".
Config:
$a->config['system']['theme'] = 'theme-name';
###Proxy Configuration Settings
If your site uses a proxy to connect to the internet, you may use these settings to communicate with the outside world.
The outside world still needs to be able to see your website, or this will not be very useful.
Config:
$a->config['system']['proxy'] = "http://proxyserver.domain:port";
$a->config['system']['proxyuser'] = "username:password";
###Network Timeout
How long to wait on a network communication before timing out.
Value is in seconds.
Default is 60 seconds.
Set to 0 for unlimited (not recommended).
Config:
$a->config['system']['curl_timeout'] = 60;
###Banner/Logo
#### Banner/Logo
Set the content for the site banner.
The default logo is the Friendica logo and name.
You may wish to provide HTML/CSS to style and/or position this content, as it may not be themed by default.
Config:
#### Language
$a->config['system']['banner'] = '<span id="logo-text">My Great Website</span>';
This option will set the default language for the node.
It is used as fall back setting should Friendica fail to recognize the visitors preferences and can be overwritten by user settings.
###Maximum Image Size
The Friendica community offers some translations.
Some more compleate then others.
See [this help page](/help/translations) for more information about the translation process.
Maximum size in bytes of uploaded images.
The default is set to 0, which means no limits.
#### System Theme
Config:
Choose a theme to be the default system theme.
This can be over-ridden by user profiles.
Default theme is "duepunto zero" at the moment.
$a->config['system']['maximagesize'] = 1000000;
You may also want to set a special theme for mobile interfaces.
Which may or may not be neccessary depending of the mobile friendlyness of the desktop theme you have chosen.
The `vier` theme for instance is mobile friendly.
###UTF-8 Regular Expressions
### Registration
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).
Config:
$a->config['system']['no_utf'] = true;
###Check Full Names
#### Check Full Names
You may find a lot of spammers trying to register on your site.
During testing we discovered that since these registrations were automatic, the "Full Name" field was often set to just an account name with no space between first and last name.
If you would like to support people with only one name as their full name, you may change this setting to true.
Default is false.
Config:
$a->config['system']['no_regfullname'] = true;
###OpenID
#### OpenID
By default, OpenID may be used for both registration and logins.
If you do not wish to make OpenID facilities available on your system (at all), set 'no_openid' to true.
Default is false.
Config:
$a->config['system']['no_openid'] = true;
###Multiple Registrations
#### Multiple Registrations
The ability to create "Pages" requires a person to register more than once.
Your site configuration can block registration (or require approval to register).
By default, logged in users can register additional accounts for use as pages.
These will still require approval if REGISTER_APPROVE is selected.
You may prohibit logged in users from creating additional accounts by setting 'block_extended_register' to true.
These will still require approval if the registration policy is set to *require approval*
You may prohibit logged in users from creating additional accounts by setting *block multible registrations* to true.
Default is false.
Config:
### File upload
$a->config['system']['block_extended_register'] = true;
#### Maximum Image Size
Security settings
---
Maximum size in bytes of uploaded images.
The default is set to 0, which means no limits.
###Verify SSL Certitificates
### Policies
By default Friendica allows SSL communication between websites that have "self-signed" SSL certificates.
For the widest compatibility with browsers and other networks we do not recommend using self-signed certificates, but we will not prevent you from using them.
SSL encrypts all the data transmitted between sites (and to your browser). This allows you to have completely encrypted communications, and also protect your login session from hijacking.
Self-signed certificates can be generated for free, without paying top-dollar for a website SSL certificate.
However these aren't looked upon favourably in the security community because they can be subject to so-called "man-in-the-middle" attacks.
If you wish, you can turn on strict certificate checking.
This will mean you cannot connect (at all) to self-signed SSL sites.
#### Global Directory
Config:
This configures the URL to update the global directory, and is supplied in the default configuration.
The undocumented part is that if this is not set, the global directory is completely unavailable to the application.
This allows a private community to be completely isolated from the global network.
$a->config['system']['verifyssl'] = true;
#### Force Publish
Corporate/Edu enhancements
---
By default, each user can choose on their Settings page whether or not to have their profile published in the site directory.
This setting forces all profiles on this site to be listed in the site directory and there is no option provided to the user to change it.
Default is false.
###Allowed Friend Domains
Comma separated list of domains which are allowed to establish friendships with this site.
Wildcards are accepted.
(Wildcard support on Windows platforms requires PHP5.3).
By default, any (valid) domain may establish friendships with this site.
Config:
$a->config['system']['allowed_sites'] = "sitea.com, *siteb.com";
###Allowed Email Domains
Comma separated list of domains which are allowed in email addresses for registrations to this site.
This can lockout those who are not part of this organisation from registering here.
Wildcards are accepted.
(Wildcard support on Windows platforms requires PHP5.3).
By default, any (valid) email address is allowed in registrations.
Config:
$a->config['system']['allowed_email'] = "sitea.com, *siteb.com";
###Block Public
#### Block Public
Set to true to block public access to all otherwise public personal pages on this site unless you are currently logged in.
This blocks the viewing of profiles, friends, photos, the site directory and search pages to unauthorised persons.
@ -181,50 +110,163 @@ Unauthorised persons will also not be able to request friendship with site membe
Default is false.
Available in version 2.2 or greater.
Config:
#### Allowed Friend Domains
$a->config['system']['block_public'] = true;
Comma separated list of domains which are allowed to establish friendships with this site.
Wildcards are accepted.
(Wildcard support on Windows platforms requires PHP5.3).
By default, any (valid) domain may establish friendships with this site.
###Force Publish
This is useful if you want to setup a closed network for educational groups, cooperations and similar communities that don't want to commuicate with the rest of the network.
By default, each user can choose on their Settings page whether or not to have their profile published in the site directory.
This setting forces all profiles on this site to be listed in the site directory and there is no option provided to the user to change it.
Default is false.
#### Allowed Email Domains
Config:
Comma separated list of domains which are allowed in email addresses for registrations to this site.
This can lockout those who are not part of this organisation from registering here.
Wildcards are accepted.
(Wildcard support on Windows platforms requires PHP5.3).
By default, any (valid) email address is allowed in registrations.
$a->config['system']['publish_all'] = true;
#### Allow Users to set remote_self
###Global Directory
If you enable the `Allow Users to set remote_self` users can select Atom feeds from their contact list being their *remote self* in die advanced contact settings.
Which means that postings by the remote self are automatically reposted by Friendica in their names.
This configures the URL to update the global directory, and is supplied in the default configuration.
The undocumented part is that if this is not set, the global directory is completely unavailable to the application.
This allows a private community to be completely isolated from the global network.
As admin of the node you can also set this flag directly in the database.
Before doing so, you should be sure you know what you do and have a backup of the database.
$a->config['system']['directory'] = 'http://dir.friendi.ca';
### Advanced
Developer Settings
---
#### Proxy Configuration Settings
### Debugging
Most useful when debugging protocol exchanges and tracking down other communications issues.
If your site uses a proxy to connect to the internet, you may use these settings to communicate with the outside world.
The outside world still needs to be able to see your website, or this will not be very useful.
Config:
#### Network Timeout
$a->config['system']['debugging'] = true;
$a->config['system']['logfile'] = 'logfile.out';
$a->config['system']['loglevel'] = LOGGER_DEBUG;
How long to wait on a network communication before timing out.
Value is in seconds.
Default is 60 seconds.
Set to 0 for unlimited (not recommended).
Turns on detailed debugging logs which will be stored in 'logfile.out' (which must be writeable by the webserver).
LOGGER_DEBUG will show a good deal of information about system activity but will not include detailed data.
You may also select LOGGER_ALL but due to the volume of information we recommend only enabling this when you are tracking down a specific problem.
Other log levels are possible but are not being used at the present time.
#### UTF-8 Regular Expressions
Please be aware that turning on the logging can fill up the disk space on your server relatively quick.
You should take preventions with e.g. [logrotate](https://en.wikipedia.org/wiki/Log_rotation) or similar tools.
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).
###PHP error logging
#### Verify SSL Certitificates
By default Friendica allows SSL communication between websites that have "self-signed" SSL certificates.
For the widest compatibility with browsers and other networks we do not recommend using self-signed certificates, but we will not prevent you from using them.
SSL encrypts all the data transmitted between sites (and to your browser).
This allows you to have completely encrypted communications, and also protect your login session from hijacking.
Self-signed certificates can be generated for free, without paying top-dollar for a website SSL certificate.
However these aren't looked upon favourably in the security community because they can be subject to so-called "man-in-the-middle" attacks.
If you wish, you can turn on strict certificate checking.
This will mean you cannot connect (at all) to self-signed SSL sites.
### Auto Discovered Contact Directory
### Performance
### Worker
### Relocate
## Users
This section of the panel let the admin control the users registered on the node.
If you have selected "Requires approval" for the *Register policy* in the general nodes configuration, new registrations will be listed at the top of the page.
There the admin can then approve or disapprove the request.
Below the new registration block the current accounts on the Friendica node are listed.
You can sort the user list by name, email, registration date, date of last login, date of last posting and the account type.
Here the admin can also block/unblock users from accessing the node or delete the accounts entirely.
In the last section of the page admins can create new accounts on the node.
The password for the new account will be send by email to the choosen email address.
## Plugins
This page is for selecting and configuration of extensions for Friendica which have to be placed into the `/addon` subdirectory of your Friendica installation.
You are presented with a long list of available addons.
The name of each addon is linked to a separate page for that addon which offers more informations and configuration possibilities.
Also shown is the version of the addon and an indicator if the addon is currently active or not.
When you update your node and the addons they may have to be reloaded.
To simplify this process there is a button at the top of the page to reload all active plugins.
## Themes
The Themes section of the admin panel works similar to the Plugins section but let you control the themes on your Friendica node.
Each theme has a dedicated suppage showing the current status, some information about the theme and a screen-shot of the Friendica interface using the theme.
Should the theme offer special settings, admins can set a global default value here.
You can activate and deactivate themes on their dedicated sub-pages thus making them available for the users of the node.
To select a default theme for the Friendica node, see the *Site* section of the admin panel.
## Additional Features
There are several optional features in Friendica.
Like the *dislike* button or the usage of a *richtext editor* for composing new postings.
In this section of the admin panel you can select a default setting for your node and eventually fix it, so users cannot change the setting anymore.
## DB Updates
Should the database structure of Friendica change, it will apply the changes automatically.
In case you are suspecious that the update might not have worked, you can use this section of the admin panel to check the situation.
## Inspect Queue
In the admin panel summary there are two numbers for the message queues.
The second number represents messages which could not be delivered and are queued for later retry.
If this number goes sky-rocking you might ask yourself which receopiant is not receiving.
Behind the inspect queue section of the admin panel you will find a list of the messages that could not be delivered.
The listing is sorted by the receipiant name so identifying potential broken communication lines should be simple.
These lines might be broken for various reasons.
The receiving end might be off-line, there might be a high system load and so on.
Don't panic!
Friendica will not queue messages for all time but will sort out *dead* nodes automatically after a while and remove messages from the queue then.
## Federation Statistics
The federation statistics page gives you a short summery of the nodes/servers/pods of the decentralized social network federation your node knows.
These numbers are not compleate and only contain nodes from networks Friendica federates directly with.
## Plugin Features
Some of the addons you can install for your Friendica node have settings which have to be set by the admin.
All those addons will be listed in this area of the admin panels side bar with their names.
## Logs
The log section of the admin panel is seperated into two pages.
On the first, following the "log" link, you can configure how much Friendica shall log.
And on the second you can read the log.
You should not place your logs into any directory that is accessible from the web.
If you have to, and you are using the default configuration from Apache, you should choose a name for the logfile ending in ``.log`` or ``.out``.
Should you use another web server, please make sure that you have the correct accessrules in place so that your log files are not accessible.
There are five different log levels: Normal, Trace, Debug, Data and All.
Specifying different verbosities of information and data written out to the log file.
Normally you should not need to log at all.
The *DEBUG* level will show a good deal of information about system activity but will not include detailed data.
In the *ALL* level Friendica will log everything to the file.
But due to the volume of information we recommend only enabling this when you are tracking down a specific problem.
**The amount of data can grow the filesize of the logfile quickly**.
You should set up some kind of [log rotation](https://en.wikipedia.org/wiki/Log_rotation) to keep the log file from growing too big.
**Known Issues**: The filename ``friendica.log`` can cause problems depending on your server configuration (see [issue 2209](https://github.com/friendica/friendica/issues/2209)).
By default PHP warnings and error messages are supressed.
If you want to enable those, you have to activate them in the ``.htconfig.php`` file.
Use the following settings to redirect PHP errors to a file.
Config:
@ -235,11 +277,61 @@ Config:
ini_set('display_errors', '0');
This will put all PHP errors in the file php.out (which must be writeable by the webserver).
Undeclared variables are occasionally referenced in the program and therefore we do not recommend using E_NOTICE or E_ALL.
Undeclared variables are occasionally referenced in the program and therefore we do not recommend using `E_NOTICE` or `E_ALL`.
The vast majority of issues reported at these levels are completely harmless.
Please report to the developers any errors you encounter in the logs using the recommended settings above.
They generally indicate issues which need to be resolved.
If you encounter a blank (white) page when using the application, view the PHP logs - as this almost always indicates an error has occurred.
*Note*: PHP logging cannot be activated from the admin panel but has to be configured from the ``.htconfig.php`` file.
## Diagnostics
In this section of the admin panel you find two tools to investigate what Friendica sees for certain ressources.
These tools can help to clarify communication problems.
For the *probe address* Friendica will display information for the address provided.
With the second tool *check webfinger* you can request information about the thing identified by a webfinger (`someone@example.com`).
# Exceptions to the rule
There are four exceptions to the rule, that all the config will be read from the data base.
These are the data base settings, the admin account settings, the path of PHP and information about an eventual installation of the node in a sub-directory of the (sub)domain.
## DB Settings
With the following settings, you specify the data base server, the username and passwort for Friendica and the database to use.
$db_host = 'your.db.host';
$db_user = 'db_username';
$db_pass = 'db_password';
$db_data = 'database_name';
## Admin users
You can set one, or more, accounts to be *Admin*.
By default this will be the one account you create during the installation process.
But you can expand the list of email addresses by any used email address you want.
Registration of new accounts with a listed email address is not possible.
$a->config['admin_email'] = 'you@example.com, buddy@example.com';
## PHP Path
Some of Friendicas processes are running in the background.
For this you need to specify the path to the PHP binary to be used.
$a->config['php_path'] = '{{$phpath}}';
## Subdirectory configuration
It is possible to install Friendica into a subdirectory of your webserver.
We strongly discurage you from doing so, as this will break federation to other networks (e.g. Diaspora, GNU Socia, Hubzilla)
Say you have a subdirectory for tests and put Friendica into a further subdirectory, the config would be:
$a->path = 'tests/friendica';
## Other exceptions
Furthermore there are some experimental settings, you can read-up in the [Config values that can only be set in .htconfig.php](help/htconfig) section of the documentation.

View file

@ -104,6 +104,7 @@ Unofficial Twitter command. It shows all direct answers (excluding the original
* max_id: maximum id
* getText: Defines the format of the status field. Can be "html" or "plain"
* include_entities: "true" shows entities for pictures and links (Default: false)
* friendica_verbose: "true" enables different error returns (default: "false")
#### Unsupported parameters
* skip_status
@ -116,6 +117,7 @@ Unofficial Twitter command. It shows all direct answers (excluding the original
* since_id: minimal id
* max_id: maximum id
* getText: Defines the format of the status field. Can be "html" or "plain"
* friendica_verbose: "true" enables different error returns (default: "false")
---
### direct_messages/conversation (*; AUTH)
@ -127,6 +129,18 @@ Shows all direct messages of a conversation
* max_id: maximum id
* getText: Defines the format of the status field. Can be "html" or "plain"
* uri: URI of the conversation
* friendica_verbose: "true" enables different error returns (default: "false")
---
### direct_messages/sent (*; AUTH)
#### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* getText: Defines the format of the status field. Can be "html" or "plain"
* include_entities: "true" shows entities for pictures and links (Default: false)
* friendica_verbose: "true" enables different error returns (default: "false")
---
### direct_messages/new (POST,PUT; AUTH)
@ -138,14 +152,22 @@ Shows all direct messages of a conversation
* title: Title of the direct message
---
### direct_messages/sent (*; AUTH)
### direct_messages/destroy (POST,DELETE; AUTH)
#### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* getText: Defines the format of the status field. Can be "html" or "plain"
* include_entities: "true" shows entities for pictures and links (Default: false)
* id: id of the message to be deleted
* include_entities: optional, currently not yet implemented
* friendica_parenturi: optional, can be used for increased safety to delete only intended messages
* friendica_verbose: "true" enables different error returns (default: "false")
#### Return values
On success:
* JSON return as defined for Twitter API not yet implemented
* on friendica_verbose=true: JSON return {"result":"ok","message":"message deleted"}
On error:
HTTP 400 BadRequest
* on friendica_verbose=true: different JSON returns {"result":"error","message":"xyz"}
---
### favorites (*; AUTH)
@ -694,6 +716,33 @@ xml
</photos>
```
---
### friendica/direct_messages_setseen (GET; AUTH)
#### Parameters
* id: id of the message to be updated as seen
#### Return values
On success:
* JSON return {"result":"ok","message":"message set to seen"}
On error:
* different JSON returns {"result":"error","message":"xyz"}
---
### friendica/direct_messages_search (GET; AUTH)
#### Parameters
* searchstring: string for which the API call should search as '%searchstring%' in field 'body' of all messages of the authenticated user (caption ignored)
#### Return values
Returns only tested with JSON, XML might work as well.
On success:
* JSON return {"success":"true","search_results": array of found messages}
* JSOn return {"success":"false","search_results":"nothing found"}
On error:
* different JSON returns {"result":"error","message":"searchstring not specified"}
---
## Not Implemented API calls
@ -718,7 +767,6 @@ The following API calls from the Twitter API aren't implemented neither in Frien
* statuses/lookup
* direct_messages/show
* search/tweets
* direct_messages/destroy
* friendships/no_retweets/ids
* friendships/incoming
* friendships/outgoing

View file

@ -4,6 +4,7 @@ Table fcontact
| Field | Description | Type | Null | Key | Default | Extra |
| -------- | ------------- | ---------------- | ---- | --- | ------------------- | --------------- |
| id | sequential ID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| guid | unique id | varchar(64) | NO | | | |
| url | | varchar(255) | NO | | | |
| name | | varchar(255) | NO | | | |
| photo | | varchar(255) | NO | | | |

View file

@ -24,9 +24,11 @@ Table item
| owner-name | Name of the owner of this item | varchar(255) | NO | | | |
| owner-link | Link to the profile page of the owner of this item | varchar(255) | NO | | | |
| owner-avatar | Link to the avatar picture of the owner of this item | varchar(255) | NO | | | |
| owner-id | Link to the contact table with uid=0 of the owner of this item | int(11) | NO | MUL | 0 | |
| author-name | Name of the author of this item | varchar(255) | NO | | | |
| author-link | Link to the profile page of the author of this item | varchar(255) | NO | | | |
| author-avatar | Link to the avatar picture of the author of this item | varchar(255) | NO | | | |
| author-id | Link to the contact table with uid=0 of the author of this item | int(11) | NO | MUL | 0 | |
| title | item title | varchar(255) | NO | | | |
| body | item body content | mediumtext | NO | | NULL | |
| app | application which generated this item | varchar(255) | NO | | | |

View file

@ -7,6 +7,8 @@ Table thread
| uid | | int(10) unsigned | NO | MUL | 0 | |
| contact-id | | int(11) unsigned | NO | | 0 | |
| gcontact-id | Global Contact | int(11) unsigned | NO | | 0 | |
| owner-id | Item owner | int(11) unsigned | NO | MUL | 0 | |
| author-id | Item author | int(11) unsigned | NO | MUL | 0 | |
| created | | datetime | NO | MUL | 0000-00-00 00:00:00 | |
| edited | | datetime | NO | | 0000-00-00 00:00:00 | |
| commented | | datetime | NO | MUL | 0000-00-00 00:00:00 | |

View file

@ -42,6 +42,12 @@ Block Tags
<p style="clear:both;">&nbsp;</p>
<pre>[code=php]function text_highlight($s,$lang)[/code]</pre>
<code><div class="hl-main"><ol class="hl-main"><li><span class="hl-code">&nbsp;</span><span class="hl-reserved">function</span><span class="hl-code"> </span><span class="hl-identifier">text_highlight</span><span class="hl-brackets">(</span><span class="hl-var">$s</span><span class="hl-code">,</span><span class="hl-var">$lang</span><span class="hl-brackets">)</span></li></ol></div></code>
<p style="clear:both;">&nbsp;</p>
<pre>[quote]Zitat[/quote]</pre>
<blockquote>Zitat</blockquote>

View file

@ -29,7 +29,7 @@ Friendica - Dokumentation und Ressourcen
**Technische Dokumentation**
* [Installation](help/Install)
* [Konfigurationen](help/Settings)
* [Konfigurationen & Admin-Panel](help/Settings)
* [Plugins](help/Plugins)
* [Konnektoren (Connectors) installieren (Twitter/GNU Social)](help/Installing-Connectors)
* [Installation eines ejabberd Servers (XMPP-Chat) mit synchronisierten Anmeldedaten](help/install-ejabberd) (EN)

View file

@ -1,55 +1,152 @@
Konfigurationen
==============
# Settings
* [Zur Startseite der Hilfe](help)
Wenn du der Administrator einer Friendica Instanz bist, hast du Zugriff auf das so genannte **Admin Panel** in dem du die Friendica Instanz konfigurieren kannst,
Hier findest du einige eingebaute Features, welche kein graphisches Interface haben oder nicht dokumentiert sind.
Konfigurationseinstellungen sind in der Datei ".htconfig.php" gespeichert.
Bearbeite diese Datei, indem du sie z.B. mit einem Texteditor öffnest.
Verschiedene Systemeinstellungen sind bereits in dieser Datei dokumentiert und werden hier nicht weiter erklärt.
Auf der Startseite des Admin Panels werden die Informationen zu der Instanz zusammengefasst.
Diese Informationen beinhalten die Anzahl der Nachrichten, die sich aktuell in den Warteschlangen befinden.
Hierbei ist die erste Zahl die Zahl der Nachrichten die gerade aktiv verteilt werden.
Diese Zahl sollte sich relativ schnell sinken.
Die zweite Zahl gibt die Anzahl von Nachrichten an, die nicht zugestellt werden konnten.
Die Zustellung wird zu einem späteren Zeitpunkt noch einmal versucht.
Unter dem Punkt "Warteschlange Inspizieren" kannst du einen schnellen Blick auf die zweite Warteschlange werfen.
Solltest du für die Hintergrundprozesse die Worker aktiviert haben, könntest du eine dritte Zahl angezeigt bekommen.
Diese repräsentiert die Anzahl der Aufgaben, die die Worker noch vor sich haben.
**Tastaturbefehle**
Des weiteren findest du eine Übersicht über die Accounts auf dem Friendica Knoten, die unter dem Punkt "Nutzer" moderiert werden können.
Sowie eine Liste der derzeit aktivierten Addons.
Diese Liste ist verlinkt, so dass du schnellen Zugriff auf die Informationsseiten der einzelnen Addons hast.
Abschließend findest du auf der Startseite des Admin Panels die installierte Version von Friendica.
Wenn du in Kontakt mit den Entwicklern trittst und Probleme oder Fehler zu schildern, gib diese Version bitte immer mit an.
Friendica erfasst die folgenden Tastaturbefehle:
Die Unterabschnitte des Admin Panels kannst du in der Seitenleiste auswählen.
* [Pause] - Pausiert die Update-Aktivität via "Ajax". Das ist ein Prozess, der Updates durchführt, ohne die Seite neu zu laden. Du kannst diesen Prozess pausieren, um deine Netzwerkauslastung zu reduzieren und/oder um es in der Javascript-Programmierung zum Debuggen zu nutzen. Ein Pausenzeichen erscheint unten links im Fenster. Klicke die [Pause]-Taste ein weiteres Mal, um die Pause zu beenden.
## Seite
**Geburtstagsbenachrichtigung**
In diesem Bereich des Admin Panels findest du die Hauptkonfiguration deiner Friendica Instanz.
Er ist in mehrere Unterabschnitte aufgeteilt, wobei die Grundeinstellungen oben auf der Seite zu finden sind.
Geburtstage erscheinen auf deiner Startseite für alle Freunde, die in den nächsten 6 Tagen Geburtstag haben.
Um deinen Geburtstag für alle sichtbar zu machen, musst du deinen Geburtstag (zumindest Tag und Monat) in dein Standardprofil eintragen.
Es ist nicht notwendig, das Jahr einzutragen.
Da die meisten Konfigurationsoptionen einen Hilfstext im Admin Panel haben, kann und will dieser Artikel nicht alle Einstellungen abdecken.
**Konfigurationseinstellungen**
### Grundeinstellungen
#### Banner/Logo
**Sprache**
Hiermit legst du das Banner der Seite fest. Standardmäßig ist das Friendica-Logo und der Name festgelegt.
Du kannst hierfür HTML/CSS nutzen, um den Inhalt zu gestalten und/oder die Position zu ändern, wenn es nicht bereits voreingestellt ist.
Systemeinstellung
#### Systensprache
Bitte schau dir die Datei util/README an, um Informationen zur Erstellung einer Übersetzung zu erhalten.
Diese Einstellung legt die Standardsprache der Instanz fest.
Sie wird verwendet, wenn es Friendica nicht gelingt die Spracheinstellungen des Besuchers zu erkennen oder diese nicht unterstützt wird.
Nutzer können diese Auswahl in den Einstellungen des Benutzerkontos überschreiben.
Konfiguriere:
```
$a->config['system']['language'] = 'name';
```
Die Friendica Gemeinschaft bietet einige Übersetzungen an, von denen einige mehr andere weniger komplett sind.
Mehr Informationen zum Übersetzungsprozess von Friendica findest du [auf dieser Seite](/help/translations) der Dokumentation.
#### Systemweites Theme
**System-Thema (Design)**
Hier kann das Theme bestimmt werden, welches standardmäßig zum Anzeigen der Seite verwendet werden soll.
Nutzer können in ihren Einstellungen andere Themes wählen.
Derzeit ist das "duepunto zero" Theme das vorausgewählte Theme.
Systemeinstellung
Für mobile Geräte kannst du ein spezielles Theme wählen, wenn das Standardtheme ungeeignet für mobile Geräte sein sollte.
Das `vier` Theme z.B. unterstützt kleine Anzeigen und benötigt kein zusätzliches mobiles Theme.
Wähle ein Thema als Standardsystemdesign (welches vom Nutzer überschrieben werden kann). Das Standarddesign ist "default".
### Registrierung
Konfiguriere:
```
$a->config['system']['theme'] = 'theme-name';
```
#### Namen auf Vollständigkeit überprüfen
Es kann vorkommen, dass viele Spammer versuchen, sich auf deiner Seite zu registrieren.
In Testphasen haben wir festgestellt, dass diese automatischen Registrierungen das Feld "Vollständiger Name" oft nur mit Namen ausfüllen, die kein Leerzeichen beinhalten.
Wenn du Leuten erlauben willst, sich nur mit einem Namen anzumelden, dann setze die Einstellung auf "true".
Die Standardeinstellung ist auf "false" gesetzt.
**Verifiziere SSL-Zertifikate**
#### OpenID Unterstützung
Sicherheitseinstellungen
Standardmäßig wird OpenID für die Registrierung und für Logins genutzt.
Wenn du nicht willst, dass OpenID-Strukturen für dein System übernommen werden, dann setze "no_openid" auf "true".
Standardmäßig ist hier "false" gesetzt.
#### Unterbinde Mehrfachregistrierung
Um mehrfache Seiten zu erstellen, muss sich eine Person mehrfach registrieren können.
Deine Seiteneinstellung kann Registrierungen komplett blockieren oder an Bedingungen knüpfen.
Standardmäßig können eingeloggte Nutzer weitere Accounts für die Seitenerstellung registrieren.
Hier ist weiterhin eine Bestätigung notwendig, wenn "REGISTER_APPROVE" ausgewählt ist.
Wenn du die Erstellung weiterer Accounts blockieren willst, dann setze die Einstellung "block_extended_register" auf "true".
Standardmäßig ist hier "false" gesetzt.
### Datei hochladen
#### Maximale Bildgröße
Maximale Bild-Dateigröße in Byte. Standardmäßig ist 0 gesetzt, was bedeutet, dass kein Limit gesetzt ist.
### Regeln
#### URL des weltweiten Verzeichnisses
Mit diesem Befehl wird die URL eingestellt, die zum Update des globalen Verzeichnisses genutzt wird.
Dieser Befehl ist in der Standardkonfiguration enthalten.
Der nicht dokumentierte Teil dieser Einstellung ist, dass das globale Verzeichnis gar nicht verfügbar ist, wenn diese Einstellung nicht gesetzt wird.
Dies erlaubt eine private Kommunikation, die komplett vom globalen Verzeichnis isoliert ist.
#### Erzwinge Veröffentlichung
Standardmäßig können Nutzer selbst auswählen, ob ihr Profil im Seitenverzeichnis erscheint.
Diese Einstellung zwingt alle Nutzer dazu, im Verzeichnis zu erscheinen.
Diese Einstellung kann vom Nutzer nicht deaktiviert werden. Die Standardeinstellung steht auf "false".
#### Öffentlichen Zugriff blockieren
Aktiviere diese Einstellung um den öffentlichen Zugriff auf alle Seiten zu sperren, solange man nicht eingeloggt ist.
Das blockiert die Ansicht von Profilen, Freunden, Fotos, vom Verzeichnis und den Suchseiten.
Ein Nebeneffekt ist, dass Einträge dieser Seite nicht im globalen Verzeichnis erscheinen.
Wir empfehlen, speziell diese Einstellung auszuschalten (die Einstellung ist an anderer Stelle auf dieser Seite erklärt).
Beachte: das ist speziell für Seiten, die beabsichtigen, von anderen Friendica-Netzwerken abgeschottet zu sein.
Unautorisierte Personen haben ebenfalls nicht die Möglichkeit, Freundschaftsanfragen von Seitennutzern zu beantworten.
Die Standardeinstellung ist deaktiviert.
Verfügbar in Version 2.2 und höher.
#### Erlaubte Domains für Kontakte
Kommagetrennte Liste von Domains, welche eine Freundschaft mit dieser Seite eingehen dürfen.
Wildcards werden akzeptiert (Wildcard-Unterstützung unter Windows benötigt PHP5.3) Standardmäßig sind alle gültigen Domains erlaubt.
Mit dieser Option kann man einfach geschlossene Netzwerke, z.B. im schulischen Bereich aufbauen, aus denen nicht mit dem Rest des Netzwerks kommuniziert werden soll.
#### Erlaubte Domains für E-Mails
Kommagetrennte Liste von Domains, welche bei der Registrierung als Part der Email-Adresse erlaubt sind.
Das grenzt Leute aus, die nicht Teil der Gruppe oder Organisation sind.
Wildcards werden akzeptiert (Wildcard-Unterstützung unter Windows benötigt PHP5.3) Standardmäßig sind alle gültigen Email-Adressen erlaubt.
#### Nutzern erlauben das remote_self Flag zu setzen
Webb du die Option `Nutzern erlauben das remote_self Flag zu setzen` aktivierst, können alle Nutzer Atom Feeds in den erweiterten Einstellungen des Kontakts als "Entferntes Konto" markieren.
Dadurch werden automatisch alle Beiträge dieser Feeds für diesen Nutzer gespiegelt und an die Kontakte bei Friendica verteilt.
Als Administrator der Friendica Instanz kannst du diese Einstellungen ansonsten nur direkt in der Datenbank vornehmen.
Bevor du das tust solltest du sicherstellen, dass du ein Backup der Datenbank hast und genau weißt was die Änderungen an der Datenbank bewirken, die du vornehmen willst.
### Erweitert
#### Proxy Einstellungen
Wenn deine Seite eine Proxy-Einstellung nutzt, musst du diese Einstellungen vornehmen, um mit anderen Seiten im Internet zu kommunizieren.
#### Netzwerk Wartezeit
Legt fest, wie lange das Netzwerk warten soll, bevor ein Timeout eintritt.
Der Wert wird in Sekunden angegeben. Standardmäßig ist 60 eingestellt; 0 steht für "unbegrenzt" (nicht empfohlen).
#### UTF-8 Reguläre Ausdrücke
Während der Registrierung werden die Namen daraufhin geprüft, ob sie reguläre UTF-8-Ausdrücke nutzen.
Hierfür wird PHP benötigt, um mit einer speziellen Einstellung kompiliert zu werden, die UTF-8-Ausdrücke benutzt.
Wenn du absolut keine Möglichkeit hast, Accounts zu registrieren, setze diesen Wert auf ja.
#### SSL Überprüfen
Standardmäßig erlaubt Friendica SSL-Kommunikation von Seiten, die "selbst unterzeichnete" SSL-Zertifikate nutzen.
Um eine weitreichende Kompatibilität mit anderen Netzwerken und Browsern zu gewährleisten, empfehlen wir, selbst unterzeichnete Zertifikate **nicht** zu nutzen.
@ -59,217 +156,166 @@ Diese Zertifikate können allerdings Opfer eines sogenannten ["man-in-the-middle
Wenn du es wünscht, kannst du eine strikte Zertifikatabfrage einstellen.
Das führt dazu, dass du keinerlei Verbindung zu einer selbst unterzeichneten SSL-Seite erstellen kannst
Konfiguriere:
```
$a->config['system']['verifyssl'] = true;
```
### Automatisch ein Kontaktverzeichnis erstellen
### Performance
**Erlaubte Freunde-Domains**
### Worker
Kooperationen/Gemeinschaften/Bildung Erweiterung
### Umsiedeln
Kommagetrennte Liste von Domains, welche eine Freundschaft mit dieser Seite eingehen dürfen.
Wildcards werden akzeptiert (Wildcard-Unterstützung unter Windows benötigt PHP5.3) Standardmäßig sind alle gültigen Domains erlaubt.
## Nutzer
Konfiguriere:
```
$a->config['system']['allowed_sites'] = "sitea.com, *siteb.com";
```
In diesem Abschnitt des Admin Panels kannst du die Nutzer deiner Friendica Instanz moderieren.
Solltest du für **Registrierungsmethode** die Einstellung "Bedarf Zustimmung" gewählt haben, werden hier zu Beginn der Seite neue Registrationen aufgelistet.
Als Administrator kannst du hier die Registration akzeptieren oder ablehnen.
**Erlaubte Email-Domains**
Unter dem Abschnitt mit den Registrationen werden die aktuell auf der Instanz registrierten Nutzer aufgelistet.
Die Liste kann nach Namen, E-Mail Adresse, Datum der Registration, der letzten Anmeldung oder dem letzten Beitrag und dem Account Typ sortiert werden.
An dieser Stelle kannst du existierende Accounts vom Zugriff auf die Instanz blockieren, sie wieder frei geben oder Accounts endgültig löschen.
Kooperationen/Gemeinschaften/Bildung Erweiterung
Im letzten Bereich auf der Seite kannst du als Administrator neue Accounts anlegen.
Das Passwort für so eingerichtete Accounts werden per E-Mail an die Nutzer geschickt.
Kommagetrennte Liste von Domains, welche bei der Registrierung als Part der Email-Adresse erlaubt sind.
Das grenzt Leute aus, die nicht Teil der Gruppe oder Organisation sind.
Wildcards werden akzeptiert (Wildcard-Unterstützung unter Windows benötigt PHP5.3) Standardmäßig sind alle gültigen Email-Adressen erlaubt.
## Plugins
Konfiguriere:
```
$a->config['system']['allowed_email'] = "sitea.com, *siteb.com";
```
Dieser Bereich des Admin Panels dient der Auswahl und Konfiguration der Erweiterungen von Friendica.
Sie müssen in das `/addon` Verzeichnis kopiert werden.
Auf der Seite wird eine Liste der verfügbaren Erweiterungen angezeigt.
Neben den Namen der Erweiterungen wird ein Indikator angezeigt, der anzeigt ob das Addon gerade aktiviert ist oder nicht.
**Öffentlichkeit blockieren**
Wenn du die Erweiterungen aktualisiert die du auf deiner Friendica Instanz nutzt könnte es sein, dass sie neu geladen werden müssen, damit die Änderungen aktiviert werden.
Um diesen Prozess zu vereinfachen gibt es am Anfang der Seite einen Button um alle aktiven Plugins neu zu laden.
Kooperationen/Gemeinschaften/Bildung Erweiterung
## Themen
Setze diese Einstellung auf "true" und sperre den öffentlichen Zugriff auf alle Seiten, solange man nicht eingeloggt ist.
Das blockiert die Ansicht von Profilen, Freunden, Fotos, vom Verzeichnis und den Suchseiten.
Ein Nebeneffekt ist, dass Einträge dieser Seite nicht im globalen Verzeichnis erscheinen.
Wir empfehlen, speziell diese Einstellung auszuschalten (die Einstellung ist an anderer Stelle auf dieser Seite erklärt).
Beachte: das ist speziell für Seiten, die beabsichtigen, von anderen Friendica-Netzwerken abgeschottet zu sein.
Unautorisierte Personen haben ebenfalls nicht die Möglichkeit, Freundschaftsanfragen von Seitennutzern zu beantworten.
Die Standardeinstellung steht auf "false".
Verfügbar in Version 2.2 und höher.
Der Bereich zur Kontrolle der auf der Friendica Instanz verfügbaren Themen funktioniert analog zum Plugins Bereich.
Jedes Theme hat eine extra Seite auf der der aktuelle Status, ein Bildschirmfoto des Themes, zusätzliche Informationen und eventuelle Einstellungen des Themes zu finden sind.
Genau wie Erweiterungen können Themes in der Übersichtsliste oder der Theme-Seite aktiviert bzw. deaktiviert werden.
Um ein Standardtheme für die Instanz zu wählen, benutze bitte die *Seiten* Bereich des Admin Panels.
Konfiguriere:
```
$a->config['system']['block_public'] = true;
```
## Zusätzliche Features
Es gibt einige optionale Features in Friendica, die Nutzer benutzen können oder halt nicht.
Zum Beispiel den *dislike* Button oder den *Webeditor* beim Erstellen von neuen Beiträgen.
In diesem Bereich des Admin Panels kannst du die Grundeinstellungen für diese Features festlegen und gegebenenfalls die Entscheidung treffen, dass Nutzer deiner Instanz diese auch nicht mehr ändern können.
**Veröffentlichung erzwingen**
## DB Updates
Kooperationen/Gemeinschaften/Bildung Erweiterung
Wenn sich die Datenbankstruktur Friendicas ändert werden die Änderungen automatisch angewandt.
Solltest du den Verdacht haben, das eine Aktualisierung fehlgeschlagen ist, kannst du in diesem Bereich des Admin Panels den Status der Aktualisierungen überprüfen.
Standardmäßig können Nutzer selbst auswählen, ob ihr Profil im Seitenverzeichnis erscheint.
Diese Einstellung zwingt alle Nutzer dazu, im Verzeichnis zu erscheinen.
Diese Einstellung kann vom Nutzer nicht deaktiviert werden. Die Standardeinstellung steht auf "false".
## Warteschlange Inspizieren
Konfiguriere:
```
$a->config['system']['publish_all'] = true;
```
Auf der Eingangsseite des Admin Panels werden zwei Zahlen fpr die Warteschlangen angegeben.
Die zweite Zahl steht für die Beiträge, die initial nicht zugestellt werden konnten und später nochmal zugestellt werden sollen.
Sollte diese Zahl durch die Decke brechen, solltest du nachsehen an welchen Kontakt die Zustellung der Beiträge nicht funktioniert.
Unter dem Menüpunkt "Warteschlange Inspizieren" findest du eine Liste dieser nicht zustellbaren Beiträge.
Diese Liste ist nach dem Empfänger sortiert.
Die Kommunikation zu dem Empfänger kann aus unterschiedlichen Gründen gestört sein.
Der andere Server könnte offline sein, oder gerade einfach nur eine hohe Systemlast aufweisen.
**Globales Verzeichnis**
Aber keine Panik!
Friendica wird die Beiträge nicht für alle Zeiten in der Warteschlange behalten.
Nach einiger Zeit werden Knoten als inaktiv identifiziert und Nachrichten an Nutzer dieser Knoten aus der Warteschlange gelöscht.
Kooperationen/Gemeinschaften/Bildung Erweiterung
## Federation Statistik
Mit diesem Befehl wird die URL eingestellt, die zum Update des globalen Verzeichnisses genutzt wird.
Dieser Befehl ist in der Standardkonfiguration enthalten.
Der nichtdokumentierte Teil dieser Einstellung ist, dass das globale Verzeichnis gar nicht verfügbar ist, wenn diese Einstellung nicht gesetzt wird.
Dies erlaubt eine private Kommunikation, die komplett vom globalen Verzeichnis isoliert ist.
Deine Instanz ist ein Teil eines Netzwerks von Servern dezentraler sozialer Netzwerke, der sogenannten **Federation**.
In diesem Bereich des Admin Panels findest du ein paar Zahlen zu dem Teil der Federation, die deine Instanz kennt.
Konfiguriere:
```
$a->config['system']['directory'] = 'http://dir.friendi.ca';
```
## Plugin Features
Einige der Erweiterungen von Friendica benötigen global gültige Einstellungen, die der Administrator vornehmen muss.
Diese Erweiterungen sind hier aufgelistet, damit du die Einstellungen schneller findest.
**Proxy Konfigurationseinstellung**
## Protokolle
Wenn deine Seite eine Proxy-Einstellung nutzt, musst du diese Einstellungen vornehmen, um mit anderen Seiten im Internet zu kommunizieren.
Dieser Bereich des Admin Panels ist auf zwei Seiten verteilt.
Die eine Seite dient der Konfiguration, die andere dem Anzeigen der Logs.
Konfiguriere:
```
$a->config['system']['proxy'] = "http://proxyserver.domain:port";
$a->config['system']['proxyuser'] = "username:password";
```
Du solltest die Logdatei nicht in einem Verzeichnis anlegen, auf das man vom Internet aus zugreifen kann.
Wenn du das dennoch tun musste und die Standardeinstellungen des Apache Servers verwendest, dann solltest du darauf achten, dass die Logdateien mit der Endung `.log` oder `.out` enden.
Solltest du einen anderen Webserver verwenden, solltest du sicherstellen, dass der Zugrif zu Dateien mit diesen Endungen nicht möglich ist.
Es gibt fünf Level der Ausführlichkeit mit denen Friendica arbeitet: Normal, Trace, Debug, Data und All.
Normalerweise solltest du für den Betrieb deiner Friendica Instanz keine Logs benötigen.
Wenn du versuchst einem Problem auf den Grund zu gehen, solltest du das "DEBUG" Level wählen.
Mit dem "All" Level schreibt Friendica alles in die Logdatei.
Die Datenmenge der geloggten Daten kann relativ schnell anwachsen, deshalb empfehlen wir das Anlegen von Protokollen nur zu aktivieren wenn es unbedingt nötig ist.
**Netzwerk-Timeout**
**Die Größe der Logdateien kann schnell anwachsen**.
Du solltest deshalb einen Dienst zur [log rotation](https://en.wikipedia.org/wiki/Log_rotation) einrichten.
Legt fest, wie lange das Netzwerk warten soll, bevor ein Timeout eintritt.
Der Wert wird in Sekunden angegeben. Standardmäßig ist 60 eingestellt; 0 steht für "unbegrenzt" (nicht empfohlen).
**Bekannte Probleme**: Der Dateiname `friendica.log` kann bei speziellen Server Konfigurationen zu Problemen führen (siehe [issue 2209](https://github.com/friendica/friendica/issues/2209)).
Konfiguriere:
Normalerweise werden Fehler- und Warnmeldungen von PHP unterdrückt.
Wenn du sie aktivieren willst, musst du folgendes in der `.htconfig.php` Datei eintragen um die Meldungen in die Datei `php.out` zu speichern
```
$a->config['system']['curl_timeout'] = 60;
```
**Banner/Logo**
Hiermit legst du das Banner der Seite fest. Standardmäßig ist das Friendica-Logo und der Name festgelegt.
Du kannst hierfür HTML/CSS nutzen, um den Inhalt zu gestalten und/oder die Position zu ändern, wenn es nicht bereits voreingestellt ist.
Konfiguriere:
```
$a->config['system']['banner'] = '<span id="logo-text">Meine tolle Webseite</span>';
```
**Maximale Bildgröße**
Maximale Bild-Dateigröße in Byte. Standardmäßig ist 0 gesetzt, was bedeutet, dass kein Limit gesetzt ist.
Konfiguriere:
```
$a->config['system']['maximagesize'] = 1000000;
```
**UTF-8 Reguläre Ausdrücke**
Während der Registrierung werden die Namen daraufhin geprüft, ob sie reguläre UTF-8-Ausdrücke nutzen.
Hierfür wird PHP benötigt, um mit einer speziellen Einstellung kompiliert zu werden, die UTF-8-Ausdrücke benutzt.
Wenn du absolut keine Möglichkeit hast, Accounts zu registrieren, setze den Wert von "no_utf" auf "true".
Standardmäßig ist "false" eingestellt (das bedeutet, dass UTF-8-Ausdrücke unterstützt werden und funktionieren).
Konfiguriere:
```
$a->config['system']['no_utf'] = true;
```
**Prüfe vollständigen Namen**
Es kann vorkommen, dass viele Spammer versuchen, sich auf deiner Seite zu registrieren.
In Testphasen haben wir festgestellt, dass diese automatischen Registrierungen das Feld "Vollständiger Name" oft nur mit Namen ausfüllen, die kein Leerzeichen beinhalten.
Wenn du Leuten erlauben willst, sich nur mit einem Namen anzumelden, dann setze die Einstellung auf "true".
Die Standardeinstellung ist auf "false" gesetzt.
Konfiguriere:
```
$a->config['system']['no_regfullname'] = true;
```
**OpenID**
Standardmäßig wird OpenID für die Registrierung und für Logins genutzt.
Wenn du nicht willst, dass OpenID-Strukturen für dein System übernommen werden, dann setze "no_openid" auf "true".
Standardmäßig ist hier "false" gesetzt.
Konfiguriere:
```
$a->config['system']['no_openid'] = true;
```
**Multiple Registrierungen**
Um mehrfache Seiten zu erstellen, muss sich eine Person mehrfach registrieren können.
Deine Seiteneinstellung kann Registrierungen komplett blockieren oder an Bedingungen knüpfen.
Standardmäßig können eingeloggte Nutzer weitere Accounts für die Seitenerstellung registrieren.
Hier ist weiterhin eine Bestätigung notwendig, wenn "REGISTER_APPROVE" ausgewählt ist.
Wenn du die Erstellung weiterer Accounts blockieren willst, dann setze die Einstellung "block_extended_register" auf "true".
Standardmäßig ist hier "false" gesetzt.
Konfiguriere:
```
$a->config['system']['block_extended_register'] = true;
```
**Entwicklereinstellungen**
Diese sind am nützlichsten, um Protokollprozesse zu debuggen oder andere Kommunikationsfehler einzugrenzen.
Konfiguriere:
```
$a->config['system']['debugging'] = true;
$a->config['system']['logfile'] = 'logfile.out';
$a->config['system']['loglevel'] = LOGGER_DEBUG;
```
Erstellt detaillierte Debugging-Logfiles, die in der Datei "logfile.out" gespeichert werden (Datei muss auf dem Server mit Schreibrechten versehen sein). "LOGGER_DEBUG" zeigt eine Menge an Systeminformationen, enthält aber keine detaillierten Daten.
Du kannst ebenfalls "LOGGER_ALL" auswählen, allerdings empfehlen wir dieses nur, wenn ein spezifisches Problem eingegrenzt werden soll.
Andere Log-Level sind möglich, werden aber derzeit noch nicht genutzt.
**PHP-Fehler-Logging**
Nutze die folgenden Einstellungen, um PHP-Fehler direkt in einer Datei zu erfassen.
Konfiguriere:
```
error_reporting(E_ERROR | E_WARNING | E_PARSE );
ini_set('error_log','php.out');
ini_set('log_errors','1');
ini_set('display_errors', '0');
```
Diese Befehle erfassen alle PHP-Fehler in der Datei "php.out" (Datei muss auf dem Server mit Schreibrechten versehen sein).
Nicht deklarierte Variablen werden manchmal mit einem Verweis versehen, weshalb wir empfehlen, "E_NOTICE" und "E_ALL" nicht zu nutzen.
Die Menge an Fehlern, die auf diesem Level gemeldet werden, ist komplett harmlos.
Bitte informiere die Entwickler über alle Fehler, die du in deinen Log-Dateien mit den oben genannten Einstellungen erhältst.
Sie weisen generell auf Fehler in, die bearbeitet werden müssen.
Wenn du eine leere (weiße) Seite erhältst, schau in die PHP-Log-Datei - dies deutet fast immer darauf hin, dass ein Fehler aufgetreten ist.
Die Datei `php.out` muss vom Webserver schreibbar sein und sollte ebenfalls außerhalb der Webverzeichnisse liegen.
Es kommt gelegentlich vor, dass nicht deklarierte Variablen referenziert werden, dehalb raten wir davon ab `E_NOTICE` oder `E_ALL` zu verwenden.
Die überwiegende Mehrzahl der auf diesen Stufen dokumentierten Fehler sind absolut harmlos.
Solltest du mit den oben empfohlenen Einstellungen Fehler finden, teile sie bitte den Entwicklern mit.
Im Allgemeinen sind dies Fehler, die behoben werden sollten.
Solltest du eine leere (weiße) Seite vorfinden, während du Friendica nutzt, werfe bitte einen Blick in die PHP Logs.
Solche *White Screens* sind so gut wie immer ein Zeichen dafür, dass ein Fehler aufgetreten ist.
## Diagnose
In diesem Bereich des Admin Panels findest du zwei Werkzeuge mit der du untersuchen kannst, wie Friendica bestimmte Ressourcen einschätzt.
Diese Werkzeuge sind insbesondere bei der Analyse von Kommunikationsproblemen hilfreich.
"Adresse untersuchen" zeigt Informationen zu einer URL an, wie Friendica sie wahrnimmt.
Mit dem zweiten Werkzeug "Webfinger überprüfen" kannst du Informationen zu einem Ding anfordern, das über einen Webfinger ( jemand@example.com ) identifiziert wird.
# Die Ausnahmen der Regel
Für die oben genannte Regel gibt es vier Ausnahmen, deren Konfiguration nicht über das Admin Panel vorgenommen werden kann.
Dies sind die Datenbank Einstellungen, die Administrator Accounts, der PHP Pfad und die Konfiguration einer eventuellen Installation in ein Unterverzeichnis unterhalb der Hauptdomain.
## Datenbank Einstellungen
Mit den folgenden Einstellungen kannst du die Zugriffsdaten für den Datenbank Server festlegen.
$db_host = 'your.db.host';
$db_user = 'db_username';
$db_pass = 'db_password';
$db_data = 'database_name';
## Administratoren
Du kannst einen, oder mehrere Accounts, zu Administratoren machen.
Normalerweise trifft dies auf den ersten Account zu, der nach der Installation angelegt wird.
Die Liste der E-Mail Adressen kann aber einfach erweitert werden.
Mit keiner der angegebenen E-Mail Adressen können weitere Accounts registriert werden.
$a->config['admin_email'] = 'you@example.com, buddy@example.com';
## PHP Pfad
Einige Prozesse von Friendica laufen im Hintergrund.
Für diese Prozesse muss der Pfad zu der PHP Version gesetzt sein, die verwendet werden soll.
$a->config['php_path'] = '/pfad/zur/php-version';
## Unterverzeichnis Konfiguration
Man kann Friendica in ein Unterverzeichnis des Webservers installieren.
Wir raten allerdings dringen davon ab, da es die Interoperabilität mit anderen Netzwerken (z.B. Diaspora, GNU Social, Hubzilla) verhindert.
Mal angenommen, du hast ein Unterverzeichnis tests und willst Friendica in ein weiteres Unterverzeichnis installieren, dann lautet die Konfiguration hierfür:
$a->path = 'tests/friendica';
## Weitere Ausnahmen
Es gibt noch einige experimentelle Einstellungen, die nur in der ``.htconfig.php`` Datei konfiguriert werden können.
Im [Konfigurationswerte, die nur in der .htconfig.php gesetzt werden können (EN)](help/htconfig) Artikel kannst du mehr darüber erfahren.

View file

@ -38,6 +38,8 @@ line to your .htconfig.php:
* max_connections_level - The maximum level of connections that are allowed to let the poller start. It is a percentage value. Default value is 75.
* max_contact_queue - Default value is 500.
* max_batch_queue - Default value is 1000.
* max_processes_backend - Maximum number of concurrent database processes for background tasks. Default value is 5.
* max_processes_frontend - Maximum number of concurrent database processes for foreground tasks. Default value is 20.
* no_oembed (Boolean) - Don't use OEmbed to fetch more information about a link.
* no_oembed_rich_content (Boolean) - Don't show the rich content (e.g. embedded PDF).
* no_smilies (Boolean) - Don't show smilies.
@ -55,7 +57,7 @@ line to your .htconfig.php:
* qsearch_limit - Default value is 100.
* relay_server - Experimental Diaspora feature. Address of the relay server where public posts should be send to. For example https://podrelay.net
* relay_subscribe (Boolean) - Enables the receiving of public posts from the relay. They will be included in the search and on the community page when it is set up to show all public items.
* relay_scope - Can be "all" or "tags". "all" means that every public post should be received. "tags" means that only posts witt selected tags should be received.
* relay_scope - Can be "all" or "tags". "all" means that every public post should be received. "tags" means that only posts with selected tags should be received.
* relay_server_tags - Comma separated list of tags for the "tags" subscription (see "relay_scrope")
* relay_user_tags (Boolean) - If enabled, the tags from the saved searches will used for the "tags" subscription in addition to the "relay_server_tags".
* remove_multiplicated_lines (Boolean) - If enabled, multiple linefeeds in items are stripped to a single one.
@ -65,6 +67,7 @@ line to your .htconfig.php:
* throttle_limit_week - Maximum number of posts that a user can send per week with the API.
* throttle_limit_month - Maximum number of posts that a user can send per month with the API.
* wall-to-wall_share (Boolean) - Displays forwarded posts like "wall-to-wall" posts.
* worker_cooldown - Cooldown time after each worker function call. Default value is 0 seconds.
* xrd_timeout - Timeout for fetching the XRD links. Default value is 20 seconds.
## service_class ##

View file

@ -27,7 +27,7 @@ Friendica Documentation and Resources
**Technical Documentation**
* [Install](help/Install)
* [Settings](help/Settings)
* [Settings & Admin Panel](help/Settings)
* [Plugins](help/Plugins)
* [Installing Connectors (Twitter/GNU Social)](help/Installing-Connectors)
* [Install an ejabberd server (XMPP chat) with synchronized credentials](help/install-ejabberd)

View file

@ -16,6 +16,11 @@ $db_user = 'mysqlusername';
$db_pass = 'mysqlpassword';
$db_data = 'mysqldatabasename';
// Set the database connection charset to UTF8.
// Changing this value will likely corrupt the special characters.
// You have been warned.
$a->config['system']['db_charset'] = "utf8mb4";
// Choose a legal default timezone. If you are unsure, use "America/Los_Angeles".
// It can be changed later and only applies to timestamps for anonymous viewers.

View file

@ -45,10 +45,10 @@ function user_remove($uid) {
// don't delete yet, will be done later when contacts have deleted my stuff
// q("DELETE FROM `user` WHERE `uid` = %d", intval($uid));
q("UPDATE `user` SET `account_removed` = 1, `account_expires_on` = UTC_TIMESTAMP() WHERE `uid` = %d", intval($uid));
proc_run('php', "include/notifier.php", "removeme", $uid);
proc_run(PRIORITY_HIGH, "include/notifier.php", "removeme", $uid);
// Send an update to the directory
proc_run('php', "include/directory.php", $r[0]['url']);
proc_run(PRIORITY_LOW, "include/directory.php", $r[0]['url']);
if($uid == local_user()) {
unset($_SESSION['authenticated']);
@ -192,72 +192,97 @@ function unmark_for_death($contact) {
);
}}
function get_contact_details_by_url($url, $uid = -1) {
/**
* @brief Get contact data for a given profile link
*
* The function looks at several places (contact table and gcontact table) for the contact
*
* @param string $url The profile link
* @param int $uid User id
* @param array $default If not data was found take this data as default value
*
* @return array Contact data
*/
function get_contact_details_by_url($url, $uid = -1, $default = array()) {
if ($uid == -1)
$uid = local_user();
$r = q("SELECT `id` AS `gid`, `url`, `name`, `nick`, `addr`, `photo`, `location`, `about`, `keywords`, `gender`, `community`, `network` FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1",
dbesc(normalise_link($url)));
if ($r) {
$profile = $r[0];
if ((($profile["addr"] == "") OR ($profile["name"] == "")) AND
in_array($profile["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS)))
proc_run('php',"include/update_gcontact.php", $profile["gid"]);
}
// Fetching further contact data from the contact table
$r = q("SELECT `id`, `uid`, `url`, `network`, `name`, `nick`, `addr`, `location`, `about`, `keywords`, `gender`, `photo`, `thumb`, `addr`, `forum`, `prv`, `bd`, `self` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND `network` IN ('%s', '')",
dbesc(normalise_link($url)), intval($uid), dbesc($profile["network"]));
if (!count($r) AND !isset($profile))
$r = q("SELECT `id`, `uid`, `url`, `network`, `name`, `nick`, `addr`, `location`, `about`, `keywords`, `gender`, `photo`, `thumb`, `addr`, `forum`, `prv`, `bd`, `self` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d",
// Fetch contact data from the contact table for the given user
$r = q("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`,
`keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `bd` AS `birthday`, `self`
FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d",
dbesc(normalise_link($url)), intval($uid));
if (!count($r) AND !isset($profile))
$r = q("SELECT `id`, `uid`, `url`, `network`, `name`, `nick`, `addr`, `location`, `about`, `keywords`, `gender`, `photo`, `thumb`, `addr`, `forum`, `prv`, `bd` FROM `contact` WHERE `nurl` = '%s' AND `uid` = 0",
// Fetch the data from the contact table with "uid=0" (which is filled automatically)
if (!$r)
$r = q("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`,
`keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `bd` AS `birthday`, 0 AS `self`
FROM `contact` WHERE `nurl` = '%s' AND `uid` = 0",
dbesc(normalise_link($url)));
// Fetch the data from the gcontact table
if (!$r)
$r = q("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`,
`keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, `community` AS `forum`, 0 AS `prv`, `community`, `birthday`, 0 AS `self`
FROM `gcontact` WHERE `nurl` = '%s'",
dbesc(normalise_link($url)));
if ($r) {
if (!isset($profile["url"]) AND $r[0]["url"])
$profile["url"] = $r[0]["url"];
if (!isset($profile["name"]) AND $r[0]["name"])
$profile["name"] = $r[0]["name"];
if (!isset($profile["nick"]) AND $r[0]["nick"])
$profile["nick"] = $r[0]["nick"];
if (!isset($profile["addr"]) AND $r[0]["addr"])
$profile["addr"] = $r[0]["addr"];
if ((!isset($profile["photo"]) OR $r[0]["self"]) AND $r[0]["photo"])
$profile["photo"] = $r[0]["photo"];
if (!isset($profile["location"]) AND $r[0]["location"])
$profile["location"] = $r[0]["location"];
if (!isset($profile["about"]) AND $r[0]["about"])
$profile["about"] = $r[0]["about"];
if (!isset($profile["keywords"]) AND $r[0]["keywords"])
$profile["keywords"] = $r[0]["keywords"];
if (!isset($profile["gender"]) AND $r[0]["gender"])
$profile["gender"] = $r[0]["gender"];
if (isset($r[0]["forum"]) OR isset($r[0]["prv"]))
$profile["community"] = ($r[0]["forum"] OR $r[0]["prv"]);
if (!isset($profile["network"]) AND $r[0]["network"])
$profile["network"] = $r[0]["network"];
if (!isset($profile["addr"]) AND $r[0]["addr"])
$profile["addr"] = $r[0]["addr"];
if (!isset($profile["bd"]) AND $r[0]["bd"])
$profile["bd"] = $r[0]["bd"];
if (isset($r[0]["thumb"]))
$profile["thumb"] = $r[0]["thumb"];
if ($r[0]["uid"] == 0)
$profile["cid"] = 0;
else
$profile["cid"] = $r[0]["id"];
} else
$profile["cid"] = 0;
// If there is more than one entry we filter out the connector networks
if (count($r) > 1)
foreach ($r AS $id => $result)
if ($result["network"] == NETWORK_STATUSNET)
unset($r[$id]);
$profile = array_shift($r);
// "bd" always contains the upcoming birthday of a contact.
// "birthday" might contain the birthday including the year of birth.
if ($profile["birthday"] != "0000-00-00") {
$bd_timestamp = strtotime($profile["birthday"]);
$month = date("m", $bd_timestamp);
$day = date("d", $bd_timestamp);
$current_timestamp = time();
$current_year = date("Y", $current_timestamp);
$current_month = date("m", $current_timestamp);
$current_day = date("d", $current_timestamp);
$profile["bd"] = $current_year."-".$month."-".$day;
$current = $current_year."-".$current_month."-".$current_day;
if ($profile["bd"] < $current)
$profile["bd"] = (++$current_year)."-".$month."-".$day;
} else
$profile["bd"] = "0000-00-00";
} else
$profile = $default;
if (($profile["photo"] == "") AND isset($default["photo"]))
$profile["photo"] = $default["photo"];
if (($profile["name"] == "") AND isset($default["name"]))
$profile["name"] = $default["name"];
if (($profile["network"] == "") AND isset($default["network"]))
$profile["network"] = $default["network"];
if (($profile["thumb"] == "") AND isset($profile["photo"]))
$profile["thumb"] = $profile["photo"];
if (($profile["micro"] == "") AND isset($profile["thumb"]))
$profile["micro"] = $profile["thumb"];
if ((($profile["addr"] == "") OR ($profile["name"] == "")) AND ($profile["gid"] != 0) AND
in_array($profile["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS)))
proc_run(PRIORITY_LOW, "include/update_gcontact.php", $profile["gid"]);
// Show contact details of Diaspora contacts only if connected
if (($profile["cid"] == 0) AND ($profile["network"] == NETWORK_DIASPORA)) {
$profile["location"] = "";
$profile["about"] = "";
$profile["gender"] = "";
$profile["birthday"] = "0000-00-00";
}
return($profile);
@ -368,7 +393,7 @@ function random_profile() {
ORDER BY rand() LIMIT 1",
dbesc(NETWORK_DFRN));
if(dba::is_result($r))
if(dbm::is_result($r))
return dirname($r[0]['url']);
return '';
}
@ -438,9 +463,19 @@ function get_contact($url, $uid = 0) {
$data = probe_url($url);
// Does this address belongs to a valid network?
if (!in_array($data["network"], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA)))
if (!in_array($data["network"], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA))) {
if ($uid != 0)
return 0;
// Get data from the gcontact table
$r = q("SELECT `name`, `nick`, `url`, `photo`, `addr`, `alias`, `network` FROM `gcontact` WHERE `nurl` = '%s'",
dbesc(normalise_link($url)));
if (!$r)
return 0;
$data = $r[0];
}
$url = $data["url"];
if ($contactid == 0) {
@ -477,6 +512,16 @@ function get_contact($url, $uid = 0) {
return 0;
$contactid = $contact[0]["id"];
// Update the newly created contact from data in the gcontact table
$r = q("SELECT `location`, `about`, `keywords`, `gender` FROM `gcontact` WHERE `nurl` = '%s'",
dbesc(normalise_link($data["url"])));
if ($r) {
logger("Update contact ".$data["url"]);
q("UPDATE `contact` SET `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s' WHERE `id` = %d",
dbesc($r["location"]), dbesc($r["about"]), dbesc($r["keywords"]),
dbesc($r["gender"]), intval($contactid));
}
}
if ((count($contact) > 1) AND ($uid == 0) AND ($contactid != 0) AND ($url != ""))
@ -586,11 +631,11 @@ function posts_from_contact($a, $contact_id) {
$r = q("SELECT `item`.`uri`, `item`.*, `item`.`id` AS `item_id`,
`author-name` AS `name`, `owner-avatar` AS `photo`,
`owner-link` AS `url`, `owner-avatar` AS `thumb`
FROM `item` FORCE INDEX (`uid_contactid_created`)
FROM `item` FORCE INDEX (`uid_contactid_id`)
WHERE `item`.`uid` = %d AND `contact-id` = %d
AND `author-link` IN ('%s', '%s')
AND NOT `deleted` AND NOT `moderated` AND `visible`
ORDER BY `item`.`created` DESC LIMIT %d, %d",
ORDER BY `item`.`id` DESC LIMIT %d, %d",
intval(local_user()),
intval($contact_id),
dbesc(str_replace("https://", "http://", $contact["url"])),

236
include/Core/Config.php Normal file
View file

@ -0,0 +1,236 @@
<?php
namespace Friendica\Core;
/**
* @file include/Core/Config.php
*
* @brief Contains the class with methods for system configuration
*/
/**
* @brief Arbitrary sytem configuration storage
* Note:
* Please do not store booleans - convert to 0/1 integer values
* The Config::get() functions return boolean false for keys that are unset,
* and this could lead to subtle bugs.
*
* There are a few places in the code (such as the admin panel) where boolean
* configurations need to be fixed as of 10/08/2011.
*/
class Config {
/**
* @brief Loads all configuration values of family into a cached storage.
*
* All configuration values of the system are stored in global cache
* which is available under the global variable $a->config
*
* @param string $family
* The category of the configuration value
* @return void
*/
public static function load($family) {
global $a;
$r = q("SELECT `v`, `k` FROM `config` WHERE `cat` = '%s'", dbesc($family));
if(count($r)) {
foreach($r as $rr) {
$k = $rr['k'];
if ($family === 'config') {
$a->config[$k] = $rr['v'];
} else {
$a->config[$family][$k] = $rr['v'];
}
}
} else if ($family != 'config') {
// Negative caching
$a->config[$family] = "!<unset>!";
}
}
/**
* @brief Get a particular user's config variable given the category name
* ($family) and a key.
*
* Get a particular config value from the given category ($family)
* and the $key from a cached storage in $a->config[$uid].
* $instore is only used by the set_config function
* to determine if the key already exists in the DB
* If a key is found in the DB but doesn't exist in
* local config cache, pull it into the cache so we don't have
* to hit the DB again for this item.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @param mixed $default_value optional
* The value to return if key is not set (default: null)
* @param boolean $refresh optional
* If true the config is loaded from the db and not from the cache (default: false)
* @return mixed Stored value or null if it does not exist
*/
public static function get($family, $key, $default_value=null, $refresh = false) {
global $a;
if(! $instore) {
// Looking if the whole family isn't set
if(isset($a->config[$family])) {
if($a->config[$family] === '!<unset>!') {
return $default_value;
}
}
if(isset($a->config[$family][$key])) {
if($a->config[$family][$key] === '!<unset>!') {
return $default_value;
}
return $a->config[$family][$key];
}
}
// If APC is enabled then fetch the data from there, else try XCache
/*if (function_exists("apc_fetch") AND function_exists("apc_exists"))
if (apc_exists($family."|".$key)) {
$val = apc_fetch($family."|".$key);
$a->config[$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}
elseif (function_exists("xcache_fetch") AND function_exists("xcache_isset"))
if (xcache_isset($family."|".$key)) {
$val = xcache_fetch($family."|".$key);
$a->config[$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}
*/
$ret = q("SELECT `v` FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
dbesc($family),
dbesc($key)
);
if(count($ret)) {
// manage array value
$val = (preg_match("|^a:[0-9]+:{.*}$|s", $ret[0]['v'])?unserialize( $ret[0]['v']):$ret[0]['v']);
$a->config[$family][$key] = $val;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($family."|".$key, $val, 600);
elseif (function_exists("xcache_set"))
xcache_set($family."|".$key, $val, 600);*/
return $val;
}
else {
$a->config[$family][$key] = '!<unset>!';
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($family."|".$key, '!<unset>!', 600);
elseif (function_exists("xcache_set"))
xcache_set($family."|".$key, '!<unset>!', 600);*/
}
return $default_value;
}
/**
* @brief Sets a configuration value for system config
*
* Stores a config value ($value) in the category ($family) under the key ($key)
* for the user_id $uid.
*
* Note: Please do not store booleans - convert to 0/1 integer values!
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to set
* @param string $value
* The value to store
* @return mixed Stored $value or false if the database update failed
*/
public static function set($family,$key,$value) {
global $a;
// If $a->config[$family] has been previously set to '!<unset>!', then
// $a->config[$family][$key] will evaluate to $a->config[$family][0], and
// $a->config[$family][$key] = $value will be equivalent to
// $a->config[$family][0] = $value[0] (this causes infuriating bugs),
// so unset the family before assigning a value to a family's key
if($a->config[$family] === '!<unset>!')
unset($a->config[$family]);
// manage array value
$dbvalue = (is_array($value)?serialize($value):$value);
$dbvalue = (is_bool($dbvalue) ? intval($dbvalue) : $dbvalue);
if(is_null(self::get($family,$key,null,true))) {
$a->config[$family][$key] = $value;
$ret = q("INSERT INTO `config` ( `cat`, `k`, `v` ) VALUES ( '%s', '%s', '%s' ) ",
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
if($ret)
return $value;
return $ret;
}
$ret = q("UPDATE `config` SET `v` = '%s' WHERE `cat` = '%s' AND `k` = '%s'",
dbesc($dbvalue),
dbesc($family),
dbesc($key)
);
$a->config[$family][$key] = $value;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($family."|".$key, $value, 600);
elseif (function_exists("xcache_set"))
xcache_set($family."|".$key, $value, 600);*/
if($ret)
return $value;
return $ret;
}
/**
* @brief Deletes the given key from the system configuration.
*
* Removes the configured value from the stored cache in $a->config
* and removes it from the database.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to delete
* @return mixed
*/
public static function delete($family,$key) {
global $a;
if(x($a->config[$family],$key))
unset($a->config[$family][$key]);
$ret = q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s'",
dbesc($family),
dbesc($key)
);
// If APC is enabled then delete the data from there, else try XCache
/*if (function_exists("apc_delete"))
apc_delete($family."|".$key);
elseif (function_exists("xcache_unset"))
xcache_unset($family."|".$key);*/
return $ret;
}
}

222
include/Core/PConfig.php Normal file
View file

@ -0,0 +1,222 @@
<?php
namespace Friendica\Core;
/**
* @file include/Core/PConfig.php
* @brief contains the class with methods for the management
* of the user configuration
*/
/**
* @brief Management of user configuration storage
* Note:
* Please do not store booleans - convert to 0/1 integer values
* The PConfig::get() functions return boolean false for keys that are unset,
* and this could lead to subtle bugs.
*/
class PConfig {
/**
* @brief Loads all configuration values of a user's config family into a cached storage.
*
* All configuration values of the given user are stored in global cache
* which is available under the global variable $a->config[$uid].
*
* @param string $uid
* The user_id
* @param string $family
* The category of the configuration value
* @return void
*/
public static function load($uid,$family) {
global $a;
$r = q("SELECT `v`,`k` FROM `pconfig` WHERE `cat` = '%s' AND `uid` = %d",
dbesc($family),
intval($uid)
);
if(count($r)) {
foreach($r as $rr) {
$k = $rr['k'];
$a->config[$uid][$family][$k] = $rr['v'];
}
} else if ($family != 'config') {
// Negative caching
$a->config[$uid][$family] = "!<unset>!";
}
}
/**
* @brief Get a particular user's config variable given the category name
* ($family) and a key.
*
* Get a particular user's config value from the given category ($family)
* and the $key from a cached storage in $a->config[$uid].
*
* @param string $uid
* The user_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @param mixed $default_value optional
* The value to return if key is not set (default: null)
* @param boolean $refresh optional
* If true the config is loaded from the db and not from the cache (default: false)
* @return mixed Stored value or null if it does not exist
*/
public static function get($uid, $family, $key, $default_value = null, $refresh = false) {
global $a;
if(! $instore) {
// Looking if the whole family isn't set
if(isset($a->config[$uid][$family])) {
if($a->config[$uid][$family] === '!<unset>!') {
return $default_value;
}
}
if(isset($a->config[$uid][$family][$key])) {
if($a->config[$uid][$family][$key] === '!<unset>!') {
return $default_value;
}
return $a->config[$uid][$family][$key];
}
}
// If APC is enabled then fetch the data from there, else try XCache
/*if (function_exists("apc_fetch") AND function_exists("apc_exists"))
if (apc_exists($uid."|".$family."|".$key)) {
$val = apc_fetch($uid."|".$family."|".$key);
$a->config[$uid][$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}
elseif (function_exists("xcache_get") AND function_exists("xcache_isset"))
if (xcache_isset($uid."|".$family."|".$key)) {
$val = xcache_get($uid."|".$family."|".$key);
$a->config[$uid][$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}*/
$ret = q("SELECT `v` FROM `pconfig` WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s' LIMIT 1",
intval($uid),
dbesc($family),
dbesc($key)
);
if(count($ret)) {
$val = (preg_match("|^a:[0-9]+:{.*}$|s", $ret[0]['v'])?unserialize( $ret[0]['v']):$ret[0]['v']);
$a->config[$uid][$family][$key] = $val;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($uid."|".$family."|".$key, $val, 600);
elseif (function_exists("xcache_set"))
xcache_set($uid."|".$family."|".$key, $val, 600);*/
return $val;
}
else {
$a->config[$uid][$family][$key] = '!<unset>!';
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($uid."|".$family."|".$key, '!<unset>!', 600);
elseif (function_exists("xcache_set"))
xcache_set($uid."|".$family."|".$key, '!<unset>!', 600);*/
}
return $default_value;
}
/**
* @brief Sets a configuration value for a user
*
* Stores a config value ($value) in the category ($family) under the key ($key)
* for the user_id $uid.
*
* @note Please do not store booleans - convert to 0/1 integer values!
*
* @param string $uid
* The user_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to set
* @param string $value
* The value to store
* @return mixed Stored $value or false
*/
public static function set($uid,$family,$key,$value) {
global $a;
// manage array value
$dbvalue = (is_array($value)?serialize($value):$value);
if(is_null(self::get($uid,$family,$key,null, true))) {
$a->config[$uid][$family][$key] = $value;
$ret = q("INSERT INTO `pconfig` ( `uid`, `cat`, `k`, `v` ) VALUES ( %d, '%s', '%s', '%s' ) ",
intval($uid),
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
if($ret)
return $value;
return $ret;
}
$ret = q("UPDATE `pconfig` SET `v` = '%s' WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s'",
dbesc($dbvalue),
intval($uid),
dbesc($family),
dbesc($key)
);
$a->config[$uid][$family][$key] = $value;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($uid."|".$family."|".$key, $value, 600);
elseif (function_exists("xcache_set"))
xcache_set($uid."|".$family."|".$key, $value, 600);*/
if($ret)
return $value;
return $ret;
}
/**
* @brief Deletes the given key from the users's configuration.
*
* Removes the configured value from the stored cache in $a->config[$uid]
* and removes it from the database.
*
* @param string $uid The user_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to delete
* @return mixed
*/
public static function delete($uid,$family,$key) {
global $a;
if(x($a->config[$uid][$family],$key))
unset($a->config[$uid][$family][$key]);
$ret = q("DELETE FROM `pconfig` WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s'",
intval($uid),
dbesc($family),
dbesc($key)
);
return $ret;
}
}

View file

@ -30,8 +30,8 @@ class Emailer {
// generate a mime boundary
$mimeBoundary =rand(0,9)."-"
.rand(10000000000,99999999999)."-"
.rand(10000000000,99999999999)."=:"
.rand(100000000,999999999)."-"
.rand(100000000,999999999)."=:"
.rand(10000,99999);
// generate a multipart/alternative message header

View file

@ -26,6 +26,7 @@ class ForumManager {
* 'name' => forum name
* 'id' => number of the key from the array
* 'micro' => contact photo in format micro
* 'thumb' => contact photo in format thumb
*/
public static function get_list($uid, $showhidden = true, $lastitem, $showprivate = false) {
@ -38,7 +39,7 @@ class ForumManager {
$select = '(`forum` OR `prv`)';
}
$contacts = q("SELECT `contact`.`id`, `contact`.`url`, `contact`.`name`, `contact`.`micro` FROM `contact`
$contacts = q("SELECT `contact`.`id`, `contact`.`url`, `contact`.`name`, `contact`.`micro`, `contact`.`thumb` FROM `contact`
WHERE `network`= 'dfrn' AND $select AND `uid` = %d
AND NOT `blocked` AND NOT `hidden` AND NOT `pending` AND NOT `archive`
AND `success_update` > `failure_update`
@ -55,6 +56,7 @@ class ForumManager {
'name' => $contact['name'],
'id' => $contact['id'],
'micro' => $contact['micro'],
'thumb' => $contact['thumb'],
);
}
return($forumlist);
@ -86,7 +88,7 @@ class ForumManager {
$total = count($contacts);
$visible_forums = 10;
if(dba::is_result($contacts)) {
if(dbm::is_result($contacts)) {
$id = 0;

View file

@ -1,13 +1,16 @@
<?php
/**
* @file include/NotificationsManager.php
* @brief Methods for read and write notifications from/to database
* or for formatting notifications
*/
require_once('include/html2plain.php');
require_once("include/datetime.php");
require_once("include/bbcode.php");
/**
* @brief Read and write notifications from/to database
* @brief Methods for read and write notifications from/to database
* or for formatting notifications
*/
class NotificationsManager {
private $a;
@ -44,7 +47,7 @@ class NotificationsManager {
/**
* @brief get all notifications for local_user()
* @brief Get all notifications for local_user()
*
* @param array $filter optional Array "column name"=>value: filter query by columns values
* @param string $order optional Space separated list of column to sort by. prepend name with "+" to sort ASC, "-" to sort DESC. Default to "-date"
@ -78,17 +81,21 @@ class NotificationsManager {
}
$order_sql = implode(", ", $asOrder);
if ($limit!="") $limit = " LIMIT ".$limit;
if($limit!="")
$limit = " LIMIT ".$limit;
$r = q("SELECT * FROM `notify` WHERE `uid` = %d $filter_sql ORDER BY $order_sql $limit",
intval(local_user())
);
if ($r!==false && count($r)>0) return $this->_set_extra($r);
if(dbm::is_result($r))
return $this->_set_extra($r);
return false;
}
/**
* @brief get one note for local_user() by $id value
* @brief Get one note for local_user() by $id value
*
* @param int $id
* @return array note values or null if not found
@ -98,7 +105,7 @@ class NotificationsManager {
intval($id),
intval(local_user())
);
if($r!==false && count($r)>0) {
if(dbm::is_result($r)) {
return $this->_set_extra($r)[0];
}
return null;
@ -133,4 +140,671 @@ class NotificationsManager {
intval(local_user())
);
}
/**
* @brief List of pages for the Notifications TabBar
*
* @param app $a The
* @return array with with notifications TabBar data
*/
public function getTabs() {
$tabs = array(
array(
'label' => t('System'),
'url'=>'notifications/system',
'sel'=> (($this->a->argv[1] == 'system') ? 'active' : ''),
'id' => 'system-tab',
'accesskey' => 'y',
),
array(
'label' => t('Network'),
'url'=>'notifications/network',
'sel'=> (($this->a->argv[1] == 'network') ? 'active' : ''),
'id' => 'network-tab',
'accesskey' => 'w',
),
array(
'label' => t('Personal'),
'url'=>'notifications/personal',
'sel'=> (($this->a->argv[1] == 'personal') ? 'active' : ''),
'id' => 'personal-tab',
'accesskey' => 'r',
),
array(
'label' => t('Home'),
'url' => 'notifications/home',
'sel'=> (($this->a->argv[1] == 'home') ? 'active' : ''),
'id' => 'home-tab',
'accesskey' => 'h',
),
array(
'label' => t('Introductions'),
'url' => 'notifications/intros',
'sel'=> (($this->a->argv[1] == 'intros') ? 'active' : ''),
'id' => 'intro-tab',
'accesskey' => 'i',
),
);
return $tabs;
}
/**
* @brief Format the notification query in an usable array
*
* @param array $notifs The array from the db query
* @param string $ident The notifications identifier (e.g. network)
* @return array
* string 'label' => The type of the notification
* string 'link' => URL to the source
* string 'image' => The avatar image
* string 'text' => The notification text
* string 'when' => Relative date of the notification
* bool 'seen' => Is the notification marked as "seen"
*/
private function formatNotifs($notifs, $ident = "") {
$notif = array();
$arr = array();
if (dbm::is_result($notifs)) {
foreach ($notifs as $it) {
// Because we use different db tables for the notification query
// we have sometimes $it['unseen'] and sometimes $it['seen].
// So we will have to transform $it['unseen']
if($it['unseen'])
$it['seen'] = ($it['unseen'] > 0 ? false : true);
// Depending on the identifier of the notification we need to use different defaults
switch ($ident) {
case 'system':
$default_item_label = 'notify';
$default_item_link = $this->a->get_baseurl(true).'/notify/view/'. $it['id'];
$default_item_image = proxy_url($it['photo'], false, PROXY_SIZE_MICRO);
$default_item_text = strip_tags(bbcode($it['msg']));
$default_item_when = relative_date($it['date']);
$default_tpl = $tpl_notify;
break;
case 'home':
$default_item_label = 'comment';
$default_item_link = $this->a->get_baseurl(true).'/display/'.$it['pguid'];
$default_item_image = proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO);
$default_item_text = sprintf( t("%s commented on %s's post"), $it['author-name'], $it['pname']);
$default_item_when = relative_date($it['created']);
$default_tpl = $tpl_item_comments;
break;
default:
$default_item_label = (($it['id'] == $it['parent']) ? 'post' : 'comment');
$default_item_link = $this->a->get_baseurl(true).'/display/'.$it['pguid'];
$default_item_image = proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO);
$default_item_text = (($it['id'] == $it['parent'])
? sprintf( t("%s created a new post"), $it['author-name'])
: sprintf( t("%s commented on %s's post"), $it['author-name'], $it['pname']));
$default_item_when = relative_date($it['created']);
$default_tpl = (($it['id'] == $it['parent']) ? $tpl_item_posts : $tpl_item_comments);
}
// Transform the different types of notification in an usable array
switch($it['verb']){
case ACTIVITY_LIKE:
$notif = array(
'label' => 'like',
'link' => $this->a->get_baseurl(true).'/display/'.$it['pguid'],
'$image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
'text' => sprintf( t("%s liked %s's post"), $it['author-name'], $it['pname']),
'when' => relative_date($it['created']),
'seen' => $it['seen']
);
break;
case ACTIVITY_DISLIKE:
$notif = array(
'label' => 'dislike',
'link' => $this->a->get_baseurl(true).'/display/'.$it['pguid'],
'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
'text' => sprintf( t("%s disliked %s's post"), $it['author-name'], $it['pname']),
'when' => relative_date($it['created']),
'seen' => $it['seen']
);
break;
case ACTIVITY_ATTEND:
$notif = array(
'label' => 'attend',
'link' => $this->a->get_baseurl(true).'/display/'.$it['pguid'],
'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
'text' => sprintf( t("%s is attending %s's event"), $it['author-name'], $it['pname']),
'when' => relative_date($it['created']),
'seen' => $it['seen']
);
break;
case ACTIVITY_ATTENDNO:
$notif = array(
'label' => 'attendno',
'link' => $this->a->get_baseurl(true).'/display/'.$it['pguid'],
'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
'text' => sprintf( t("%s is not attending %s's event"), $it['author-name'], $it['pname']),
'when' => relative_date($it['created']),
'seen' => $it['seen']
);
break;
case ACTIVITY_ATTENDMAYBE:
$notif = array(
'label' => 'attendmaybe',
'link' => $this->a->get_baseurl(true).'/display/'.$it['pguid'],
'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
'text' => sprintf( t("%s may attend %s's event"), $it['author-name'], $it['pname']),
'when' => relative_date($it['created']),
'seen' => $it['seen']
);
break;
case ACTIVITY_FRIEND:
$xmlhead="<"."?xml version='1.0' encoding='UTF-8' ?".">";
$obj = parse_xml_string($xmlhead.$it['object']);
$it['fname'] = $obj->title;
$notif = array(
'label' => 'friend',
'link' => $this->a->get_baseurl(true).'/display/'.$it['pguid'],
'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO),
'text' => sprintf( t("%s is now friends with %s"), $it['author-name'], $it['fname']),
'when' => relative_date($it['created']),
'seen' => $it['seen']
);
break;
default:
$notif = array(
'label' => $default_item_label,
'link' => $default_item_link,
'image' => $default_item_image,
'text' => $default_item_text,
'when' => $default_item_when,
'seen' => $it['seen']
);
}
$arr[] = $notif;
}
}
return $arr;
}
/**
* @brief Total number of network notifications
* @param int|string $seen
* If 0 only include notifications into the query
* which aren't marked as "seen"
* @return int Number of network notifications
*/
private function networkTotal($seen = 0) {
$sql_seen = "";
if($seen === 0)
$sql_seen = " AND `item`.`unseen` = 1 ";
$r = q("SELECT COUNT(*) AS `total`
FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent`
WHERE `item`.`visible` = 1 AND `pitem`.`parent` != 0 AND
`item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0
$sql_seen",
intval(local_user())
);
if(dbm::is_result($r))
return $r[0]['total'];
return 0;
}
/**
* @brief Get network notifications
*
* @param int|string $seen
* If 0 only include notifications into the query
* which aren't marked as "seen"
* @param int $start Start the query at this point
* @param int $limit Maximum number of query results
*
* @return array with
* string 'ident' => Notification identifier
* int 'total' => Total number of available network notifications
* array 'notifications' => Network notifications
*/
public function networkNotifs($seen = 0, $start = 0, $limit = 80) {
$ident = 'network';
$total = $this->networkTotal($seen);
$notifs = array();
$sql_seen = "";
if($seen === 0)
$sql_seen = " AND `item`.`unseen` = 1 ";
$r = q("SELECT `item`.`id`,`item`.`parent`, `item`.`verb`, `item`.`author-name`, `item`.`unseen`,
`item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object` AS `object`,
`pitem`.`author-name` AS `pname`, `pitem`.`author-link` AS `plink`, `pitem`.`guid` AS `pguid`
FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent`
WHERE `item`.`visible` = 1 AND `pitem`.`parent` != 0 AND
`item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0
$sql_seen
ORDER BY `item`.`created` DESC LIMIT %d, %d ",
intval(local_user()),
intval($start),
intval($limit)
);
if(dbm::is_result($r))
$notifs = $this->formatNotifs($r, $ident);
$arr = array (
'notifications' => $notifs,
'ident' => $ident,
'total' => $total,
);
return $arr;
}
/**
* @brief Total number of system notifications
* @param int|string $seen
* If 0 only include notifications into the query
* which aren't marked as "seen"
* @return int Number of system notifications
*/
private function systemTotal($seen = 0) {
$sql_seen = "";
if($seen === 0)
$sql_seen = " AND `seen` = 0 ";
$r = q("SELECT COUNT(*) AS `total` FROM `notify` WHERE `uid` = %d $sql_seen",
intval(local_user())
);
if(dbm::is_result($r))
return $r[0]['total'];
return 0;
}
/**
* @brief Get system notifications
*
* @param int|string $seen
* If 0 only include notifications into the query
* which aren't marked as "seen"
* @param int $start Start the query at this point
* @param int $limit Maximum number of query results
*
* @return array with
* string 'ident' => Notification identifier
* int 'total' => Total number of available system notifications
* array 'notifications' => System notifications
*/
public function systemNotifs($seen = 0, $start = 0, $limit = 80) {
$ident = 'system';
$total = $this->systemTotal($seen);
$notifs = array();
$sql_seen = "";
if($seen === 0)
$sql_seen = " AND `seen` = 0 ";
$r = q("SELECT `id`, `photo`, `msg`, `date`, `seen` FROM `notify`
WHERE `uid` = %d $sql_seen ORDER BY `date` DESC LIMIT %d, %d ",
intval(local_user()),
intval($start),
intval($limit)
);
if(dbm::is_result($r))
$notifs = $this->formatNotifs($r, $ident);
$arr = array (
'notifications' => $notifs,
'ident' => $ident,
'total' => $total,
);
return $arr;
}
/**
* @brief Addional SQL query string for the personal notifications
*
* @return string The additional sql query
*/
private function _personal_sql_extra() {
$myurl = $this->a->get_baseurl(true) . '/profile/'. $this->a->user['nickname'];
$myurl = substr($myurl,strpos($myurl,'://')+3);
$myurl = str_replace(array('www.','.'),array('','\\.'),$myurl);
$diasp_url = str_replace('/profile/','/u/',$myurl);
$sql_extra = sprintf(" AND ( `item`.`author-link` regexp '%s' or `item`.`tag` regexp '%s' or `item`.`tag` regexp '%s' ) ",
dbesc($myurl . '$'),
dbesc($myurl . '\\]'),
dbesc($diasp_url . '\\]')
);
return $sql_extra;
}
/**
* @brief Total number of personal notifications
* @param int|string $seen
* If 0 only include notifications into the query
* which aren't marked as "seen"
* @return int Number of personal notifications
*/
private function personalTotal($seen = 0) {
$sql_seen = "";
$sql_extra = $this->_personal_sql_extra();
if($seen === 0)
$sql_seen = " AND `item`.`unseen` = 1 ";
$r = q("SELECT COUNT(*) AS `total`
FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent`
WHERE `item`.`visible` = 1
$sql_extra
$sql_seen
AND `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0 " ,
intval(local_user())
);
if(dbm::is_result($r))
return $r[0]['total'];
return 0;
}
/**
* @brief Get personal notifications
*
* @param int|string $seen
* If 0 only include notifications into the query
* which aren't marked as "seen"
* @param int $start Start the query at this point
* @param int $limit Maximum number of query results
*
* @return array with
* string 'ident' => Notification identifier
* int 'total' => Total number of available personal notifications
* array 'notifications' => Personal notifications
*/
public function personalNotifs($seen = 0, $start = 0, $limit = 80) {
$ident = 'personal';
$total = $this->personalTotal($seen);
$sql_extra = $this->_personal_sql_extra();
$notifs = array();
$sql_seen = "";
if($seen === 0)
$sql_seen = " AND `item`.`unseen` = 1 ";
$r = q("SELECT `item`.`id`,`item`.`parent`, `item`.`verb`, `item`.`author-name`, `item`.`unseen`,
`item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object` AS `object`,
`pitem`.`author-name` AS `pname`, `pitem`.`author-link` AS `plink`, `pitem`.`guid` AS `pguid`,
FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent`
WHERE `item`.`visible` = 1
$sql_extra
$sql_seen
AND `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0
ORDER BY `item`.`created` DESC LIMIT %d, %d " ,
intval(local_user()),
intval($start),
intval($limit)
);
if(dbm::is_result($r))
$notifs = $this->formatNotifs($r, $ident);
$arr = array (
'notifications' => $notifs,
'ident' => $ident,
'total' => $total,
);
return $arr;
}
/**
* @brief Total number of home notifications
* @param int|string $seen
* If 0 only include notifications into the query
* which aren't marked as "seen"
* @return int Number of home notifications
*/
private function homeTotal($seen = 0) {
$sql_seen = "";
if($seen === 0)
$sql_seen = " AND `item`.`unseen` = 1 ";
$r = q("SELECT COUNT(*) AS `total` FROM `item`
WHERE `item`.`visible` = 1 AND
`item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 1
$sql_seen",
intval(local_user())
);
if(dbm::is_result($r))
return $r[0]['total'];
return 0;
}
/**
* @brief Get home notifications
*
* @param int|string $seen
* If 0 only include notifications into the query
* which aren't marked as "seen"
* @param int $start Start the query at this point
* @param int $limit Maximum number of query results
*
* @return array with
* string 'ident' => Notification identifier
* int 'total' => Total number of available home notifications
* array 'notifications' => Home notifications
*/
public function homeNotifs($seen = 0, $start = 0, $limit = 80) {
$ident = 'home';
$total = $this->homeTotal($seen);
$notifs = array();
$sql_seen = "";
if($seen === 0)
$sql_seen = " AND `item`.`unseen` = 1 ";
$r = q("SELECT `item`.`id`,`item`.`parent`, `item`.`verb`, `item`.`author-name`, `item`.`unseen`,
`item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object` as `object`,
`pitem`.`author-name` as `pname`, `pitem`.`author-link` as `plink`, `pitem`.`guid` as `pguid`
FROM `item` INNER JOIN `item` as `pitem` ON `pitem`.`id`=`item`.`parent`
WHERE `item`.`visible` = 1 AND
`item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 1
$sql_seen
ORDER BY `item`.`created` DESC LIMIT %d, %d ",
intval(local_user()),
intval($start),
intval($limit)
);
if(dbm::is_result($r))
$notifs = $this->formatNotifs($r, $ident);
$arr = array (
'notifications' => $notifs,
'ident' => $ident,
'total' => $total,
);
return $arr;
}
/**
* @brief Total number of introductions
* @param bool $all
* If false only include introductions into the query
* which aren't marked as ignored
* @return int Number of introductions
*/
private function introTotal($all = false) {
$sql_extra = "";
if(!$all)
$sql_extra = " AND `ignore` = 0 ";
$r = q("SELECT COUNT(*) AS `total` FROM `intro`
WHERE `intro`.`uid` = %d $sql_extra AND `intro`.`blocked` = 0 ",
intval($_SESSION['uid'])
);
if(dbm::is_result($r))
return $r[0]['total'];
return 0;
}
/**
* @brief Get introductions
*
* @param bool $all
* If false only include introductions into the query
* which aren't marked as ignored
* @param int $start Start the query at this point
* @param int $limit Maximum number of query results
*
* @return array with
* string 'ident' => Notification identifier
* int 'total' => Total number of available introductions
* array 'notifications' => Introductions
*/
public function introNotifs($all = false, $start = 0, $limit = 80) {
$ident = 'introductions';
$total = $this->introTotal($seen);
$notifs = array();
$sql_extra = "";
if(!$all)
$sql_extra = " AND `ignore` = 0 ";
/// @todo Fetch contact details by "get_contact_details_by_url" instead of queries to contact, fcontact and gcontact
$r = q("SELECT `intro`.`id` AS `intro_id`, `intro`.*, `contact`.*, `fcontact`.`name` AS `fname`,`fcontact`.`url` AS `furl`,`fcontact`.`photo` AS `fphoto`,`fcontact`.`request` AS `frequest`,
`gcontact`.`location` AS `glocation`, `gcontact`.`about` AS `gabout`,
`gcontact`.`keywords` AS `gkeywords`, `gcontact`.`gender` AS `ggender`,
`gcontact`.`network` AS `gnetwork`
FROM `intro`
LEFT JOIN `contact` ON `contact`.`id` = `intro`.`contact-id`
LEFT JOIN `gcontact` ON `gcontact`.`nurl` = `contact`.`nurl`
LEFT JOIN `fcontact` ON `intro`.`fid` = `fcontact`.`id`
WHERE `intro`.`uid` = %d $sql_extra AND `intro`.`blocked` = 0
LIMIT %d, %d",
intval($_SESSION['uid']),
intval($start),
intval($limit)
);
if(dbm::is_result($r))
$notifs = $this->formatIntros($r);
$arr = array (
'ident' => $ident,
'total' => $total,
'notifications' => $notifs,
);
return $arr;
}
/**
* @brief Format the notification query in an usable array
*
* @param array $intros The array from the db query
* @return array with the introductions
*/
private function formatIntros($intros) {
$knowyou = '';
foreach($intros as $it) {
// There are two kind of introduction. Contacts suggested by other contacts and normal connection requests.
// We have to distinguish between these two because they use different data.
// Contact suggestions
if($it['fid']) {
$return_addr = bin2hex($this->a->user['nickname'] . '@' . $this->a->get_hostname() . (($this->a->path) ? '/' . $this->a->path : ''));
$intro = array(
'label' => 'friend_suggestion',
'notify_type' => t('Friend Suggestion'),
'intro_id' => $it['intro_id'],
'madeby' => $it['name'],
'contact_id' => $it['contact-id'],
'photo' => ((x($it,'fphoto')) ? proxy_url($it['fphoto'], false, PROXY_SIZE_SMALL) : "images/person-175.jpg"),
'name' => $it['fname'],
'url' => zrl($it['furl']),
'hidden' => $it['hidden'] == 1,
'post_newfriend' => (intval(get_pconfig(local_user(),'system','post_newfriend')) ? '1' : 0),
'knowyou' => $knowyou,
'note' => $it['note'],
'request' => $it['frequest'] . '?addr=' . $return_addr,
);
// Normal connection requests
} else {
// Probe the contact url to get missing data
$ret = probe_url($it["url"]);
if ($it['gnetwork'] == "")
$it['gnetwork'] = $ret["network"];
// Don't show these data until you are connected. Diaspora is doing the same.
if($it['gnetwork'] === NETWORK_DIASPORA) {
$it['glocation'] = "";
$it['gabout'] = "";
$it['ggender'] = "";
}
$intro = array(
'label' => (($it['network'] !== NETWORK_OSTATUS) ? 'friend_request' : 'follower'),
'notify_type' => (($it['network'] !== NETWORK_OSTATUS) ? t('Friend/Connect Request') : t('New Follower')),
'dfrn_id' => $it['issued-id'],
'uid' => $_SESSION['uid'],
'intro_id' => $it['intro_id'],
'contact_id' => $it['contact-id'],
'photo' => ((x($it,'photo')) ? proxy_url($it['photo'], false, PROXY_SIZE_SMALL) : "images/person-175.jpg"),
'name' => $it['name'],
'location' => bbcode($it['glocation'], false, false),
'about' => bbcode($it['gabout'], false, false),
'keywords' => $it['gkeywords'],
'gender' => $it['ggender'],
'hidden' => $it['hidden'] == 1,
'post_newfriend' => (intval(get_pconfig(local_user(),'system','post_newfriend')) ? '1' : 0),
'url' => $it['url'],
'zrl' => zrl($it['url']),
'addr' => $ret['addr'],
'network' => $it['gnetwork'],
'knowyou' => $it['knowyou'],
'note' => $it['note'],
);
}
$arr[] = $intro;
}
return $arr;
}
}

View file

@ -589,7 +589,7 @@ class Photo {
$r = q("select `guid` from photo where `resource-id` = '%s' and `guid` != '' limit 1",
dbesc($rid)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$guid = $r[0]['guid'];
else
$guid = get_guid();
@ -823,9 +823,12 @@ function get_photo_info($url) {
$data = Cache::get($url);
if (is_null($data)) {
$img_str = fetch_url($url, true, $redirects, 4);
// Unserialise to be able to check in the next step if the cached data is alright.
if (!is_null($data))
$data = unserialize($data);
if (is_null($data) OR !$data) {
$img_str = fetch_url($url, true, $redirects, 4);
$filesize = strlen($img_str);
if (function_exists("getimagesizefromstring"))
@ -846,8 +849,7 @@ function get_photo_info($url) {
$data["size"] = $filesize;
Cache::set($url, serialize($data));
} else
$data = unserialize($data);
}
return $data;
}

1124
include/Probe.php Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,335 +1,5 @@
<?php
require_once('library/HTML5/Parser.php');
require_once('include/crypto.php');
require_once('include/feed.php');
if(! function_exists('scrape_dfrn')) {
function scrape_dfrn($url, $dont_probe = false) {
$a = get_app();
$ret = array();
logger('scrape_dfrn: url=' . $url);
// Try to fetch the data from noscrape. This is faster than parsing the HTML
$noscrape = str_replace("/hcard/", "/noscrape/", $url);
$noscrapejson = fetch_url($noscrape);
$noscrapedata = array();
if ($noscrapejson) {
$noscrapedata = json_decode($noscrapejson, true);
if (is_array($noscrapedata)) {
if ($noscrapedata["nick"] != "")
return($noscrapedata);
else
unset($noscrapedata["nick"]);
} else
$noscrapedata = array();
}
$s = fetch_url($url);
if (!$s)
return $ret;
if (!$dont_probe) {
$probe = probe_url($url);
if (isset($probe["addr"]))
$ret["addr"] = $probe["addr"];
}
$headers = $a->get_curl_headers();
logger('scrape_dfrn: headers=' . $headers, LOGGER_DEBUG);
$lines = explode("\n",$headers);
if(count($lines)) {
foreach($lines as $line) {
// don't try and run feeds through the html5 parser
if(stristr($line,'content-type:') && ((stristr($line,'application/atom+xml')) || (stristr($line,'application/rss+xml'))))
return ret;
}
}
try {
$dom = HTML5_Parser::parse($s);
} catch (DOMException $e) {
logger('scrape_dfrn: parse error: ' . $e);
}
if(! $dom)
return $ret;
$items = $dom->getElementsByTagName('link');
// get DFRN link elements
foreach($items as $item) {
$x = $item->getAttribute('rel');
if(($x === 'alternate') && ($item->getAttribute('type') === 'application/atom+xml'))
$ret['feed_atom'] = $item->getAttribute('href');
if(substr($x,0,5) == "dfrn-") {
$ret[$x] = $item->getAttribute('href');
}
if($x === 'lrdd') {
$decoded = urldecode($item->getAttribute('href'));
if(preg_match('/acct:([^@]*)@/',$decoded,$matches))
$ret['nick'] = $matches[1];
}
}
// Pull out hCard profile elements
$largest_photo = 0;
$items = $dom->getElementsByTagName('*');
foreach($items as $item) {
if(attribute_contains($item->getAttribute('class'), 'vcard')) {
$level2 = $item->getElementsByTagName('*');
foreach($level2 as $x) {
if(attribute_contains($x->getAttribute('class'),'fn')) {
$ret['fn'] = $x->textContent;
}
if((attribute_contains($x->getAttribute('class'),'photo'))
|| (attribute_contains($x->getAttribute('class'),'avatar'))) {
$size = intval($x->getAttribute('width'));
// dfrn prefers 175, so if we find this, we set largest_size so it can't be topped.
if(($size > $largest_photo) || ($size == 175) || (! $largest_photo)) {
$ret['photo'] = $x->getAttribute('src');
$largest_photo = (($size == 175) ? 9999 : $size);
}
}
if(attribute_contains($x->getAttribute('class'),'key')) {
$ret['key'] = $x->textContent;
}
}
}
}
return array_merge($ret, $noscrapedata);
}}
if(! function_exists('validate_dfrn')) {
function validate_dfrn($a) {
$errors = 0;
if(! x($a,'key'))
$errors ++;
if(! x($a,'dfrn-request'))
$errors ++;
if(! x($a,'dfrn-confirm'))
$errors ++;
if(! x($a,'dfrn-notify'))
$errors ++;
if(! x($a,'dfrn-poll'))
$errors ++;
return $errors;
}}
if(! function_exists('scrape_meta')) {
function scrape_meta($url) {
$a = get_app();
$ret = array();
logger('scrape_meta: url=' . $url);
$s = fetch_url($url);
if(! $s)
return $ret;
$headers = $a->get_curl_headers();
logger('scrape_meta: headers=' . $headers, LOGGER_DEBUG);
$lines = explode("\n",$headers);
if(count($lines)) {
foreach($lines as $line) {
// don't try and run feeds through the html5 parser
if(stristr($line,'content-type:') && ((stristr($line,'application/atom+xml')) || (stristr($line,'application/rss+xml'))))
return ret;
}
}
try {
$dom = HTML5_Parser::parse($s);
} catch (DOMException $e) {
logger('scrape_meta: parse error: ' . $e);
}
if(! $dom)
return $ret;
$items = $dom->getElementsByTagName('meta');
// get DFRN link elements
foreach($items as $item) {
$x = $item->getAttribute('name');
if(substr($x,0,5) == "dfrn-")
$ret[$x] = $item->getAttribute('content');
}
return $ret;
}}
if(! function_exists('scrape_vcard')) {
function scrape_vcard($url) {
$a = get_app();
$ret = array();
logger('scrape_vcard: url=' . $url);
$s = fetch_url($url);
if(! $s)
return $ret;
$headers = $a->get_curl_headers();
$lines = explode("\n",$headers);
if(count($lines)) {
foreach($lines as $line) {
// don't try and run feeds through the html5 parser
if(stristr($line,'content-type:') && ((stristr($line,'application/atom+xml')) || (stristr($line,'application/rss+xml'))))
return ret;
}
}
try {
$dom = HTML5_Parser::parse($s);
} catch (DOMException $e) {
logger('scrape_vcard: parse error: ' . $e);
}
if(! $dom)
return $ret;
// Pull out hCard profile elements
$largest_photo = 0;
$items = $dom->getElementsByTagName('*');
foreach($items as $item) {
if(attribute_contains($item->getAttribute('class'), 'vcard')) {
$level2 = $item->getElementsByTagName('*');
foreach($level2 as $x) {
if(attribute_contains($x->getAttribute('class'),'fn'))
$ret['fn'] = $x->textContent;
if((attribute_contains($x->getAttribute('class'),'photo'))
|| (attribute_contains($x->getAttribute('class'),'avatar'))) {
$size = intval($x->getAttribute('width'));
if(($size > $largest_photo) || (! $largest_photo)) {
$ret['photo'] = $x->getAttribute('src');
$largest_photo = $size;
}
}
if((attribute_contains($x->getAttribute('class'),'nickname'))
|| (attribute_contains($x->getAttribute('class'),'uid'))) {
$ret['nick'] = $x->textContent;
}
}
}
}
return $ret;
}}
if(! function_exists('scrape_feed')) {
function scrape_feed($url) {
$a = get_app();
$ret = array();
$cookiejar = tempnam(get_temppath(), 'cookiejar-scrape-feed-');
$s = fetch_url($url, false, $redirects, 0, Null, $cookiejar);
unlink($cookiejar);
$headers = $a->get_curl_headers();
$code = $a->get_curl_code();
logger('scrape_feed: returns: ' . $code . ' headers=' . $headers, LOGGER_DEBUG);
if(! $s) {
logger('scrape_feed: no data returned for ' . $url);
return $ret;
}
$lines = explode("\n",$headers);
if(count($lines)) {
foreach($lines as $line) {
if(stristr($line,'content-type:')) {
if(stristr($line,'application/atom+xml') || stristr($s,'<feed')) {
$ret['feed_atom'] = $url;
return $ret;
}
if(stristr($line,'application/rss+xml') || stristr($s,'<rss')) {
$ret['feed_rss'] = $url;
return $ret;
}
}
}
// perhaps an RSS version 1 feed with a generic or incorrect content-type?
if(stristr($s,'</item>')) {
$ret['feed_rss'] = $url;
return $ret;
}
}
$basename = implode('/', array_slice(explode('/',$url),0,3)) . '/';
$doc = new DOMDocument();
@$doc->loadHTML($s);
$xpath = new DomXPath($doc);
$base = $xpath->query("//base");
foreach ($base as $node) {
$attr = array();
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
if ($attr["href"] != "")
$basename = $attr["href"] ;
}
$list = $xpath->query("//link");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
if (($attr["rel"] == "alternate") AND ($attr["type"] == "application/atom+xml"))
$ret["feed_atom"] = $attr["href"];
if (($attr["rel"] == "alternate") AND ($attr["type"] == "application/rss+xml"))
$ret["feed_rss"] = $attr["href"];
}
// Drupal and perhaps others only provide relative URLs. Turn them into absolute.
if(x($ret,'feed_atom') && (! strstr($ret['feed_atom'],'://')))
$ret['feed_atom'] = $basename . $ret['feed_atom'];
if(x($ret,'feed_rss') && (! strstr($ret['feed_rss'],'://')))
$ret['feed_rss'] = $basename . $ret['feed_rss'];
return $ret;
}}
require_once('include/Probe.php');
/**
*
@ -349,594 +19,17 @@ function scrape_feed($url) {
*
*/
define('PROBE_NORMAL', 0);
define('PROBE_DIASPORA', 1);
function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
require_once('include/email.php');
$result = array();
if (!$url)
return $result;
$result = Cache::get("probe_url:".$mode.":".$url);
if (!is_null($result)) {
$result = unserialize($result);
return $result;
}
$original_url = $url;
$network = null;
$diaspora = false;
$diaspora_base = '';
$diaspora_guid = '';
$diaspora_key = '';
$has_lrdd = false;
$email_conversant = false;
$connectornetworks = false;
$appnet = false;
if (strpos($url,'twitter.com')) {
$connectornetworks = true;
$network = NETWORK_TWITTER;
}
$lastfm = ((strpos($url,'last.fm/user') !== false) ? true : false);
$at_addr = ((strpos($url,'@') !== false) ? true : false);
if((!$appnet) && (!$lastfm) && !$connectornetworks) {
if(strpos($url,'mailto:') !== false && $at_addr) {
$url = str_replace('mailto:','',$url);
$links = array();
}
else
$links = lrdd($url);
if ((count($links) == 0) AND strstr($url, "/index.php")) {
$url = str_replace("/index.php", "", $url);
$links = lrdd($url);
}
if (count($links)) {
$has_lrdd = true;
logger('probe_url: found lrdd links: ' . print_r($links,true), LOGGER_DATA);
foreach($links as $link) {
if($link['@attributes']['rel'] === NAMESPACE_ZOT)
$zot = unamp($link['@attributes']['href']);
if($link['@attributes']['rel'] === NAMESPACE_DFRN)
$dfrn = unamp($link['@attributes']['href']);
if($link['@attributes']['rel'] === 'salmon')
$notify = unamp($link['@attributes']['href']);
if($link['@attributes']['rel'] === NAMESPACE_FEED)
$poll = unamp($link['@attributes']['href']);
if($link['@attributes']['rel'] === 'http://microformats.org/profile/hcard')
$hcard = unamp($link['@attributes']['href']);
if($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page')
$profile = unamp($link['@attributes']['href']);
if($link['@attributes']['rel'] === 'http://portablecontacts.net/spec/1.0')
$poco = unamp($link['@attributes']['href']);
if($link['@attributes']['rel'] === 'http://joindiaspora.com/seed_location') {
$diaspora_base = unamp($link['@attributes']['href']);
$diaspora = true;
}
if($link['@attributes']['rel'] === 'http://joindiaspora.com/guid') {
$diaspora_guid = unamp($link['@attributes']['href']);
$diaspora = true;
}
if($link['@attributes']['rel'] === 'diaspora-public-key') {
$diaspora_key = base64_decode(unamp($link['@attributes']['href']));
if(strstr($diaspora_key,'RSA '))
$pubkey = rsatopem($diaspora_key);
else
$pubkey = $diaspora_key;
$diaspora = true;
}
if(($link['@attributes']['rel'] === 'http://ostatus.org/schema/1.0/subscribe') AND ($mode == PROBE_NORMAL)) {
$diaspora = false;
}
}
// Status.Net can have more than one profile URL. We need to match the profile URL
// to a contact on incoming messages to prevent spam, and we won't know which one
// to match. So in case of two, one of them is stored as an alias. Only store URL's
// and not webfinger user@host aliases. If they've got more than two non-email style
// aliases, let's hope we're lucky and get one that matches the feed author-uri because
// otherwise we're screwed.
$backup_alias = "";
foreach($links as $link) {
if($link['@attributes']['rel'] === 'alias') {
if(strpos($link['@attributes']['href'],'@') === false) {
if(isset($profile)) {
$alias_url = $link['@attributes']['href'];
if(($alias_url !== $profile) AND ($backup_alias == "") AND
($alias_url !== str_replace("/index.php", "", $profile)))
$backup_alias = $alias_url;
if(($alias_url !== $profile) AND !strstr($alias_url, "index.php") AND
($alias_url !== str_replace("/index.php", "", $profile)))
$alias = $alias_url;
}
else
$profile = unamp($link['@attributes']['href']);
}
}
}
if ($alias == "")
$alias = $backup_alias;
// If the profile is different from the url then the url is abviously an alias
if (($alias == "") AND ($profile != "") AND !$at_addr AND (normalise_link($profile) != normalise_link($url)))
$alias = $url;
}
elseif($mode == PROBE_NORMAL) {
// Check email
$orig_url = $url;
if((strpos($orig_url,'@')) && validate_email($orig_url)) {
$x = q("SELECT `prvkey` FROM `user` WHERE `uid` = %d LIMIT 1",
intval(local_user())
);
$r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1",
intval(local_user())
);
if(count($x) && count($r)) {
$mailbox = construct_mailbox_name($r[0]);
$password = '';
openssl_private_decrypt(hex2bin($r[0]['pass']),$password,$x[0]['prvkey']);
$mbox = email_connect($mailbox,$r[0]['user'],$password);
if(! $mbox)
logger('probe_url: email_connect failed.');
unset($password);
}
if($mbox) {
$msgs = email_poll($mbox,$orig_url);
logger('probe_url: searching ' . $orig_url . ', ' . count($msgs) . ' messages found.', LOGGER_DEBUG);
if(count($msgs)) {
$addr = $orig_url;
$network = NETWORK_MAIL;
$name = substr($url,0,strpos($url,'@'));
$phost = substr($url,strpos($url,'@')+1);
$profile = 'http://' . $phost;
// fix nick character range
$vcard = array('fn' => $name, 'nick' => $name, 'photo' => avatar_img($url));
$notify = 'smtp ' . random_string();
$poll = 'email ' . random_string();
$priority = 0;
$x = email_msg_meta($mbox,$msgs[0]);
if(stristr($x[0]->from,$orig_url))
$adr = imap_rfc822_parse_adrlist($x[0]->from,'');
elseif(stristr($x[0]->to,$orig_url))
$adr = imap_rfc822_parse_adrlist($x[0]->to,'');
if(isset($adr)) {
foreach($adr as $feadr) {
if((strcasecmp($feadr->mailbox,$name) == 0)
&&(strcasecmp($feadr->host,$phost) == 0)
&& (strlen($feadr->personal))) {
$personal = imap_mime_header_decode($feadr->personal);
$vcard['fn'] = "";
foreach($personal as $perspart)
if ($perspart->charset != "default")
$vcard['fn'] .= iconv($perspart->charset, 'UTF-8//IGNORE', $perspart->text);
else
$vcard['fn'] .= $perspart->text;
$vcard['fn'] = notags($vcard['fn']);
}
}
}
}
imap_close($mbox);
}
}
}
}
if($mode == PROBE_NORMAL) {
if(strlen($zot)) {
$s = fetch_url($zot);
if($s) {
$j = json_decode($s);
if($j) {
$network = NETWORK_ZOT;
$vcard = array(
'fn' => $j->fullname,
'nick' => $j->nickname,
'photo' => $j->photo
);
$profile = $j->url;
$notify = $j->post;
$pubkey = $j->pubkey;
$poll = 'N/A';
}
}
}
if(strlen($dfrn)) {
$ret = scrape_dfrn(($hcard) ? $hcard : $dfrn, true);
if(is_array($ret) && x($ret,'dfrn-request')) {
$network = NETWORK_DFRN;
$request = $ret['dfrn-request'];
$confirm = $ret['dfrn-confirm'];
$notify = $ret['dfrn-notify'];
$poll = $ret['dfrn-poll'];
$vcard = array();
$vcard['fn'] = $ret['fn'];
$vcard['nick'] = $ret['nick'];
$vcard['photo'] = $ret['photo'];
}
}
}
// Scrape the public key from the hcard.
// Diaspora will remove it from the webfinger somewhere in the future.
if (($hcard != "") AND ($pubkey == "")) {
$ret = scrape_dfrn(($hcard) ? $hcard : $dfrn, true);
if (isset($ret["key"])) {
$hcard_key = $ret["key"];
if(strstr($hcard_key,'RSA '))
$pubkey = rsatopem($hcard_key);
else
$pubkey = $hcard_key;
}
}
if($diaspora && $diaspora_base && $diaspora_guid) {
$diaspora_notify = $diaspora_base.'receive/users/'.$diaspora_guid;
if($mode == PROBE_DIASPORA || !$notify || ($notify == $diaspora_notify)) {
$notify = $diaspora_notify;
$batch = $diaspora_base . 'receive/public' ;
}
if(strpos($url,'@'))
$addr = str_replace('acct:', '', $url);
}
if($network !== NETWORK_ZOT && $network !== NETWORK_DFRN && $network !== NETWORK_MAIL) {
if($diaspora)
if ($mode == PROBE_DIASPORA)
$network = NETWORK_DIASPORA;
elseif($has_lrdd AND ($notify))
$network = NETWORK_OSTATUS;
else
$network = "";
if(strpos($url,'@'))
$addr = str_replace('acct:', '', $url);
$data = Probe::uri($url, $network);
$priority = 0;
if($hcard && ! $vcard) {
$vcard = scrape_vcard($hcard);
// Google doesn't use absolute url in profile photos
if((x($vcard,'photo')) && substr($vcard['photo'],0,1) == '/') {
$h = @parse_url($hcard);
if($h)
$vcard['photo'] = $h['scheme'] . '://' . $h['host'] . $vcard['photo'];
}
logger('probe_url: scrape_vcard: ' . print_r($vcard,true), LOGGER_DATA);
}
if($diaspora && $addr) {
// Diaspora returns the name as the nick. As the nick will never be updated,
// let's use the Diaspora nickname (the first part of the handle) as the nick instead
$addr_parts = explode('@', $addr);
$vcard['nick'] = $addr_parts[0];
}
if($lastfm) {
$profile = $url;
$poll = str_replace(array('www.','last.fm/'),array('','ws.audioscrobbler.com/1.0/'),$url) . '/recenttracks.rss';
$vcard['nick'] = basename($url);
$vcard['fn'] = $vcard['nick'] . t(' on Last.fm');
$network = NETWORK_FEED;
}
if(! x($vcard,'fn'))
if(x($vcard,'nick'))
$vcard['fn'] = $vcard['nick'];
$check_feed = false;
if(stristr($url,'tumblr.com') && (! stristr($url,'/rss'))) {
$poll = $url . '/rss';
$check_feed = true;
// Will leave it to others to figure out how to grab the avatar, which is on the $url page in the open graph meta links
}
if($appnet || ! $poll)
$check_feed = true;
if((! isset($vcard)) || (! x($vcard,'fn')) || (! $profile))
$check_feed = true;
if(($at_addr) && (! count($links)))
$check_feed = false;
if ($connectornetworks)
$check_feed = false;
if($check_feed) {
$feedret = scrape_feed(($poll) ? $poll : $url);
logger('probe_url: scrape_feed ' . (($poll)? $poll : $url) . ' returns: ' . print_r($feedret,true), LOGGER_DATA);
if(count($feedret) && ($feedret['feed_atom'] || $feedret['feed_rss'])) {
$poll = ((x($feedret,'feed_atom')) ? unamp($feedret['feed_atom']) : unamp($feedret['feed_rss']));
if(! x($vcard))
$vcard = array();
}
if(x($feedret,'photo') && (! x($vcard,'photo')))
$vcard['photo'] = $feedret['photo'];
$cookiejar = tempnam(get_temppath(), 'cookiejar-scrape-feed-');
$xml = fetch_url($poll, false, $redirects, 0, Null, $cookiejar);
unlink($cookiejar);
logger('probe_url: fetch feed: ' . $poll . ' returns: ' . $xml, LOGGER_DATA);
if ($xml == "") {
logger("scrape_feed: XML is empty for feed ".$poll);
$network = NETWORK_PHANTOM;
} else {
$data = feed_import($xml,$dummy1,$dummy2, $dummy3, true);
if (!is_array($data)) {
logger("scrape_feed: This doesn't seem to be a feed: ".$poll);
$network = NETWORK_PHANTOM;
} else {
if (($vcard["photo"] == "") AND ($data["header"]["author-avatar"] != ""))
$vcard["photo"] = $data["header"]["author-avatar"];
if (($vcard["fn"] == "") AND ($data["header"]["author-name"] != ""))
$vcard["fn"] = $data["header"]["author-name"];
if (($vcard["nick"] == "") AND ($data["header"]["author-nick"] != ""))
$vcard["nick"] = $data["header"]["author-nick"];
if ($network == NETWORK_OSTATUS) {
if ($data["header"]["author-id"] != "")
$alias = $data["header"]["author-id"];
if ($data["header"]["author-link"] != "")
$profile = $data["header"]["author-link"];
} elseif(!$profile AND ($data["header"]["author-link"] != "") AND !in_array($network, array("", NETWORK_FEED)))
$profile = $data["header"]["author-link"];
}
}
// Workaround for misconfigured Friendica servers
if (($network == "") AND (strstr($url, "/profile/"))) {
$noscrape = str_replace("/profile/", "/noscrape/", $url);
$noscrapejson = fetch_url($noscrape);
if ($noscrapejson) {
$network = NETWORK_DFRN;
$poco = str_replace("/profile/", "/poco/", $url);
$noscrapedata = json_decode($noscrapejson, true);
if (isset($noscrapedata["addr"]))
$addr = $noscrapedata["addr"];
if (isset($noscrapedata["fn"]))
$vcard["fn"] = $noscrapedata["fn"];
if (isset($noscrapedata["key"]))
$pubkey = $noscrapedata["key"];
if (isset($noscrapedata["photo"]))
$vcard["photo"] = $noscrapedata["photo"];
if (isset($noscrapedata["dfrn-request"]))
$request = $noscrapedata["dfrn-request"];
if (isset($noscrapedata["dfrn-confirm"]))
$confirm = $noscrapedata["dfrn-confirm"];
if (isset($noscrapedata["dfrn-notify"]))
$notify = $noscrapedata["dfrn-notify"];
if (isset($noscrapedata["dfrn-poll"]))
$poll = $noscrapedata["dfrn-poll"];
}
}
if(! $network)
$network = NETWORK_FEED;
if(! x($vcard,'nick')) {
$vcard['nick'] = strtolower(notags(unxmlify($vcard['fn'])));
if(strpos($vcard['nick'],' '))
$vcard['nick'] = trim(substr($vcard['nick'],0,strpos($vcard['nick'],' ')));
}
if(! $priority)
$priority = 2;
}
}
if(! x($vcard,'photo')) {
$a = get_app();
$vcard['photo'] = App::get_baseurl() . '/images/person-175.jpg' ;
}
if(! $profile)
$profile = $url;
// No human could be associated with this link, use the URL as the contact name
if(($network === NETWORK_FEED) && ($poll) && (! x($vcard,'fn')))
$vcard['fn'] = $url;
if (($notify != "") AND ($poll != "")) {
$baseurl = matching_url(normalise_link($notify), normalise_link($poll));
$baseurl2 = matching_url($baseurl, normalise_link($profile));
if ($baseurl2 != "")
$baseurl = $baseurl2;
}
if (($baseurl == "") AND ($notify != ""))
$baseurl = matching_url(normalise_link($profile), normalise_link($notify));
if (($baseurl == "") AND ($poll != ""))
$baseurl = matching_url(normalise_link($profile), normalise_link($poll));
if (substr($baseurl, -10) == "/index.php")
$baseurl = str_replace("/index.php", "", $baseurl);
if ($network == "")
$network = NETWORK_PHANTOM;
$baseurl = rtrim($baseurl, "/");
if(strpos($url,'@') AND ($addr == "") AND ($network == NETWORK_DFRN))
$addr = str_replace('acct:', '', $url);
$vcard['fn'] = notags($vcard['fn']);
$vcard['nick'] = str_replace(' ','',notags($vcard['nick']));
$result['name'] = $vcard['fn'];
$result['nick'] = $vcard['nick'];
$result['url'] = $profile;
$result['addr'] = $addr;
$result['batch'] = $batch;
$result['notify'] = $notify;
$result['poll'] = $poll;
$result['request'] = $request;
$result['confirm'] = $confirm;
$result['poco'] = $poco;
$result['photo'] = $vcard['photo'];
$result['priority'] = $priority;
$result['network'] = $network;
$result['alias'] = $alias;
$result['pubkey'] = $pubkey;
$result['baseurl'] = $baseurl;
logger('probe_url: ' . print_r($result,true), LOGGER_DEBUG);
if ($level == 1) {
// Trying if it maybe a diaspora account
if (($result['network'] == NETWORK_FEED) OR ($result['addr'] == "")) {
require_once('include/bbcode.php');
$address = GetProfileUsername($url, "", true);
$result2 = probe_url($address, $mode, ++$level);
if ($result2['network'] != "")
$result = $result2;
}
// Maybe it's some non standard GNU Social installation (Single user, subfolder or no uri rewrite)
if (($result['network'] == NETWORK_FEED) AND ($result['baseurl'] != "") AND ($result['nick'] != "")) {
$addr = $result['nick'].'@'.str_replace("http://", "", $result['baseurl']);
$result2 = probe_url($addr, $mode, ++$level);
if (($result2['network'] != "") AND ($result2['network'] != NETWORK_FEED))
$result = $result2;
}
// Quickfix for Hubzilla systems with enabled OStatus plugin
if (($result['network'] == NETWORK_DIASPORA) AND ($result["batch"] == "")) {
$result2 = probe_url($url, PROBE_DIASPORA, ++$level);
if ($result2['network'] == NETWORK_DIASPORA) {
$addr = $result["addr"];
$result = $result2;
if (($result["addr"] == "") AND ($addr != ""))
$result["addr"] = $addr;
}
}
}
// Only store into the cache if the value seems to be valid
if ($result['network'] != NETWORK_PHANTOM) {
Cache::set("probe_url:".$mode.":".$original_url,serialize($result), CACHE_DAY);
/// @todo temporary fix - we need a real contact update function that updates only changing fields
/// The biggest problem is the avatar picture that could have a reduced image size.
/// It should only be updated if the existing picture isn't existing anymore.
if (($result['network'] != NETWORK_FEED) AND ($mode == PROBE_NORMAL) AND
$result["name"] AND $result["nick"] AND $result["url"] AND $result["addr"] AND $result["poll"])
q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `url` = '%s', `addr` = '%s',
`notify` = '%s', `poll` = '%s', `alias` = '%s', `success_update` = '%s'
WHERE `nurl` = '%s' AND NOT `self` AND `uid` = 0",
dbesc($result["name"]),
dbesc($result["nick"]),
dbesc($result["url"]),
dbesc($result["addr"]),
dbesc($result["notify"]),
dbesc($result["poll"]),
dbesc($result["alias"]),
dbesc(datetime_convert()),
dbesc(normalise_link($result['url']))
);
}
return $result;
}
/**
* @brief Find the matching part between two url
*
* @param string $url1
* @param string $url2
* @return string The matching part
*/
function matching_url($url1, $url2) {
if (($url1 == "") OR ($url2 == ""))
return "";
$url1 = normalise_link($url1);
$url2 = normalise_link($url2);
$parts1 = parse_url($url1);
$parts2 = parse_url($url2);
if (!isset($parts1["host"]) OR !isset($parts2["host"]))
return "";
if ($parts1["scheme"] != $parts2["scheme"])
return "";
if ($parts1["host"] != $parts2["host"])
return "";
if ($parts1["port"] != $parts2["port"])
return "";
$match = $parts1["scheme"]."://".$parts1["host"];
if ($parts1["port"])
$match .= ":".$parts1["port"];
$pathparts1 = explode("/", $parts1["path"]);
$pathparts2 = explode("/", $parts2["path"]);
$i = 0;
$path = "";
do {
$path1 = $pathparts1[$i];
$path2 = $pathparts2[$i];
if ($path1 == $path2)
$path .= $path1."/";
} while (($path1 == $path2) AND ($i++ <= count($pathparts1)));
$match .= $path;
return normalise_link($match);
return $data;
}

View file

@ -1,7 +1,8 @@
<?php
/**
* @file include/smilies.php
* @file include/Smilies.php
* @brief This file contains the Smilies class which contains functions to handle smiles
*/
/**
@ -63,41 +64,41 @@ class Smilies {
);
$icons = array(
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-heart.gif" alt="&lt;3" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-brokenheart.gif" alt="&lt;/3" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-brokenheart.gif" alt="&lt;\\3" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-smile.gif" alt=":-)" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-wink.gif" alt=";-)" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-frown.gif" alt=":-(" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-tongue-out.gif" alt=":-P" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-tongue-out.gif" alt=":-p" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-\"" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-\"" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-x" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-X" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-laughing.gif" alt=":-D" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-surprised.gif" alt="8-|" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-surprised.gif" alt="8-O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-surprised.gif" alt=":-O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-thumbsup.gif" alt="\\o/" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="o.O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="O.o" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="o_O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="O_o" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-cry.gif" alt=":\'(" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-foot-in-mouth.gif" alt=":-!" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-undecided.gif" alt=":-/" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-embarassed.gif" alt=":-[" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-cool.gif" alt="8-)" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/beer_mug.gif" alt=":beer" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/beer_mug.gif" alt=":homebrew" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/coffee.gif" alt=":coffee" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-facepalm.gif" alt=":facepalm" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/like.gif" alt=":like" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/dislike.gif" alt=":dislike" />',
'<a href="http://friendica.com">~friendica <img class="smiley" src="' . app::get_baseurl() . '/images/friendica-16.png" alt="~friendica" /></a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . app::get_baseurl() . '/images/rm-16.png" alt="red" />matrix</a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . app::get_baseurl() . '/images/rm-16.png" alt="red" />matrix</a>'
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-heart.gif" alt="&lt;3" title="&lt;3" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-brokenheart.gif" alt="&lt;/3" title="&lt;/3" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-brokenheart.gif" alt="&lt;\\3" title="&lt;\\3" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-smile.gif" alt=":-)" title=":-)" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-wink.gif" alt=";-)" title=";-)" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-frown.gif" alt=":-(" title=":-(" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-tongue-out.gif" alt=":-P" title=":-P" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-tongue-out.gif" alt=":-p" title=":-P" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-\" title=":-\" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-\" title=":-\" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-x" title=":-x" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-X" title=":-X" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-laughing.gif" alt=":-D" title=":-D" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-surprised.gif" alt="8-|" title="8-|" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-surprised.gif" alt="8-O" title="8-O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-surprised.gif" alt=":-O" title="8-O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-thumbsup.gif" alt="\\o/" title="\\o/" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="o.O" title="o.O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="O.o" title="O.o" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="o_O" title="o_O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="O_o" title="O_o" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-cry.gif" alt=":\'(" title=":\'("/>',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-foot-in-mouth.gif" alt=":-!" title=":-!" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-undecided.gif" alt=":-/" title=":-/" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-embarassed.gif" alt=":-[" title=":-[" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-cool.gif" alt="8-)" title="8-)" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/beer_mug.gif" alt=":beer" title=":beer" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/beer_mug.gif" alt=":homebrew" title=":homebrew" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/coffee.gif" alt=":coffee" title=":coffee" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-facepalm.gif" alt=":facepalm" title=":facepalm" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/like.gif" alt=":like" title=":like" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/dislike.gif" alt=":dislike" title=":dislike" />',
'<a href="http://friendica.com">~friendica <img class="smiley" src="' . app::get_baseurl() . '/images/friendica-16.png" alt="~friendica" title="~friendica" /></a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . app::get_baseurl() . '/images/rm-16.png" alt="red#" title="red#" />matrix</a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . app::get_baseurl() . '/images/rm-16.png" alt="red#matrix" title="red#matrix" />matrix</a>'
);
$params = array('texts' => $texts, 'icons' => $icons);

View file

@ -33,7 +33,7 @@ function group_select($selname,$selclass,$preselected = false,$size = 4) {
call_hooks($a->module . '_pre_' . $selname, $arr);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $rr) {
if((is_array($preselected)) && in_array($rr['id'], $preselected))
$selected = " selected=\"selected\" ";
@ -144,7 +144,7 @@ function contact_selector($selname, $selclass, $preselected = false, $options) {
call_hooks($a->module . '_pre_' . $selname, $arr);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $rr) {
if((is_array($preselected)) && in_array($rr['id'], $preselected))
$selected = " selected=\"selected\" ";
@ -220,7 +220,7 @@ function contact_select($selname, $selclass, $preselected = false, $size = 4, $p
$receiverlist = array();
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $rr) {
if((is_array($preselected)) && in_array($rr['id'], $preselected))
$selected = " selected=\"selected\" ";
@ -314,7 +314,7 @@ function populate_acl($user = null, $show_jotnets = false) {
$r = q("SELECT `pubmail` FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1",
intval(local_user())
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$mail_enabled = true;
if(intval($r[0]['pubmail']))
$pubmail_enabled = true;
@ -399,7 +399,7 @@ function acl_lookup(&$a, $out_type = 'json') {
$count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 100);
$search = (x($_REQUEST,'search') ? $_REQUEST['search'] : "");
$type = (x($_REQUEST,'type') ? $_REQUEST['type'] : "");
$mode = (x($_REQUEST,'mode') ? $_REQUEST['mode'] : "");
$mode = (x($_REQUEST,'smode') ? $_REQUEST['smode'] : "");
$conv_id = (x($_REQUEST,'conversation') ? $_REQUEST['conversation'] : null);
// For use with jquery.textcomplete for private mail completion
@ -481,11 +481,11 @@ function acl_lookup(&$a, $out_type = 'json') {
if ($type=='' || $type=='g'){
$r = q("SELECT `group`.`id`, `group`.`name`, GROUP_CONCAT(DISTINCT `group_member`.`contact-id` SEPARATOR ',') AS uids
FROM `group`,`group_member`
WHERE `group`.`deleted` = 0 AND `group`.`uid` = %d
AND `group_member`.`gid`=`group`.`id`
FROM `group`
INNER JOIN `group_member` ON `group_member`.`gid`=`group`.`id` AND `group_member`.`uid` = `group`.`uid`
WHERE NOT `group`.`deleted` AND `group`.`uid` = %d
$sql_extra
GROUP BY `group`.`id`
GROUP BY `group`.`name`
ORDER BY `group`.`name`
LIMIT %d,%d",
intval(local_user()),
@ -577,7 +577,7 @@ function acl_lookup(&$a, $out_type = 'json') {
$r = array();
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $g){
$contacts[] = array(
"type" => "c",
@ -612,7 +612,7 @@ function acl_lookup(&$a, $out_type = 'json') {
dbesc($search),
implode("','", $known_contacts)
);
if (dba::is_result($r)){
if (dbm::is_result($r)){
foreach($r as $row) {
// nickname..
$up = parse_url($row['author-link']);
@ -690,7 +690,7 @@ function navbar_complete(&$a) {
$localsearch = get_config('system','poco_local_search');
$search = $prefix.notags(trim($_REQUEST['search']));
$mode = $_REQUEST['mode'];
$mode = $_REQUEST['smode'];
// don't search if search term has less than 2 characters
if(! $search || mb_strlen($search) < 2)

File diff suppressed because it is too large Load diff

View file

@ -50,7 +50,7 @@ if (isset($_SESSION) && x($_SESSION,'authenticated') && (!x($_POST,'auth-params'
$r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1",
intval($_SESSION['visitor_id'])
);
if (dba::is_result($r)) {
if (dbm::is_result($r)) {
$a->contact = $r[0];
}
}
@ -169,7 +169,7 @@ if (isset($_SESSION) && x($_SESSION,'authenticated') && (!x($_POST,'auth-params'
dbesc(trim($_POST['username'])),
dbesc($encrypted)
);
if (dba::is_result($r))
if (dbm::is_result($r))
$record = $r[0];
}

View file

@ -75,7 +75,7 @@ class exAuth
public function __construct($sLogFile, $bDebug)
{
global $db;
global $a, $db;
// setter
$this->sLogFile = $sLogFile;
@ -135,25 +135,19 @@ class exAuth
} else {
// ovdje provjeri prijavu
$sUser = str_replace(array("%20", "(a)"), array(" ", "@"), $aCommand[1]);
$this->writeDebugLog("[debug] doing auth for ". $sUser);
$this->writeDebugLog("[debug] doing auth for ".$sUser."@".$aCommand[2]);
// If the hostnames doesn't match, we try to authenticate remotely
if ($a->get_hostname() != $aCommand[2])
$Error = !$this->check_credentials($aCommand[2], $aCommand[1], $aCommand[3], true);
else {
//$sQuery = "SELECT `uid`, `password` FROM `user` WHERE `password`='".hash('whirlpool',$aCommand[3])."' AND `nickname`='". $db->escape($sUser) ."'";
$sQuery = "SELECT `uid`, `password` FROM `user` WHERE `nickname`='". $db->escape($sUser) ."'";
$this->writeDebugLog("[debug] using query ". $sQuery);
if ($oResult = q($sQuery)){
$uid = $oResult[0]["uid"];
$Error = ($oResult[0]["password"] != hash('whirlpool',$aCommand[3]));
/*
if ($oResult[0]["password"] == hash('whirlpool',$aCommand[3])) {
// korisnik OK
$this->writeLog("[exAuth] authentificated user ". $sUser ."@". $aCommand[2]);
fwrite(STDOUT, pack("nn", 2, 1));
} else {
// korisnik nije OK
$this->writeLog("[exAuth] authentification failed for user ". $sUser ."@". $aCommand[2]);
fwrite(STDOUT, pack("nn", 2, 0));
}
$oResult->close();
*/
} else {
$this->writeLog("[MySQL] invalid query: ". $sQuery);
$Error = true;
@ -164,7 +158,7 @@ class exAuth
$this->writeLog("[exAuth] got password ".$oConfig[0]["v"]);
$Error = ($aCommand[3] != $oConfig[0]["v"]);
}
}
if ($Error) {
$this->writeLog("[exAuth] authentification failed for user ". $sUser ."@". $aCommand[2]);
fwrite(STDOUT, pack("nn", 2, 0));
@ -207,6 +201,27 @@ class exAuth
}
}
private function check_credentials($host, $user, $password, $ssl) {
$url = ($ssl ? "https":"http")."://".$host."/api/account/verify_credentials.json";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $user.':'.$password);
$header = curl_exec($ch);
$curl_info = @curl_getinfo($ch);
$http_code = $curl_info["http_code"];
curl_close($ch);
return($http_code == 200);
}
private function writeLog($sMessage)
{
if (is_resource($this->rLogFile)) {

View file

@ -6,4 +6,5 @@ $vendorDir = dirname(dirname(dirname(__FILE__)))."/library";
$baseDir = dirname($vendorDir);
return array(
'Friendica\\' => array($baseDir . '/include'),
);

View file

@ -34,7 +34,6 @@ function bb_map_location($match) {
function bb_attachment($Text, $simplehtml = false, $tryoembed = true) {
$data = get_attachment_data($Text);
if (!$data)
return $Text;
@ -85,7 +84,7 @@ function bb_attachment($Text, $simplehtml = false, $tryoembed = true) {
$text .= $oembed;
if (trim($data["description"]) != "")
$text .= sprintf('<blockquote>%s</blockquote></span>', trim($data["description"]));
$text .= sprintf('<blockquote>%s</blockquote></span>', trim(bbcode($data["description"])));
}
}
return $data["text"].$text.$data["after"];
@ -101,8 +100,14 @@ function bb_remove_share_information($Text, $plaintext = false, $nolink = false)
if ($nolink)
return $data["text"].$data["after"];
if ($plaintext)
$title = htmlentities($data["title"], ENT_QUOTES, 'UTF-8', false);
$text = htmlentities($data["text"], ENT_QUOTES, 'UTF-8', false);
if ($plaintext OR (($title != "") AND strstr($text, $title)))
$data["title"] = $data["url"];
elseif (($text != "") AND strstr($title, $text)) {
$data["text"] = $data["title"];
$data["title"] = $data["url"];
}
if (($data["text"] == "") AND ($data["title"] != "") AND ($data["url"] == ""))
return $data["title"].$data["after"];
@ -115,10 +120,10 @@ function bb_remove_share_information($Text, $plaintext = false, $nolink = false)
if (($data["url"] != "") AND ($data["title"] != ""))
$text .= "\n[url=".$data["url"]."]".$data["title"]."[/url]";
elseif (($link != ""))
elseif (($data["url"] != ""))
$text .= "\n".$data["url"];
return $text.$data["after"];
return $text."\n".$data["after"];
}
function bb_cleanstyle($st) {
@ -390,8 +395,6 @@ function bb_ShareAttributes($share, $simplehtml) {
$itemcache = get_itemcachepath();
// relative dates only make sense when they aren't cached
if ($itemcache == "") {
preg_match("/posted='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$posted = $matches[1];
@ -400,26 +403,32 @@ function bb_ShareAttributes($share, $simplehtml) {
if ($matches[1] != "")
$posted = $matches[1];
// relative dates only make sense when they aren't cached
if ($itemcache == "")
$reldate = (($posted) ? " " . relative_date($posted) : '');
}
// We only call this so that a previously unknown contact can be added.
// This is important for the function "get_contact_details_by_url".
// This function then can fetch an entry from the contact table.
get_contact($profile, 0);
$data = get_contact_details_by_url($profile);
if (isset($data["name"]) AND isset($data["addr"]))
if (isset($data["name"]) AND ($data["name"] != "") AND isset($data["addr"]) AND ($data["addr"] != ""))
$userid_compact = $data["name"]." (".$data["addr"].")";
else
$userid_compact = GetProfileUsername($profile,$author, true);
if (isset($data["addr"]))
if (isset($data["addr"]) AND ($data["addr"] != ""))
$userid = $data["addr"];
else
$userid = GetProfileUsername($profile,$author, false);
if (isset($data["name"]))
if (isset($data["name"]) AND ($data["name"] != ""))
$author = $data["name"];
if (isset($data["photo"]))
$avatar = $data["photo"];
if (isset($data["micro"]) AND ($data["micro"] != ""))
$avatar = $data["micro"];
$preshare = trim($share[1]);
@ -483,13 +492,22 @@ function bb_ShareAttributes($share, $simplehtml) {
$text .= "<br /><br />".$link;
break;
default:
$headline = trim($share[1]).'<div class="shared_header">';
if ($avatar != "")
$headline .= '<img src="'.proxy_url($avatar, false, PROXY_SIZE_MICRO).'" height="32" width="32" >';
$text = trim($share[1])."\n";
$headline .= sprintf(t('<span><a href="%s" target="_blank">%s</a> wrote the following <a href="%s" target="_blank">post</a>'.$reldate.':</span>'), $profile, $author, $link);
$headline .= "</div>";
$text = $headline.'<blockquote class="shared_content">'.trim($share[3])."</blockquote>";
$avatar = proxy_url($avatar, false, PROXY_SIZE_THUMB);
$tpl = get_markup_template('shared_content.tpl');
$text .= replace_macros($tpl,
array(
'$profile' => $profile,
'$avatar' => $avatar,
'$author' => $author,
'$link' => $link,
'$posted' => $posted,
'$reldate' => $reldate,
'$content' => trim($share[3])
)
);
break;
}
return($text);
@ -705,6 +723,13 @@ function bb_CleanPictureLinks($text) {
return ($text);
}
function bb_highlight($match) {
if(in_array(strtolower($match[1]),['php','css','mysql','sql','abap','diff','html','perl','ruby',
'vbscript','avrc','dtd','java','xml','cpp','python','javascript','js','sh']))
return text_highlight($match[2],strtolower($match[1]));
return $match[0];
}
// BBcode 2 HTML was written by WAY2WEB.net
// extended to work with Mistpark/Friendica - Mike Macgirvin
@ -757,6 +782,11 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
if (!$tryoembed)
$Text = preg_replace("/\[share(.*?)avatar\s?=\s?'.*?'\s?(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","\n[share$1$2]$3[/share]",$Text);
// Check for [code] text here, before the linefeeds are messed with.
// The highlighter will unescape and re-escape the content.
if (strpos($Text,'[code=') !== false) {
$Text = preg_replace_callback("/\[code=(.*?)\](.*?)\[\/code\]/ism", 'bb_highlight', $Text);
}
// Convert new line chars to html <br /> tags
// nlbr seems to be hopelessly messed up
@ -803,7 +833,10 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
$Text = preg_replace("/([@])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
'$1<span class="vcard"><a href="$2" class="url" title="$3"><span class="fn nickname mention">$3</span></a></span>',
$Text);
elseif (!$simplehtml)
$Text = preg_replace("/([@])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
'$1<a href="$2" class="userinfo mention" title="$3">$3</a>',
$Text);
// Bookmarks in red - will be converted to bookmarks in friendica
$Text = preg_replace("/#\^\[url\]([$URLSearchString]*)\[\/url\]/ism", '[bookmark=$1]$1[/bookmark]', $Text);
@ -845,6 +878,9 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
if ($tryoembed)
$Text = preg_replace_callback("/\[url\]([$URLSearchString]*)\[\/url\]/ism",'tryoembed',$Text);
$Text = preg_replace("/([#])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
'$1<a href="$2" class="tag" title="$3">$3</a>', $Text);
$Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '<a href="$1" target="_blank">$1</a>', $Text);
$Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1" target="_blank">$2</a>', $Text);
//$Text = preg_replace("/\[url\=([$URLSearchString]*)\]([$URLSearchString]*)\[\/url\]/ism", '<a href="$1" target="_blank">$2</a>', $Text);
@ -884,6 +920,9 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
$Text = preg_replace("(\[h5\](.*?)\[\/h5\])ism",'<h5>$1</h5>',$Text);
$Text = preg_replace("(\[h6\](.*?)\[\/h6\])ism",'<h6>$1</h6>',$Text);
// Check for paragraph
$Text = preg_replace("(\[p\](.*?)\[\/p\])ism",'<p>$1</p>',$Text);
// Check for bold text
$Text = preg_replace("(\[b\](.*?)\[\/b\])ism",'<strong>$1</strong>',$Text);
@ -1103,6 +1142,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
$Text = preg_replace("/\[event\-finish\](.*?)\[\/event\-finish\]/ism",'',$Text);
$Text = preg_replace("/\[event\-location\](.*?)\[\/event\-location\]/ism",'',$Text);
$Text = preg_replace("/\[event\-adjust\](.*?)\[\/event\-adjust\]/ism",'',$Text);
$Text = preg_replace("/\[event\-id\](.*?)\[\/event\-id\]/ism",'',$Text);
}

View file

@ -10,7 +10,7 @@
dbesc($key)
);
if (dba::is_result($r))
if (dbm::is_result($r))
return $r[0]['v'];
return null;
@ -38,7 +38,7 @@
* $r = q("SELECT * FROM `cache` WHERE `k`='%s' limit 1",
* dbesc($key)
* );
* if(dba::is_result($r)) {
* if(dbm::is_result($r)) {
* q("UPDATE `cache` SET `v` = '%s', `updated = '%s' WHERE `k` = '%s'",
* dbesc($value),
* dbesc(datetime_convert()),

View file

@ -1,8 +1,8 @@
<?php
/**
* @file include/config.php
*
* Arbitrary configuration storage
* @brief (Deprecated) Arbitrary configuration storage
* Note:
* Please do not store booleans - convert to 0/1 integer values
* The get_?config() functions return boolean false for keys that are unset,
@ -12,330 +12,140 @@
* configurations need to be fixed as of 10/08/2011.
*/
use \Friendica\Core\Config;
use \Friendica\Core\PConfig;
// retrieve a "family" of config variables from database to cached storage
if(! function_exists('load_config')) {
function load_config($family) {
global $a;
$r = q("SELECT `v`, `k` FROM `config` WHERE `cat` = '%s'", dbesc($family));
if(dba::is_result($r)) {
foreach($r as $rr) {
$k = $rr['k'];
if ($family === 'config') {
$a->config[$k] = $rr['v'];
} else {
$a->config[$family][$k] = $rr['v'];
}
}
} else if ($family != 'config') {
// Negative caching
$a->config[$family] = "!<unset>!";
}
}}
// get a particular config variable given the family name
// and key. Returns false if not set.
// $instore is only used by the set_config function
// to determine if the key already exists in the DB
// If a key is found in the DB but doesn't exist in
// local config cache, pull it into the cache so we don't have
// to hit the DB again for this item.
if(! function_exists('get_config')) {
function get_config($family, $key, $instore = false) {
global $a;
if(! $instore) {
// Looking if the whole family isn't set
if(isset($a->config[$family])) {
if($a->config[$family] === '!<unset>!') {
return false;
}
}
if(isset($a->config[$family][$key])) {
if($a->config[$family][$key] === '!<unset>!') {
return false;
}
return $a->config[$family][$key];
}
}
// If APC is enabled then fetch the data from there, else try XCache
/*if (function_exists("apc_fetch") AND function_exists("apc_exists"))
if (apc_exists($family."|".$key)) {
$val = apc_fetch($family."|".$key);
$a->config[$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}
elseif (function_exists("xcache_fetch") AND function_exists("xcache_isset"))
if (xcache_isset($family."|".$key)) {
$val = xcache_fetch($family."|".$key);
$a->config[$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}
/**
* @brief (Deprecated) Loads all configuration values of family into a cached storage.
*
* Note: This function is deprecated. Use Config::load() instead.
*
* @param string $family
* The category of the configuration value
* @return void
*/
$ret = q("SELECT `v` FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
dbesc($family),
dbesc($key)
);
if(count($ret)) {
// manage array value
$val = (preg_match("|^a:[0-9]+:{.*}$|s", $ret[0]['v'])?unserialize( $ret[0]['v']):$ret[0]['v']);
$a->config[$family][$key] = $val;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($family."|".$key, $val, 600);
elseif (function_exists("xcache_set"))
xcache_set($family."|".$key, $val, 600);*/
return $val;
function load_config($family) {
return Config::load($family);
}
else {
$a->config[$family][$key] = '!<unset>!';
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($family."|".$key, '!<unset>!', 600);
elseif (function_exists("xcache_set"))
xcache_set($family."|".$key, '!<unset>!', 600);*/
/**
* @brief (Deprecated) Get a particular user's config variable given the category name
* ($family) and a key.
*
* Note: This function is deprecated. Use Config::get() instead.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @param boolean $refresh
* If true the config is loaded from the db and not from the cache
* @return mixed Stored value or false if it does not exist
*/
function get_config($family, $key, $refresh = false) {
$v = Config::get($family, $key, false, $refresh);
return $v;
}
return false;
}}
// Store a config value ($value) in the category ($family)
// under the key ($key)
// Return the value, or false if the database update failed
if(! function_exists('set_config')) {
/**
* @brief (Deprecated) Sets a configuration value for system config
*
* Note: This function is deprecated. Use Config::set() instead.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to set
* @param string $value
* The value to store
* @return mixed Stored $value or false if the database update failed
*/
function set_config($family,$key,$value) {
global $a;
// If $a->config[$family] has been previously set to '!<unset>!', then
// $a->config[$family][$key] will evaluate to $a->config[$family][0], and
// $a->config[$family][$key] = $value will be equivalent to
// $a->config[$family][0] = $value[0] (this causes infuriating bugs),
// so unset the family before assigning a value to a family's key
if($a->config[$family] === '!<unset>!')
unset($a->config[$family]);
// manage array value
$dbvalue = (is_array($value)?serialize($value):$value);
$dbvalue = (is_bool($dbvalue) ? intval($dbvalue) : $dbvalue);
if(get_config($family,$key,true) === false) {
$a->config[$family][$key] = $value;
$ret = q("INSERT INTO `config` ( `cat`, `k`, `v` ) VALUES ( '%s', '%s', '%s' ) ",
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
if($ret)
return $value;
return $ret;
return Config::set($family, $key, $value);
}
$ret = q("UPDATE `config` SET `v` = '%s' WHERE `cat` = '%s' AND `k` = '%s'",
dbesc($dbvalue),
dbesc($family),
dbesc($key)
);
$a->config[$family][$key] = $value;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($family."|".$key, $value, 600);
elseif (function_exists("xcache_set"))
xcache_set($family."|".$key, $value, 600);*/
if($ret)
return $value;
return $ret;
}}
if(! function_exists('load_pconfig')) {
function load_pconfig($uid,$family) {
global $a;
$r = q("SELECT `v`,`k` FROM `pconfig` WHERE `cat` = '%s' AND `uid` = %d",
dbesc($family),
intval($uid)
);
if(dba::is_result($r)) {
foreach($r as $rr) {
$k = $rr['k'];
$a->config[$uid][$family][$k] = $rr['v'];
}
} else if ($family != 'config') {
// Negative caching
$a->config[$uid][$family] = "!<unset>!";
}
}}
if(! function_exists('get_pconfig')) {
function get_pconfig($uid,$family, $key, $instore = false) {
global $a;
if(! $instore) {
// Looking if the whole family isn't set
if(isset($a->config[$uid][$family])) {
if($a->config[$uid][$family] === '!<unset>!') {
return false;
}
}
if(isset($a->config[$uid][$family][$key])) {
if($a->config[$uid][$family][$key] === '!<unset>!') {
return false;
}
return $a->config[$uid][$family][$key];
}
}
// If APC is enabled then fetch the data from there, else try XCache
/*if (function_exists("apc_fetch") AND function_exists("apc_exists"))
if (apc_exists($uid."|".$family."|".$key)) {
$val = apc_fetch($uid."|".$family."|".$key);
$a->config[$uid][$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}
elseif (function_exists("xcache_get") AND function_exists("xcache_isset"))
if (xcache_isset($uid."|".$family."|".$key)) {
$val = xcache_get($uid."|".$family."|".$key);
$a->config[$uid][$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}*/
$ret = q("SELECT `v` FROM `pconfig` WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s' LIMIT 1",
intval($uid),
dbesc($family),
dbesc($key)
);
if(count($ret)) {
$val = (preg_match("|^a:[0-9]+:{.*}$|s", $ret[0]['v'])?unserialize( $ret[0]['v']):$ret[0]['v']);
$a->config[$uid][$family][$key] = $val;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($uid."|".$family."|".$key, $val, 600);
elseif (function_exists("xcache_set"))
xcache_set($uid."|".$family."|".$key, $val, 600);*/
return $val;
}
else {
$a->config[$uid][$family][$key] = '!<unset>!';
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($uid."|".$family."|".$key, '!<unset>!', 600);
elseif (function_exists("xcache_set"))
xcache_set($uid."|".$family."|".$key, '!<unset>!', 600);*/
}
return false;
}}
if(! function_exists('del_config')) {
/**
* @brief (Deprecated) Deletes the given key from the system configuration.
*
* Note: This function is deprecated. Use Config::delete() instead.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to delete
* @return mixed
*/
function del_config($family,$key) {
global $a;
if(x($a->config[$family],$key))
unset($a->config[$family][$key]);
$ret = q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s'",
dbesc($family),
dbesc($key)
);
// If APC is enabled then delete the data from there, else try XCache
/*if (function_exists("apc_delete"))
apc_delete($family."|".$key);
elseif (function_exists("xcache_unset"))
xcache_unset($family."|".$key);*/
return $ret;
}}
// Same as above functions except these are for personal config storage and take an
// additional $uid argument.
if(! function_exists('set_pconfig')) {
function set_pconfig($uid,$family,$key,$value) {
global $a;
// manage array value
$dbvalue = (is_array($value)?serialize($value):$value);
if(get_pconfig($uid,$family,$key,true) === false) {
$a->config[$uid][$family][$key] = $value;
$ret = q("INSERT INTO `pconfig` ( `uid`, `cat`, `k`, `v` ) VALUES ( %d, '%s', '%s', '%s' ) ",
intval($uid),
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
if($ret)
return $value;
return $ret;
return Config::delete($family, $key);
}
$ret = q("UPDATE `pconfig` SET `v` = '%s' WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s'",
dbesc($dbvalue),
intval($uid),
dbesc($family),
dbesc($key)
);
$a->config[$uid][$family][$key] = $value;
/**
* @brief (Deprecated) Loads all configuration values of a user's config family into a cached storage.
*
* Note: This function is deprecated. Use PConfig::load() instead.
*
* @param string $uid
* The user_id
* @param string $family
* The category of the configuration value
* @return void
*/
function load_pconfig($uid,$family) {
return PConfig::load($uid, $family);
}
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($uid."|".$family."|".$key, $value, 600);
elseif (function_exists("xcache_set"))
xcache_set($uid."|".$family."|".$key, $value, 600);*/
/**
* @brief (Deprecated) Get a particular user's config variable given the category name
* ($family) and a key.
*
* Note: This function is deprecated. Use PConfig::get() instead.
*
* @param string $uid
* The user_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @param boolean $refresh
* If true the config is loaded from the db and not from the cache
* @return mixed Stored value or false if it does not exist
*/
function get_pconfig($uid, $family, $key, $refresh = false) {
$v = PConfig::get($uid, $family, $key, false, $refresh);
return $v;
}
/**
* @brief (Deprecated) Sets a configuration value for a user
*
* Note: This function is deprecated. Use PConfig::set() instead.
*
* @param string $uid
* The user_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to set
* @param string $value
* The value to store
* @return mixed Stored $value or false
*/
function set_pconfig($uid,$family,$key,$value) {
return PConfig::set($uid, $family, $key, $value);
}
if($ret)
return $value;
return $ret;
}}
if(! function_exists('del_pconfig')) {
/**
* @brief (Deprecated) Deletes the given key from the users's configuration.
*
* Note: This function is deprecated. Use PConfig::delete() instead.
*
* @param string $uid The user_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to delete
* @return mixed
*/
function del_pconfig($uid,$family,$key) {
global $a;
if(x($a->config[$uid][$family],$key))
unset($a->config[$uid][$family][$key]);
$ret = q("DELETE FROM `pconfig` WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s'",
intval($uid),
dbesc($family),
dbesc($key)
);
return $ret;
}}
return PConfig::delete($uid, $family, $key);
}

View file

@ -7,12 +7,12 @@ function contact_profile_assign($current,$foreign_net) {
$disabled = (($foreign_net) ? ' disabled="true" ' : '');
$o .= "<select id=\"contact-profile-selector\" $disabled name=\"profile-assign\" />\r\n";
$o .= "<select id=\"contact-profile-selector\" class=\"form-control\" $disabled name=\"profile-assign\" />\r\n";
$r = q("SELECT `id`, `profile-name` FROM `profile` WHERE `uid` = %d",
intval($_SESSION['uid']));
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $rr) {
$selected = (($rr['id'] == $current) ? " selected=\"selected\" " : "");
$o .= "<option value=\"{$rr['id']}\" $selected >{$rr['profile-name']}</option>\r\n";

View file

@ -93,7 +93,7 @@ function networks_widget($baseurl,$selected = '') {
);
$nets = array();
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
require_once('include/contact_selectors.php');
foreach($r as $rr) {
if($rr['network'])
@ -204,13 +204,13 @@ function common_friends_visitor_widget($profile_uid) {
dbesc(normalise_link(get_my_url())),
intval($profile_uid)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$cid = $r[0]['id'];
else {
$r = q("select id from gcontact where nurl = '%s' limit 1",
dbesc(normalise_link(get_my_url()))
);
if(dba::is_result($r))
if(dbm::is_result($r))
$zcid = $r[0]['id'];
}
}

View file

@ -373,6 +373,84 @@ function visible_activity($item) {
return true;
}
/**
* @brief SQL query for items
*/
function item_query() {
return "SELECT ".item_fieldlists()." FROM `item` ".
item_joins()." WHERE ".item_condition();
}
/**
* @brief List of all data fields that are needed for displaying items
*/
function item_fieldlists() {
/*
These Fields are not added below (yet). They are here to for bug search.
`item`.`type`,
`item`.`extid`,
`item`.`received`,
`item`.`changed`,
`item`.`moderated`,
`item`.`target-type`,
`item`.`target`,
`item`.`resource-id`,
`item`.`tag`,
`item`.`inform`,
`item`.`pubmail`,
`item`.`visible`,
`item`.`spam`,
`item`.`bookmark`,
`item`.`unseen`,
`item`.`deleted`,
`item`.`origin`,
`item`.`forum_mode`,
`item`.`last-child`,
`item`.`mention`,
`item`.`global`,
`item`.`gcontact-id`,
`item`.`shadow`,
*/
return "`item`.`author-link`, `item`.`author-name`, `item`.`author-avatar`,
`item`.`owner-link`, `item`.`owner-name`, `item`.`owner-avatar`,
`item`.`contact-id`, `item`.`uid`, `item`.`id`, `item`.`parent`,
`item`.`uri`, `item`.`thr-parent`, `item`.`parent-uri`,
`item`.`commented`, `item`.`created`, `item`.`edited`,
`item`.`verb`, `item`.`object-type`, `item`.`postopts`, `item`.`plink`,
`item`.`guid`, `item`.`wall`, `item`.`private`, `item`.`starred`,
`item`.`title`, `item`.`body`, `item`.`file`, `item`.`event-id`,
`item`.`location`, `item`.`coord`, `item`.`app`, `item`.`attach`,
`item`.`rendered-hash`, `item`.`rendered-html`, `item`.`object`,
`item`.`allow_cid`, `item`.`allow_gid`, `item`.`deny_cid`, `item`.`deny_gid`,
`item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
`author`.`thumb` AS `author-thumb`, `owner`.`thumb` AS `owner-thumb`,
`contact`.`network`, `contact`.`url`, `contact`.`name`, `contact`.`writable`,
`contact`.`self`, `contact`.`id` AS `cid`, `contact`.`alias`";
}
/**
* @brief SQL join for contacts that are needed for displaying items
*/
function item_joins() {
return "STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND
NOT `contact`.`blocked` AND NOT `contact`.`pending`
LEFT JOIN `contact` AS `author` ON `author`.`id`=`item`.`author-id`
LEFT JOIN `contact` AS `owner` ON `owner`.`id`=`item`.`owner-id`";
}
/**
* @brief SQL condition for items that are needed for displaying items
*/
function item_condition() {
return "`item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`";
}
/**
* "Render" a conversation or list of items for HTML display.
@ -389,6 +467,7 @@ if(!function_exists('conversation')) {
function conversation(&$a, $items, $mode, $update, $preview = false) {
require_once('include/bbcode.php');
require_once('include/Contact.php');
require_once('mod/proxy.php');
$ssl_state = ((local_user()) ? true : false);
@ -494,8 +573,6 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
else
$return_url = $_SESSION['return_url'] = $a->query_string;
load_contact_links(local_user());
$cb = array('items' => $items, 'mode' => $mode, 'update' => $update, 'preview' => $preview);
call_hooks('conversation_start',$cb);
@ -544,7 +621,6 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
$comment = '';
$owner_url = '';
$owner_photo = '';
$owner_name = '';
$sparkle = '';
@ -589,18 +665,6 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
$tags[] = $prefix."<a href=\"".$tag["url"]."\" target=\"_blank\">".$tag["term"]."</a>";
}
/*foreach(explode(',',$item['tag']) as $tag){
$tag = trim($tag);
if ($tag!="") {
$t = bbcode($tag);
$tags[] = $t;
if($t[0] == '#')
$hashtags[] = $t;
elseif($t[0] == '@')
$mentions[] = $t;
}
}*/
$sp = false;
$profile_link = best_link_url($item,$sp);
if($profile_link === 'mailbox')
@ -610,11 +674,21 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
else
$profile_link = zrl($profile_link);
$normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']);
if(($normalised != 'mailbox') && (x($a->contacts[$normalised])))
$profile_avatar = $a->contacts[$normalised]['thumb'];
if (!isset($item['author-thumb']) OR ($item['author-thumb'] == "")) {
$author_contact = get_contact_details_by_url($item['author-link'], $profile_owner);
if ($author_contact["thumb"])
$item['author-thumb'] = $author_contact["thumb"];
else
$profile_avatar = $a->remove_baseurl(((strlen($item['author-avatar'])) ? $item['author-avatar'] : $item['thumb']));
$item['author-thumb'] = $item['author-avatar'];
}
if (!isset($item['owner-thumb']) OR ($item['owner-thumb'] == "")) {
$owner_contact = get_contact_details_by_url($item['owner-link'], $profile_owner);
if ($owner_contact["thumb"])
$item['owner-thumb'] = $owner_contact["thumb"];
else
$item['owner-thumb'] = $item['owner-avatar'];
}
$locate = array('location' => $item['location'], 'coord' => $item['coord'], 'html' => '');
call_hooks('render_location',$locate);
@ -668,17 +742,21 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
$owner_name_e = $owner_name;
}
if ($item['item_network'] == "")
$item['item_network'] = $item['network'];
$tmp_item = array(
'template' => $tpl,
'id' => (($preview) ? 'P0' : $item['item_id']),
'network' => $item['item_network'],
'network_name' => network_to_name($item['item_network'], $profile_link),
'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])),
'profile_url' => $profile_link,
'item_photo_menu' => item_photo_menu($item),
'name' => $profile_name_e,
'sparkle' => $sparkle,
'lock' => $lock,
'thumb' => proxy_url($profile_avatar, false, PROXY_SIZE_THUMB),
'thumb' => App::remove_baseurl(proxy_url($item['author-thumb'], false, PROXY_SIZE_THUMB)),
'title' => $item['title_e'],
'body' => $body_e,
'tags' => $tags_e,
@ -697,7 +775,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
'indent' => '',
'owner_name' => $owner_name_e,
'owner_url' => $owner_url,
'owner_photo' => proxy_url($owner_photo, false, PROXY_SIZE_THUMB),
'owner_photo' => App::remove_baseurl(proxy_url($item['owner-thumb'], false, PROXY_SIZE_THUMB)),
'plink' => get_plink($item),
'edpost' => false,
'isstarred' => $isstarred,
@ -801,23 +879,13 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
function best_link_url($item,&$sparkle,$ssl_state = false) {
$a = get_app();
$best_url = '';
$sparkle = false;
$clean_url = normalise_link($item['author-link']);
if((local_user()) && (local_user() == $item['uid'])) {
if(isset($a->contacts) && x($a->contacts,$clean_url)) {
if($a->contacts[$clean_url]['network'] === NETWORK_DFRN) {
$best_url = 'redir/'.$a->contacts[$clean_url]['id'];
$sparkle = true;
} else
$best_url = $a->contacts[$clean_url]['url'];
}
} elseif (local_user()) {
$r = q("SELECT `id` FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `nurl` = '%s' LIMIT 1",
if (local_user()) {
$r = q("SELECT `id` FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `nurl` = '%s' AND NOT `pending` LIMIT 1",
dbesc(NETWORK_DFRN), intval(local_user()), dbesc(normalise_link($clean_url)));
if ($r) {
$best_url = 'redir/'.$r[0]['id'];
@ -837,15 +905,12 @@ function best_link_url($item,&$sparkle,$ssl_state = false) {
if(! function_exists('item_photo_menu')){
function item_photo_menu($item){
$a = get_app();
$ssl_state = false;
if(local_user()) {
if(local_user())
$ssl_state = true;
if(! count($a->contacts))
load_contact_links(local_user());
}
$sub_link="";
$poke_link="";
$contact_url="";
@ -853,6 +918,7 @@ function item_photo_menu($item){
$status_link="";
$photos_link="";
$posts_link="";
$network = "";
if((local_user()) && local_user() == $item['uid'] && $item['parent'] == $item['id'] && (! $item['self'])) {
$sub_link = 'javascript:dosubthread(' . $item['id'] . '); return false;';
@ -863,47 +929,33 @@ function item_photo_menu($item){
if($profile_link === 'mailbox')
$profile_link = '';
if($sparkle) {
$cid = intval(basename($profile_link));
$status_link = $profile_link . "?url=status";
$photos_link = $profile_link . "?url=photos";
$profile_link = $profile_link . "?url=profile";
$pm_url = 'message/new/' . $cid;
$zurl = '';
}
else {
$profile_link = zrl($profile_link);
if(local_user() && local_user() == $item['uid'] && link_compare($item['url'],$item['author-link'])) {
$cid = $item['contact-id'];
} else {
$r = q("SELECT `id`, `network` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' LIMIT 1",
$cid = 0;
$network = "";
$rel = 0;
$r = q("SELECT `id`, `network`, `rel` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' LIMIT 1",
intval(local_user()), dbesc(normalise_link($item['author-link'])));
if ($r) {
$cid = $r[0]["id"];
$network = $r[0]["network"];
$rel = $r[0]["rel"];
}
if ($r[0]["network"] == NETWORK_DIASPORA)
$pm_url = 'message/new/' . $cid;
if($sparkle) {
$status_link = $profile_link."?url=status";
$photos_link = $profile_link."?url=photos";
$profile_link = $profile_link."?url=profile";
$zurl = '';
} else
$cid = 0;
}
}
if(($cid) && (! $item['self'])) {
$profile_link = zrl($profile_link);
if($cid && !$item['self']) {
$poke_link = 'poke/?f=&c='.$cid;
$contact_url = 'contacts/'.$cid;
$posts_link = 'contacts/'.$cid.'/posts';
$clean_url = normalise_link($item['author-link']);
if((local_user()) && (local_user() == $item['uid'])) {
if(isset($a->contacts) && x($a->contacts,$clean_url)) {
if($a->contacts[$clean_url]['network'] === NETWORK_DIASPORA) {
if (in_array($network, array(NETWORK_DFRN, NETWORK_DIASPORA)))
$pm_url = 'message/new/'.$cid;
}
}
}
}
if (local_user()) {
$menu = Array(
@ -916,10 +968,10 @@ function item_photo_menu($item){
t("Send PM") => $pm_url
);
if ($a->contacts[$clean_url]['network'] === NETWORK_DFRN)
if ($network == NETWORK_DFRN)
$menu[t("Poke")] = $poke_link;
if ((($cid == 0) OR ($a->contacts[$clean_url]['rel'] == CONTACT_IS_FOLLOWER)) AND
if ((($cid == 0) OR ($rel == CONTACT_IS_FOLLOWER)) AND
in_array($item['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA)))
$menu[t("Connect/Follow")] = "follow?url=".urlencode($item['author-link']);
} else
@ -1228,6 +1280,10 @@ function status_editor($a,$x, $notes_cid = 0, $popup=false) {
'$private' => t('Private post'),
'$is_private' => $private_post,
'$public_link' => $public_post_link,
//jot nav tab (used in some themes)
'$message' => t('Message'),
'$browser' => t('Browser'),
));

View file

@ -27,7 +27,6 @@ function cron_run(&$argv, &$argc){
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once('include/session.php');
require_once('include/datetime.php');
require_once('include/items.php');
@ -70,36 +69,33 @@ function cron_run(&$argv, &$argc){
// run queue delivery process in the background
proc_run('php',"include/queue.php");
proc_run(PRIORITY_NEGLIGIBLE,"include/queue.php");
// run the process to discover global contacts in the background
proc_run('php',"include/discover_poco.php");
proc_run(PRIORITY_LOW,"include/discover_poco.php");
// run the process to update locally stored global contacts in the background
proc_run('php',"include/discover_poco.php", "checkcontact");
proc_run(PRIORITY_LOW,"include/discover_poco.php", "checkcontact");
// expire any expired accounts
// Expire and remove user entries
cron_expire_and_remove_users();
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() ");
// 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");
// delete user and contact records for recently removed accounts
// Check every conversation
proc_run(PRIORITY_MEDIUM, "include/cronjobs.php", "ostatus_conversations");
$r = q("SELECT * FROM `user` WHERE `account_removed` = 1 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']));
}
}
$abandon_days = intval(get_config('system','account_abandon_days'));
if($abandon_days < 1)
$abandon_days = 0;
// 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);
@ -113,9 +109,7 @@ function cron_run(&$argv, &$argc){
// update nodeinfo data
nodeinfo_cron();
/// @TODO Regenerate usage statistics
// q("ANALYZE TABLE `item`");
}
// once daily run birthday_updates and then expire in background
@ -126,11 +120,11 @@ function cron_run(&$argv, &$argc){
update_contact_birthdays();
proc_run('php',"include/discover_poco.php", "suggestions");
proc_run(PRIORITY_LOW,"include/discover_poco.php", "suggestions");
set_config('system','last_expire_day',$d2);
proc_run('php','include/expire.php');
proc_run(PRIORITY_LOW,'include/expire.php');
}
// Clear cache entries
@ -142,6 +136,42 @@ function cron_run(&$argv, &$argc){
// Repair entries in the database
cron_repair_database();
// Poll contacts
cron_poll_contacts($argc, $argv);
logger('cron: end');
set_config('system','last_cron', time());
return;
}
/**
* @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
*
* @param Integer $argc Number of command line arguments
* @param Array $argv Array of command line arguments
*/
function cron_poll_contacts($argc, $argv) {
$manual_id = 0;
$generation = 0;
$force = false;
@ -180,6 +210,10 @@ function cron_run(&$argv, &$argc){
// and which have a polling address and ignore Diaspora since
// 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)
$abandon_days = 0;
$abandon_sql = (($abandon_days)
? sprintf(" AND `user`.`login_date` > UTC_TIMESTAMP() - INTERVAL %d DAY ", intval($abandon_days))
: ''
@ -272,18 +306,12 @@ function cron_run(&$argv, &$argc){
logger("Polling ".$contact["network"]." ".$contact["id"]." ".$contact["nick"]." ".$contact["name"]);
proc_run('php','include/onepoll.php',$contact['id']);
proc_run(PRIORITY_MEDIUM,'include/onepoll.php',$contact['id']);
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
}
logger('cron: end');
set_config('system','last_cron', time());
return;
}
/**
@ -382,7 +410,7 @@ function cron_repair_diaspora(&$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 ($r) {
if (dbm::is_result($r)) {
foreach ($r AS $contact) {
if (poco_reachable($contact["url"])) {
$data = probe_url($contact["url"]);
@ -410,6 +438,12 @@ function cron_repair_database() {
// 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

View file

@ -31,6 +31,17 @@ function cronhooks_run(&$argv, &$argc){
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]) {
logger("Calling cron hook '".$hook[1]."'", LOGGER_DEBUG);
call_single_hook($a, $name, $hook, $data);
}
return;
}
$last = get_config('system','last_cronhook');
$poll_interval = intval(get_config('system','cronhook_interval'));
@ -47,12 +58,16 @@ function cronhooks_run(&$argv, &$argc){
$a->set_baseurl(get_config('system','url'));
load_hooks();
logger('cronhooks: start');
$d = datetime_convert();
if (get_config("system", "worker") AND 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');

77
include/cronjobs.php Normal file
View file

@ -0,0 +1,77 @@
<?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);
}
require_once("boot.php");
function cronjobs_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/ostatus.php');
require_once('include/post_update.php');
require_once('mod/nodeinfo.php');
load_config('config');
load_config('system');
$a->set_baseurl(get_config('system','url'));
// No parameter set? So return
if ($argc <= 1)
return;
// Check OStatus conversations
// Check only conversations with mentions (for a longer time)
if ($argv[1] == 'ostatus_mentions') {
ostatus::check_conversations(true);
return;
}
// Check every conversation
if ($argv[1] == 'ostatus_conversations') {
ostatus::check_conversations(false);
return;
}
// Call possible post update functions
// see include/post_update.php for more details
if ($argv[1] == 'post_update') {
post_update();
return;
}
// update nodeinfo data
if ($argv[1] == 'nodeinfo') {
nodeinfo_cron();
return;
}
return;
}
if (array_search(__file__,get_included_files())===0){
cronjobs_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -162,7 +162,7 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d
* @brief Wrapper for date selector, tailored for use in birthday fields.
*
* @param string $dob Date of Birth
* @return string
* @return string Formatted html
*/
function dob($dob) {
list($year,$month,$day) = sscanf($dob,'%4d-%2d-%2d');
@ -175,7 +175,18 @@ function dob($dob) {
else
$value = (($year) ? datetime_convert('UTC','UTC',$dob,'Y-m-d') : datetime_convert('UTC','UTC',$dob,'m-d'));
$o = '<input type="text" name="dob" value="' . $value . '" placeholder="' . t('YYYY-MM-DD or MM-DD') . '" />';
$age = ((intval($value)) ? age($value, $a->user["timezone"], $a->user["timezone"]) : "");
$o = replace_macros(get_markup_template("field_input.tpl"), array(
'$field' => array(
'dob',
t('Birthday:'),
$value,
(((intval($age)) > 0 ) ? t('Age: ') . $age : ""),
'',
'placeholder="' . t('YYYY-MM-DD or MM-DD') . '"'
)
));
// if ($dob && $dob != '0000-00-00')
// $o = datesel($f,mktime(0,0,0,0,0,1900),mktime(),mktime(0,0,0,$month,$day,$year),'dob');
@ -202,7 +213,7 @@ function dob($dob) {
* @return string Parsed HTML output.
*/
function datesel($format, $min, $max, $default, $id = 'datepicker') {
return datetimesel($format,$min,$max,$default,$id,true,false, '','');
return datetimesel($format,$min,$max,$default,'',$id,true,false, '','');
}
/**
@ -220,7 +231,7 @@ function datesel($format, $min, $max, $default, $id = 'datepicker') {
* @return string Parsed HTML output.
*/
function timesel($format, $h, $m, $id='timepicker') {
return datetimesel($format,new DateTime(),new DateTime(),new DateTime("$h:$m"),$id,false,true);
return datetimesel($format,new DateTime(),new DateTime(),new DateTime("$h:$m"),'',$id,false,true);
}
/**
@ -251,7 +262,7 @@ function timesel($format, $h, $m, $id='timepicker') {
* @todo Once browser support is better this could probably be replaced with
* native HTML5 date picker.
*/
function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pickdate = true, $picktime = true, $minfrom = '', $maxfrom = '', $required = false) {
function datetimesel($format, $min, $max, $default, $label, $id = 'datetimepicker', $pickdate = true, $picktime = true, $minfrom = '', $maxfrom = '', $required = false) {
// First day of the week (0 = Sunday)
$firstDay = get_pconfig(local_user(),'system','first_day_of_week');
@ -273,7 +284,7 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic
$minjs = $min ? ",minDate: new Date({$min->getTimestamp()}*1000), yearStart: " . $min->format('Y') : '';
$maxjs = $max ? ",maxDate: new Date({$max->getTimestamp()}*1000), yearEnd: " . $max->format('Y') : '';
$input_text = $default ? 'value="' . date($dateformat, $default->getTimestamp()) . '"' : '';
$input_text = $default ? date($dateformat, $default->getTimestamp()) : '';
$defaultdatejs = $default ? ",defaultDate: new Date({$default->getTimestamp()}*1000)" : '';
$pickers = '';
@ -283,9 +294,9 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic
$extra_js = '';
$pickers .= ",dayOfWeekStart: ".$firstDay.",lang:'".$lang."'";
if($minfrom != '')
$extra_js .= "\$('#$minfrom').data('xdsoft_datetimepicker').setOptions({onChangeDateTime: function (currentDateTime) { \$('#$id').data('xdsoft_datetimepicker').setOptions({minDate: currentDateTime})}})";
$extra_js .= "\$('#id_$minfrom').data('xdsoft_datetimepicker').setOptions({onChangeDateTime: function (currentDateTime) { \$('#id_$id').data('xdsoft_datetimepicker').setOptions({minDate: currentDateTime})}})";
if($maxfrom != '')
$extra_js .= "\$('#$maxfrom').data('xdsoft_datetimepicker').setOptions({onChangeDateTime: function (currentDateTime) { \$('#$id').data('xdsoft_datetimepicker').setOptions({maxDate: currentDateTime})}})";
$extra_js .= "\$('#id_$maxfrom').data('xdsoft_datetimepicker').setOptions({onChangeDateTime: function (currentDateTime) { \$('#id_$id').data('xdsoft_datetimepicker').setOptions({maxDate: currentDateTime})}})";
$readable_format = $dateformat;
$readable_format = str_replace('Y','yyyy',$readable_format);
@ -294,10 +305,13 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic
$readable_format = str_replace('H','HH',$readable_format);
$readable_format = str_replace('i','MM',$readable_format);
$o .= "<div class='date'><input type='text' placeholder='$readable_format' name='$id' id='$id' $input_text />";
$o .= '</div>';
$tpl = get_markup_template('field_input.tpl');
$o .= replace_macros($tpl,array(
'$field' => array($id, $label, $input_text, '', (($required) ? '*' : ''), 'placeholder="' . $readable_format . '"'),
));
$o .= "<script type='text/javascript'>";
$o .= "\$(function () {var picker = \$('#$id').datetimepicker({step:5,format:'$dateformat' $minjs $maxjs $pickers $defaultdatejs}); $extra_js})";
$o .= "\$(function () {var picker = \$('#id_$id').datetimepicker({step:5,format:'$dateformat' $minjs $maxjs $pickers $defaultdatejs}); $extra_js})";
$o .= "</script>";
return $o;
@ -544,7 +558,7 @@ function update_contact_birthdays() {
// In-network birthdays are handled within local_delivery
$r = q("SELECT * FROM contact WHERE `bd` != '' AND `bd` != '0000-00-00' AND SUBSTRING(`bd`,1,4) != `bdyear` ");
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $rr) {
logger('update_contact_birthday: ' . $rr['bd']);

View file

@ -1,4 +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
@ -65,6 +66,8 @@ class dba {
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;
@ -72,6 +75,8 @@ class dba {
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);
}
if(! $this->connected) {
$this->db = null;
@ -94,6 +99,14 @@ 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");
$stamp1 = microtime(true);
if($this->mysqli)
@ -106,6 +119,9 @@ class dba {
$a->save_timestamp($stamp1, "database");
if (strtolower(substr($sql, 0, 6)) != "select")
$a->save_timestamp($stamp1, "database_write");
if(x($a->config,'system') && x($a->config['system'],'db_log')) {
if (($duration > $a->config["system"]["db_loglimit"])) {
$duration = round($duration, 3);
@ -118,14 +134,17 @@ class dba {
}
if($this->mysqli) {
if($this->db->errno)
if($this->db->errno) {
$this->error = $this->db->error;
$this->errorno = $this->db->errno;
}
elseif(mysql_errno($this->db))
} elseif(mysql_errno($this->db)) {
$this->error = mysql_error($this->db);
$this->errorno = mysql_errno($this->db);
}
if(strlen($this->error)) {
logger('dba: ' . $this->error);
logger('DB Error ('.$connstr.') '.$this->errorno.': '.$this->error);
}
if($this->debug) {
@ -230,16 +249,6 @@ class dba {
}
}
/**
* Checks if $array is a filled array with at least one entry.
*
* @param $array mixed A filled array with at least one entry
* @return Whether $array is a filled array
*/
public static function is_result ($array) {
return (is_array($array) && count($array) > 0);
}
function __destruct() {
if ($this->db)
if($this->mysqli)

View file

@ -232,16 +232,6 @@ class dba {
}
}
/**
* Checks if $array is a filled array with at least one entry.
*
* @param $array mixed A filled array with at least one entry
* @return Whether $array is a filled array
*/
public function is_result ($array) {
return (is_array($array) && count($array) > 0);
}
function __destruct() {
if ($this->db)
\DDDBL\disconnect();

49
include/dbm.php Normal file
View file

@ -0,0 +1,49 @@
<?php
/**
* @brief This class contain functions for the database management
*
*/
class dbm {
/**
* @brief Return a list of database processes
*
* @return array
* 'list' => List of processes, separated in their different states
* 'amount' => Number of concurrent database processes
*/
public static function processlist() {
$r = q("SHOW PROCESSLIST");
$s = array();
$processes = 0;
$states = array();
foreach ($r AS $process) {
$state = trim($process["State"]);
// Filter out all non blocking processes
if (!in_array($state, array("", "init", "statistics", "updating"))) {
++$states[$state];
++$processes;
}
}
$statelist = "";
foreach ($states AS $state => $usage) {
if ($statelist != "")
$statelist .= ", ";
$statelist .= $state.": ".$usage;
}
return(array("list" => $statelist, "amount" => $processes));
}
/**
* Checks if $array is a filled array with at least one entry.
*
* @param $array mixed A filled array with at least one entry
* @return Whether $array is a filled array
*/
public static function is_result($array) {
return (is_array($array) && count($array) > 0);
}
}
?>

View file

@ -260,6 +260,13 @@ function db_field_command($parameters, $create = true) {
function db_create_table($name, $fields, $verbose, $action, $indexes=null) {
global $a, $db;
if (isset($a->config["system"]["db_charset"]))
$charset = $a->config["system"]["db_charset"];
elseif ($verbose)
$charset = "utf8mb4";
else
$charset = "utf8";
$r = true;
$sql = "";
@ -282,7 +289,7 @@ function db_create_table($name, $fields, $verbose, $action, $indexes=null) {
$sql = implode(",\n\t", $sql_rows);
$sql = sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n\t", dbesc($name)).$sql."\n) DEFAULT CHARSET=utf8";
$sql = sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n\t", dbesc($name)).$sql."\n) DEFAULT CHARSET=".$charset;
if ($verbose)
echo $sql.";\n";
@ -365,10 +372,10 @@ function db_definition() {
"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"),
"allow_cid" => array("type" => "mediumtext", "not null" => "1"),
"allow_gid" => array("type" => "mediumtext", "not null" => "1"),
"deny_cid" => array("type" => "mediumtext", "not null" => "1"),
"deny_gid" => array("type" => "mediumtext", "not null" => "1"),
"allow_cid" => array("type" => "mediumtext"),
"allow_gid" => array("type" => "mediumtext"),
"deny_cid" => array("type" => "mediumtext"),
"deny_gid" => array("type" => "mediumtext"),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -389,7 +396,7 @@ function db_definition() {
$database["cache"] = array(
"fields" => array(
"k" => array("type" => "varchar(255)", "not null" => "1", "primary" => "1"),
"v" => array("type" => "text", "not null" => "1"),
"v" => array("type" => "text"),
"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"),
),
@ -429,7 +436,7 @@ function db_definition() {
"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"cat" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"k" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"v" => array("type" => "text", "not null" => "1"),
"v" => array("type" => "text"),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -449,29 +456,29 @@ function db_definition() {
"name" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"nick" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"location" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"about" => array("type" => "text", "not null" => "1"),
"keywords" => array("type" => "text", "not null" => "1"),
"about" => array("type" => "text"),
"keywords" => array("type" => "text"),
"gender" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"attag" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"avatar" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"photo" => array("type" => "text", "not null" => "1"),
"thumb" => array("type" => "text", "not null" => "1"),
"micro" => array("type" => "text", "not null" => "1"),
"site-pubkey" => array("type" => "text", "not null" => "1"),
"photo" => array("type" => "text"),
"thumb" => array("type" => "text"),
"micro" => array("type" => "text"),
"site-pubkey" => array("type" => "text"),
"issued-id" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"dfrn-id" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"nurl" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"addr" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"alias" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"pubkey" => array("type" => "text", "not null" => "1"),
"prvkey" => array("type" => "text", "not null" => "1"),
"pubkey" => array("type" => "text"),
"prvkey" => array("type" => "text"),
"batch" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"request" => array("type" => "text", "not null" => "1"),
"notify" => array("type" => "text", "not null" => "1"),
"poll" => array("type" => "text", "not null" => "1"),
"confirm" => array("type" => "text", "not null" => "1"),
"poco" => array("type" => "text", "not null" => "1"),
"request" => array("type" => "text"),
"notify" => array("type" => "text"),
"poll" => array("type" => "text"),
"confirm" => array("type" => "text"),
"poco" => array("type" => "text"),
"aes_allow" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"ret-aes" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"usehub" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
@ -495,15 +502,15 @@ function db_definition() {
"archive" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"pending" => array("type" => "tinyint(1)", "not null" => "1", "default" => "1"),
"rating" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"reason" => array("type" => "text", "not null" => "1"),
"reason" => array("type" => "text"),
"closeness" => array("type" => "tinyint(2)", "not null" => "1", "default" => "99"),
"info" => array("type" => "mediumtext", "not null" => "1"),
"info" => array("type" => "mediumtext"),
"profile-id" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"bdyear" => array("type" => "varchar(4)", "not null" => "1", "default" => ""),
"bd" => array("type" => "date", "not null" => "1", "default" => "0000-00-00"),
"notify_new_posts" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"fetch_further_information" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"ffi_keyword_blacklist" => array("type" => "mediumtext", "not null" => "1"),
"ffi_keyword_blacklist" => array("type" => "mediumtext"),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -515,12 +522,12 @@ function db_definition() {
"fields" => array(
"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"guid" => array("type" => "varchar(64)", "not null" => "1", "default" => ""),
"recips" => array("type" => "mediumtext", "not null" => "1"),
"recips" => array("type" => "mediumtext"),
"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"),
"subject" => array("type" => "mediumtext", "not null" => "1"),
"subject" => array("type" => "mediumtext"),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -548,17 +555,17 @@ function db_definition() {
"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"),
"summary" => array("type" => "text", "not null" => "1"),
"desc" => array("type" => "text", "not null" => "1"),
"location" => array("type" => "text", "not null" => "1"),
"summary" => array("type" => "text"),
"desc" => array("type" => "text"),
"location" => array("type" => "text"),
"type" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"nofinish" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"adjust" => array("type" => "tinyint(1)", "not null" => "1", "default" => "1"),
"ignore" => array("type" => "tinyint(1) unsigned", "not null" => "1", "default" => "0"),
"allow_cid" => array("type" => "mediumtext", "not null" => "1"),
"allow_gid" => array("type" => "mediumtext", "not null" => "1"),
"deny_cid" => array("type" => "mediumtext", "not null" => "1"),
"deny_gid" => array("type" => "mediumtext", "not null" => "1"),
"allow_cid" => array("type" => "mediumtext"),
"allow_gid" => array("type" => "mediumtext"),
"deny_cid" => array("type" => "mediumtext"),
"deny_gid" => array("type" => "mediumtext"),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -568,6 +575,7 @@ function db_definition() {
$database["fcontact"] = array(
"fields" => array(
"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"guid" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"name" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"photo" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
@ -581,7 +589,7 @@ function db_definition() {
"priority" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"network" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"alias" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"pubkey" => array("type" => "text", "not null" => "1"),
"pubkey" => array("type" => "text"),
"updated" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
),
"indexes" => array(
@ -605,7 +613,7 @@ function db_definition() {
"id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"server" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"posturl" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"key" => array("type" => "text", "not null" => "1"),
"key" => array("type" => "text"),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -621,7 +629,7 @@ function db_definition() {
"url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"request" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"photo" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"note" => array("type" => "text", "not null" => "1"),
"note" => array("type" => "text"),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
),
"indexes" => array(
@ -654,8 +662,8 @@ function db_definition() {
"last_contact" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
"last_failure" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
"location" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"about" => array("type" => "text", "not null" => "1"),
"keywords" => array("type" => "text", "not null" => "1"),
"about" => array("type" => "text"),
"keywords" => array("type" => "text"),
"gender" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"birthday" => array("type" => "varchar(32)", "not null" => "1", "default" => "0000-00-00"),
"community" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
@ -663,7 +671,7 @@ function db_definition() {
"nsfw" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"network" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"addr" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"notify" => array("type" => "text", "not null" => "1"),
"notify" => array("type" => "text"),
"alias" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"generation" => array("type" => "tinyint(3)", "not null" => "1", "default" => "0"),
"server_url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
@ -725,7 +733,7 @@ function db_definition() {
"nurl" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"version" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"site_name" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"info" => array("type" => "text", "not null" => "1"),
"info" => array("type" => "text"),
"register_policy" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"poco" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"noscrape" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
@ -762,7 +770,7 @@ function db_definition() {
"contact-id" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"knowyou" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"duplex" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"note" => array("type" => "text", "not null" => "1"),
"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"),
"blocked" => array("type" => "tinyint(1)", "not null" => "1", "default" => "1"),
@ -792,34 +800,36 @@ function db_definition() {
"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"),
"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" => ""),
"owner-avatar" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"author-id" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"author-name" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"author-link" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"author-avatar" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"title" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"body" => array("type" => "mediumtext", "not null" => "1"),
"body" => array("type" => "mediumtext"),
"app" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"verb" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"object-type" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"object" => array("type" => "text", "not null" => "1"),
"object" => array("type" => "text"),
"target-type" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"target" => array("type" => "text", "not null" => "1"),
"postopts" => array("type" => "text", "not null" => "1"),
"target" => array("type" => "text"),
"postopts" => array("type" => "text"),
"plink" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"resource-id" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"event-id" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"tag" => array("type" => "mediumtext", "not null" => "1"),
"attach" => array("type" => "mediumtext", "not null" => "1"),
"inform" => array("type" => "mediumtext", "not null" => "1"),
"file" => array("type" => "mediumtext", "not null" => "1"),
"tag" => array("type" => "mediumtext"),
"attach" => array("type" => "mediumtext"),
"inform" => array("type" => "mediumtext"),
"file" => array("type" => "mediumtext"),
"location" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"coord" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"allow_cid" => array("type" => "mediumtext", "not null" => "1"),
"allow_gid" => array("type" => "mediumtext", "not null" => "1"),
"deny_cid" => array("type" => "mediumtext", "not null" => "1"),
"deny_gid" => array("type" => "mediumtext", "not null" => "1"),
"allow_cid" => array("type" => "mediumtext"),
"allow_gid" => array("type" => "mediumtext"),
"deny_cid" => array("type" => "mediumtext"),
"deny_gid" => array("type" => "mediumtext"),
"private" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"pubmail" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"moderated" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
@ -835,7 +845,7 @@ function db_definition() {
"mention" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"network" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"rendered-hash" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"rendered-html" => array("type" => "mediumtext", "not null" => "1"),
"rendered-html" => array("type" => "mediumtext"),
"global" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
),
"indexes" => array(
@ -847,7 +857,7 @@ function db_definition() {
"extid" => array("extid"),
"uid_id" => array("uid","id"),
"uid_created" => array("uid","created"),
"uid_unseen" => array("uid","unseen"),
"uid_unseen_contactid" => array("uid","unseen","contact-id"),
"uid_network_received" => array("uid","network","received"),
"uid_received" => array("uid","received"),
"uid_network_commented" => array("uid","network","commented"),
@ -855,15 +865,18 @@ function db_definition() {
"uid_title" => array("uid","title"),
"uid_thrparent" => array("uid","thr-parent"),
"uid_parenturi" => array("uid","parent-uri"),
"uid_contactid_id" => array("uid","contact-id","id"),
"uid_contactid_created" => array("uid","contact-id","created"),
"gcontactid_uid_created" => array("gcontact-id","uid","created"),
"authorid_created" => array("author-id","created"),
"ownerid_created" => array("owner-id","created"),
"wall_body" => array("wall","body(6)"),
"uid_visible_moderated_created" => array("uid","visible","moderated","created"),
"uid_uri" => array("uid","uri"),
"uid_wall_created" => array("uid","wall","created"),
"resource-id" => array("resource-id"),
"uid_type" => array("uid","type"),
"uid_starred" => array("uid","starred"),
"uid_starred_id" => array("uid","starred", "id"),
"contactid_allowcid_allowpid_denycid_denygid" => array("contact-id","allow_cid(10)","allow_gid(10)","deny_cid(10)","deny_gid(10)"),
"uid_wall_parent_created" => array("uid","wall","parent","created"),
"uid_type_changed" => array("uid","type","changed"),
@ -913,7 +926,7 @@ function db_definition() {
"contact-id" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"convid" => array("type" => "int(11) unsigned", "not null" => "1", "default" => "0"),
"title" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"body" => array("type" => "mediumtext", "not null" => "1"),
"body" => array("type" => "mediumtext"),
"seen" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"reply" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"replied" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
@ -941,7 +954,7 @@ function db_definition() {
"ssltype" => array("type" => "varchar(16)", "not null" => "1", "default" => ""),
"mailbox" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"user" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"pass" => array("type" => "text", "not null" => "1"),
"pass" => array("type" => "text"),
"reply_to" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"action" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"movetofolder" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
@ -972,7 +985,7 @@ function db_definition() {
"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"),
"msg" => array("type" => "mediumtext", "not null" => "1"),
"msg" => array("type" => "mediumtext"),
"uid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"link" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"iid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
@ -1003,7 +1016,7 @@ function db_definition() {
$database["oembed"] = array(
"fields" => array(
"url" => array("type" => "varchar(255)", "not null" => "1", "primary" => "1"),
"content" => array("type" => "text", "not null" => "1"),
"content" => array("type" => "text"),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
),
"indexes" => array(
@ -1016,7 +1029,7 @@ function db_definition() {
"url" => array("type" => "varchar(255)", "not null" => "1", "primary" => "1"),
"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" => "text", "not null" => "1"),
"content" => array("type" => "text"),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
),
"indexes" => array(
@ -1030,7 +1043,7 @@ function db_definition() {
"uid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"cat" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"k" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"v" => array("type" => "mediumtext", "not null" => "1"),
"v" => array("type" => "mediumtext"),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -1047,7 +1060,7 @@ function db_definition() {
"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"),
"title" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"desc" => array("type" => "text", "not null" => "1"),
"desc" => array("type" => "text"),
"album" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"filename" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"type" => array("type" => "varchar(128)", "not null" => "1", "default" => "image/jpeg"),
@ -1057,10 +1070,10 @@ function db_definition() {
"data" => array("type" => "mediumblob", "not null" => "1"),
"scale" => array("type" => "tinyint(3)", "not null" => "1", "default" => "0"),
"profile" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"allow_cid" => array("type" => "mediumtext", "not null" => "1"),
"allow_gid" => array("type" => "mediumtext", "not null" => "1"),
"deny_cid" => array("type" => "mediumtext", "not null" => "1"),
"deny_gid" => array("type" => "mediumtext", "not null" => "1"),
"allow_cid" => array("type" => "mediumtext"),
"allow_gid" => array("type" => "mediumtext"),
"deny_cid" => array("type" => "mediumtext"),
"deny_gid" => array("type" => "mediumtext"),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -1073,16 +1086,16 @@ function db_definition() {
"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"),
"q0" => array("type" => "mediumtext", "not null" => "1"),
"q1" => array("type" => "mediumtext", "not null" => "1"),
"q2" => array("type" => "mediumtext", "not null" => "1"),
"q3" => array("type" => "mediumtext", "not null" => "1"),
"q4" => array("type" => "mediumtext", "not null" => "1"),
"q5" => array("type" => "mediumtext", "not null" => "1"),
"q6" => array("type" => "mediumtext", "not null" => "1"),
"q7" => array("type" => "mediumtext", "not null" => "1"),
"q8" => array("type" => "mediumtext", "not null" => "1"),
"q9" => array("type" => "mediumtext", "not null" => "1"),
"q0" => array("type" => "mediumtext"),
"q1" => array("type" => "mediumtext"),
"q2" => array("type" => "mediumtext"),
"q3" => array("type" => "mediumtext"),
"q4" => array("type" => "mediumtext"),
"q5" => array("type" => "mediumtext"),
"q6" => array("type" => "mediumtext"),
"q7" => array("type" => "mediumtext"),
"q8" => array("type" => "mediumtext"),
"q9" => array("type" => "mediumtext"),
),
"indexes" => array(
"PRIMARY" => array("id"),
@ -1101,6 +1114,17 @@ function db_definition() {
"choice" => array("choice"),
)
);
$database["process"] = array(
"fields" => array(
"pid" => array("type" => "int(10) unsigned", "not null" => "1", "primary" => "1"),
"command" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
),
"indexes" => array(
"PRIMARY" => array("pid"),
"command" => array("command"),
)
);
$database["profile"] = array(
"fields" => array(
"id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
@ -1119,26 +1143,26 @@ function db_definition() {
"hometown" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"gender" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"marital" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"with" => array("type" => "text", "not null" => "1"),
"with" => array("type" => "text"),
"howlong" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"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" => ""),
"pub_keywords" => array("type" => "text", "not null" => "1"),
"prv_keywords" => array("type" => "text", "not null" => "1"),
"likes" => array("type" => "text", "not null" => "1"),
"dislikes" => array("type" => "text", "not null" => "1"),
"about" => array("type" => "text", "not null" => "1"),
"pub_keywords" => array("type" => "text"),
"prv_keywords" => array("type" => "text"),
"likes" => array("type" => "text"),
"dislikes" => array("type" => "text"),
"about" => array("type" => "text"),
"summary" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"music" => array("type" => "text", "not null" => "1"),
"book" => array("type" => "text", "not null" => "1"),
"tv" => array("type" => "text", "not null" => "1"),
"film" => array("type" => "text", "not null" => "1"),
"interest" => array("type" => "text", "not null" => "1"),
"romance" => array("type" => "text", "not null" => "1"),
"work" => array("type" => "text", "not null" => "1"),
"education" => array("type" => "text", "not null" => "1"),
"contact" => array("type" => "text", "not null" => "1"),
"music" => array("type" => "text"),
"book" => array("type" => "text"),
"tv" => array("type" => "text"),
"film" => array("type" => "text"),
"interest" => array("type" => "text"),
"romance" => array("type" => "text"),
"work" => array("type" => "text"),
"education" => array("type" => "text"),
"contact" => array("type" => "text"),
"homepage" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"photo" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"thumb" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
@ -1185,7 +1209,7 @@ function db_definition() {
"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"),
"content" => array("type" => "mediumtext", "not null" => "1"),
"content" => array("type" => "mediumtext"),
"batch" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
),
"indexes" => array(
@ -1226,7 +1250,7 @@ function db_definition() {
"fields" => array(
"id" => array("type" => "bigint(20) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"sid" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"data" => array("type" => "text", "not null" => "1"),
"data" => array("type" => "text"),
"expire" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0"),
),
"indexes" => array(
@ -1239,8 +1263,8 @@ function db_definition() {
"fields" => array(
"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"iid" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0"),
"signed_text" => array("type" => "mediumtext", "not null" => "1"),
"signature" => array("type" => "text", "not null" => "1"),
"signed_text" => array("type" => "mediumtext"),
"signature" => array("type" => "text"),
"signer" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
),
"indexes" => array(
@ -1296,6 +1320,8 @@ function db_definition() {
"uid" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0"),
"contact-id" => array("type" => "int(11) unsigned", "not null" => "1", "default" => "0"),
"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"),
@ -1335,7 +1361,7 @@ function db_definition() {
$database["tokens"] = array(
"fields" => array(
"id" => array("type" => "varchar(40)", "not null" => "1", "primary" => "1"),
"secret" => array("type" => "text", "not null" => "1"),
"secret" => array("type" => "text"),
"client_id" => array("type" => "varchar(20)", "not null" => "1", "default" => ""),
"expires" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"scope" => array("type" => "varchar(200)", "not null" => "1", "default" => ""),
@ -1361,10 +1387,10 @@ function db_definition() {
"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" => ""),
"pubkey" => array("type" => "text", "not null" => "1"),
"prvkey" => array("type" => "text", "not null" => "1"),
"spubkey" => array("type" => "text", "not null" => "1"),
"sprvkey" => array("type" => "text", "not null" => "1"),
"pubkey" => array("type" => "text"),
"prvkey" => array("type" => "text"),
"spubkey" => array("type" => "text"),
"sprvkey" => array("type" => "text"),
"verified" => array("type" => "tinyint(1) unsigned", "not null" => "1", "default" => "0"),
"blocked" => array("type" => "tinyint(1) unsigned", "not null" => "1", "default" => "0"),
"blockwall" => array("type" => "tinyint(1) unsigned", "not null" => "1", "default" => "0"),
@ -1384,11 +1410,11 @@ function db_definition() {
"expire_notification_sent" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"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", "not null" => "1"),
"allow_gid" => array("type" => "mediumtext", "not null" => "1"),
"deny_cid" => array("type" => "mediumtext", "not null" => "1"),
"deny_gid" => array("type" => "mediumtext", "not null" => "1"),
"openidserver" => array("type" => "text", "not null" => "1"),
"allow_cid" => array("type" => "mediumtext"),
"allow_gid" => array("type" => "mediumtext"),
"deny_cid" => array("type" => "mediumtext"),
"deny_gid" => array("type" => "mediumtext"),
"openidserver" => array("type" => "text"),
),
"indexes" => array(
"PRIMARY" => array("uid"),
@ -1408,7 +1434,7 @@ function db_definition() {
$database["workerqueue"] = array(
"fields" => array(
"id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"parameter" => array("type" => "text", "not null" => "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"),
"pid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
@ -1445,6 +1471,7 @@ function dbstructure_run(&$argv, &$argc) {
switch ($argv[1]) {
case "update":
update_structure(true, true);
set_config('system','build',DB_UPDATE_VERSION);
return;
case "dumpsql":
print_structure(db_definition());

View file

@ -254,7 +254,7 @@ function delivery_run(&$argv, &$argc){
intval($contact_id)
);
if (dba::is_result($r))
if (dbm::is_result($r))
$contact = $r[0];
if ($contact['self'])
@ -416,7 +416,7 @@ function delivery_run(&$argv, &$argc){
intval($argv[2]),
intval($uid)
);
if (dba::is_result($r))
if (dbm::is_result($r))
$it = $r[0];
}
if (!$it)

View file

@ -68,10 +68,11 @@ class dfrn {
* @param string $owner_nick Owner nick name
* @param string $last_update Date of the last update
* @param int $direction Can be -1, 0 or 1.
* @param boolean $onlyheader Output only the header without content? (Default is "no")
*
* @return string DFRN feed entries
*/
public static function feed($dfrn_id, $owner_nick, $last_update, $direction = 0) {
public static function feed($dfrn_id, $owner_nick, $last_update, $direction = 0, $onlyheader = false) {
$a = get_app();
@ -196,7 +197,6 @@ class dfrn {
`contact`.`name`, `contact`.`network`, `contact`.`photo`, `contact`.`url`,
`contact`.`name-date`, `contact`.`uri-date`, `contact`.`avatar-date`,
`contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `contact-id`, `contact`.`uid` AS `contact-uid`,
`sign`.`signed_text`, `sign`.`signature`, `sign`.`signer`
FROM `item` $sql_post_table
INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
@ -234,7 +234,7 @@ class dfrn {
// This hook can't work anymore
// call_hooks('atom_feed', $atom);
if(! count($items)) {
if (!count($items) OR $onlyheader) {
$atom = trim($doc->saveXML());
call_hooks('atom_feed_end', $atom);
@ -368,6 +368,8 @@ class dfrn {
xml::add_element($doc, $relocate, "dfrn:url", $owner['url']);
xml::add_element($doc, $relocate, "dfrn:name", $owner['name']);
xml::add_element($doc, $relocate, "dfrn:addr", $owner['addr']);
xml::add_element($doc, $relocate, "dfrn:avatar", $owner['avatar']);
xml::add_element($doc, $relocate, "dfrn:photo", $photos[4]);
xml::add_element($doc, $relocate, "dfrn:thumb", $photos[5]);
xml::add_element($doc, $relocate, "dfrn:micro", $photos[6]);
@ -462,38 +464,53 @@ class dfrn {
*/
private function add_author($doc, $owner, $authorelement, $public) {
// Is the profile hidden or shouldn't be published in the net? Then add the "hide" element
$r = q("SELECT `id` FROM `profile` INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
WHERE (`hidewall` OR NOT `net-publish`) AND `user`.`uid` = %d",
intval($owner['uid']));
if ($r)
$hidewall = true;
else
$hidewall = false;
$author = $doc->createElement($authorelement);
$namdate = datetime_convert('UTC', 'UTC', $owner['name-date'].'+00:00', ATOM_TIME);
$uridate = datetime_convert('UTC', 'UTC', $owner['uri-date'].'+00:00', ATOM_TIME);
$picdate = datetime_convert('UTC', 'UTC', $owner['avatar-date'].'+00:00', ATOM_TIME);
if (!$public OR !$hidewall)
$attributes = array("dfrn:updated" => $namdate);
else
$attributes = array();
xml::add_element($doc, $author, "name", $owner["name"], $attributes);
$attributes = array("dfrn:updated" => $namdate);
xml::add_element($doc, $author, "uri", app::get_baseurl().'/profile/'.$owner["nickname"], $attributes);
$attributes = array("dfrn:updated" => $namdate);
xml::add_element($doc, $author, "dfrn:handle", $owner["addr"], $attributes);
$attributes = array("rel" => "photo", "type" => "image/jpeg", "dfrn:updated" => $picdate,
$attributes = array("rel" => "photo", "type" => "image/jpeg",
"media:width" => 175, "media:height" => 175, "href" => $owner['photo']);
if (!$public OR !$hidewall)
$attributes["dfrn:updated"] = $picdate;
xml::add_element($doc, $author, "link", "", $attributes);
$attributes = array("rel" => "avatar", "type" => "image/jpeg", "dfrn:updated" => $picdate,
"media:width" => 175, "media:height" => 175, "href" => $owner['photo']);
$attributes["rel"] = "avatar";
xml::add_element($doc, $author, "link", "", $attributes);
if ($hidewall)
xml::add_element($doc, $author, "dfrn:hide", "true");
// The following fields will only be generated if the data isn't meant for a public feed
if ($public)
return $author;
$birthday = feed_birthday($owner['uid'], $owner['timezone']);
if ($birthday)
xml::add_element($doc, $author, "dfrn:birthday", $birthday);
// The following fields will only be generated if this isn't for a public feed
if ($public)
return $author;
// Only show contact details when we are allowed to
$r = q("SELECT `profile`.`about`, `profile`.`name`, `profile`.`homepage`, `user`.`nickname`, `user`.`timezone`,
`profile`.`locality`, `profile`.`region`, `profile`.`country-name`, `profile`.`pub_keywords`, `profile`.`dob`
@ -1126,7 +1143,7 @@ class dfrn {
$author["link"] = $xpath->evaluate($element."/atom:uri/text()", $context)->item(0)->nodeValue;
$r = q("SELECT `id`, `uid`, `url`, `network`, `avatar-date`, `name-date`, `uri-date`, `addr`,
`name`, `nick`, `about`, `location`, `keywords`, `bdyear`, `bd`
`name`, `nick`, `about`, `location`, `keywords`, `bdyear`, `bd`, `hidden`
FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
intval($importer["uid"]), dbesc(normalise_link($author["link"])), dbesc(NETWORK_STATUSNET));
if ($r) {
@ -1210,6 +1227,16 @@ class dfrn {
/// - poco:region
/// - poco:country
// If the "hide" element is present then the profile isn't searchable.
$hide = intval($xpath->evaluate($element."/dfrn:hide/text()", $context)->item(0)->nodeValue == "true");
logger("Hidden status for contact ".$contact["url"].": ".$hide, LOGGER_DEBUG);
// If the contact isn't searchable then set the contact to "hidden".
// Problem: This can be manually overridden by the user.
if ($hide)
$contact["hidden"] = true;
// Save the keywords into the contact table
$tags = array();
$tagelements = $xpath->evaluate($element."/poco:tags/text()", $context);
@ -1266,13 +1293,13 @@ class dfrn {
$datefields = array("name-date", "uri-date");
foreach ($datefields AS $field)
if (strtotime($contact[$field]) > strtotime($r[0][$field])) {
logger("Difference for contact ".$contact["id"]." in field '".$field."'. Old value: '".$contact[$field]."', new value '".$r[0][$field]."'", LOGGER_DEBUG);
logger("Difference for contact ".$contact["id"]." in field '".$field."'. New value: '".$contact[$field]."', old value '".$r[0][$field]."'", LOGGER_DEBUG);
$update = true;
}
foreach ($fields AS $field => $data)
if ($contact[$field] != $r[0][$field]) {
logger("Difference for contact ".$contact["id"]." in field '".$field."'. Old value: '".$contact[$field]."', new value '".$r[0][$field]."'", LOGGER_DEBUG);
logger("Difference for contact ".$contact["id"]." in field '".$field."'. New value: '".$contact[$field]."', old value '".$r[0][$field]."'", LOGGER_DEBUG);
$update = true;
}
@ -1280,13 +1307,13 @@ class dfrn {
logger("Update contact data for contact ".$contact["id"]." (".$contact["nick"].")", LOGGER_DEBUG);
q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s',
`addr` = '%s', `keywords` = '%s', `bdyear` = '%s', `bd` = '%s',
`addr` = '%s', `keywords` = '%s', `bdyear` = '%s', `bd` = '%s', `hidden` = %d,
`name-date` = '%s', `uri-date` = '%s'
WHERE `id` = %d AND `network` = '%s'",
dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]),
dbesc($contact["addr"]), dbesc($contact["keywords"]), dbesc($contact["bdyear"]),
dbesc($contact["bd"]), dbesc($contact["name-date"]), dbesc($contact["uri-date"]),
intval($contact["id"]), dbesc($contact["network"]));
dbesc($contact["bd"]), intval($contact["hidden"]), dbesc($contact["name-date"]),
dbesc($contact["uri-date"]), intval($contact["id"]), dbesc($contact["network"]));
}
update_contact_avatar($author["avatar"], $importer["uid"], $contact["id"],
@ -1299,6 +1326,7 @@ class dfrn {
$poco["generation"] = 2;
$poco["photo"] = $author["avatar"];
$poco["hide"] = $hide;
update_gcontact($poco);
}
@ -1430,7 +1458,7 @@ class dfrn {
dbesc(normalise_link($suggest["url"])),
intval($suggest["uid"])
);
if(dba::is_result($r))
if(dbm::is_result($r))
return false;
// Do we already have an fcontact record for this person?
@ -1441,7 +1469,7 @@ class dfrn {
dbesc($suggest["name"]),
dbesc($suggest["request"])
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$fid = $r[0]["id"];
// OK, we do. Do we already have an introduction for this person ?
@ -1449,7 +1477,7 @@ class dfrn {
intval($suggest["uid"]),
intval($fid)
);
if(dba::is_result($r))
if(dbm::is_result($r))
return false;
}
if(!$fid)
@ -1464,7 +1492,7 @@ class dfrn {
dbesc($suggest["name"]),
dbesc($suggest["request"])
);
if(dba::is_result($r))
if(dbm::is_result($r))
$fid = $r[0]["id"];
else
// database record did not get created. Quietly give up.
@ -1519,7 +1547,9 @@ class dfrn {
$relocate["uid"] = $importer["importer_uid"];
$relocate["cid"] = $importer["id"];
$relocate["url"] = $xpath->query("dfrn:url/text()", $relocation)->item(0)->nodeValue;
$relocate["addr"] = $xpath->query("dfrn:addr/text()", $relocation)->item(0)->nodeValue;
$relocate["name"] = $xpath->query("dfrn:name/text()", $relocation)->item(0)->nodeValue;
$relocate["avatar"] = $xpath->query("dfrn:avatar/text()", $relocation)->item(0)->nodeValue;
$relocate["photo"] = $xpath->query("dfrn:photo/text()", $relocation)->item(0)->nodeValue;
$relocate["thumb"] = $xpath->query("dfrn:thumb/text()", $relocation)->item(0)->nodeValue;
$relocate["micro"] = $xpath->query("dfrn:micro/text()", $relocation)->item(0)->nodeValue;
@ -1529,6 +1559,12 @@ class dfrn {
$relocate["poll"] = $xpath->query("dfrn:poll/text()", $relocation)->item(0)->nodeValue;
$relocate["sitepubkey"] = $xpath->query("dfrn:sitepubkey/text()", $relocation)->item(0)->nodeValue;
if (($relocate["avatar"] == "") AND ($relocate["photo"] != ""))
$relocate["avatar"] = $relocate["photo"];
if ($relocate["addr"] == "")
$relocate["addr"] = preg_replace("=(https?://)(.*)/profile/(.*)=ism", "$3@$2", $relocate["url"]);
// update contact
$r = q("SELECT `photo`, `url` FROM `contact` WHERE `id` = %d AND `uid` = %d;",
intval($importer["id"]),
@ -1538,44 +1574,75 @@ class dfrn {
$old = $r[0];
$x = q("UPDATE `contact` SET
// Update the gcontact entry
$relocate["server_url"] = preg_replace("=(https?://)(.*)/profile/(.*)=ism", "$1$2", $relocate["url"]);
$x = q("UPDATE `gcontact` SET
`name` = '%s',
`photo` = '%s',
`thumb` = '%s',
`micro` = '%s',
`url` = '%s',
`nurl` = '%s',
`addr` = '%s',
`connect` = '%s',
`notify` = '%s',
`server_url` = '%s'
WHERE `nurl` = '%s';",
dbesc($relocate["name"]),
dbesc($relocate["avatar"]),
dbesc($relocate["url"]),
dbesc(normalise_link($relocate["url"])),
dbesc($relocate["addr"]),
dbesc($relocate["addr"]),
dbesc($relocate["notify"]),
dbesc($relocate["server_url"]),
dbesc(normalise_link($old["url"])));
// Update the contact table. We try to find every entry.
$x = q("UPDATE `contact` SET
`name` = '%s',
`avatar` = '%s',
`url` = '%s',
`nurl` = '%s',
`addr` = '%s',
`request` = '%s',
`confirm` = '%s',
`notify` = '%s',
`poll` = '%s',
`site-pubkey` = '%s'
WHERE `id` = %d AND `uid` = %d;",
WHERE (`id` = %d AND `uid` = %d) OR (`nurl` = '%s');",
dbesc($relocate["name"]),
dbesc($relocate["photo"]),
dbesc($relocate["thumb"]),
dbesc($relocate["micro"]),
dbesc($relocate["avatar"]),
dbesc($relocate["url"]),
dbesc(normalise_link($relocate["url"])),
dbesc($relocate["addr"]),
dbesc($relocate["request"]),
dbesc($relocate["confirm"]),
dbesc($relocate["notify"]),
dbesc($relocate["poll"]),
dbesc($relocate["sitepubkey"]),
intval($importer["id"]),
intval($importer["importer_uid"]));
intval($importer["importer_uid"]),
dbesc(normalise_link($old["url"])));
update_contact_avatar($relocate["avatar"], $importer["importer_uid"], $importer["id"], true);
if ($x === false)
return false;
// update items
/// @todo This is an extreme performance killer
$fields = array(
'owner-link' => array($old["url"], $relocate["url"]),
'author-link' => array($old["url"], $relocate["url"]),
'owner-avatar' => array($old["photo"], $relocate["photo"]),
'author-avatar' => array($old["photo"], $relocate["photo"]),
//'owner-avatar' => array($old["photo"], $relocate["photo"]),
//'author-avatar' => array($old["photo"], $relocate["photo"]),
);
foreach ($fields as $n=>$f) {
$r = q("SELECT `id` FROM `item` WHERE `%s` = '%s' AND `uid` = %d LIMIT 1",
$n, dbesc($f[0]),
intval($importer["importer_uid"]));
if ($r) {
$x = q("UPDATE `item` SET `%s` = '%s' WHERE `%s` = '%s' AND `uid` = %d",
$n, dbesc($f[1]),
$n, dbesc($f[0]),
@ -1583,6 +1650,7 @@ class dfrn {
if ($x === false)
return false;
}
}
/// @TODO
/// merge with current record, current contents have priority
@ -1624,7 +1692,7 @@ class dfrn {
$changed = true;
if ($entrytype == DFRN_REPLY_RC)
proc_run("php", "include/notifier.php","comment-import", $current["id"]);
proc_run(PRIORITY_HIGH, "include/notifier.php","comment-import", $current["id"]);
}
// update last-child if it changes
@ -2120,7 +2188,7 @@ class dfrn {
dbesc($item["uri"]),
intval($importer["uid"])
);
if(dba::is_result($r))
if(dbm::is_result($r))
$ev["id"] = $r[0]["id"];
$event_id = event_store($ev);
@ -2141,7 +2209,7 @@ class dfrn {
}
// Update content if 'updated' changes
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
if (self::update_content($r[0], $item, $importer, $entrytype))
logger("Item ".$item["uri"]." was updated.", LOGGER_DEBUG);
else
@ -2163,7 +2231,7 @@ class dfrn {
intval($posted_id),
intval($importer["importer_uid"])
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$parent = $r[0]["parent"];
$parent_uri = $r[0]["parent-uri"];
}
@ -2184,7 +2252,7 @@ class dfrn {
if($posted_id AND $parent AND ($entrytype == DFRN_REPLY_RC)) {
logger("Notifying followers about comment ".$posted_id, LOGGER_DEBUG);
proc_run("php", "include/notifier.php", "comment-import", $posted_id);
proc_run(PRIORITY_HIGH, "include/notifier.php", "comment-import", $posted_id);
}
return true;
@ -2345,7 +2413,7 @@ class dfrn {
dbesc($item["parent-uri"]),
intval($importer["uid"])
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d",
intval($r[0]["id"])
);
@ -2355,7 +2423,7 @@ class dfrn {
if($entrytype == DFRN_REPLY_RC) {
logger("Notifying followers about deletion of post ".$item["id"], LOGGER_DEBUG);
proc_run("php", "include/notifier.php","drop", $item["id"]);
proc_run(PRIORITY_HIGH, "include/notifier.php","drop", $item["id"]);
}
}
}

View file

@ -3,40 +3,9 @@
* @file include/diaspora.php
* @brief The implementation of the diaspora protocol
*
* Checklist:
*
* Checked:
* - send status
* - send comment
* - send like
* - send mail
* - send status retraction
* - send comment retraction on own post
* - send like retraction on own post
* - send comment retraction on diaspora post
* - send like retraction on diaspora post
* - receive status
* - receive reshare
* - receive comment
* - receive like
* - receive connect request
* - receive profile data
* - receive mail
* - receive comment retraction
* - receive like retraction
* - relay comment
* - relay like
* - relay comment retraction from diaspora
* - relay comment retraction from friendica
* - relay like retraction from diaspora
* - relay like retraction from friendica
* - send share
*
* Should work:
* - receive account deletion
* - send unshare
*
* Unchecked:
* The new protocol is described here: http://diaspora.github.io/diaspora_federation/index.html
* Currently this implementation here interprets the old and the new protocol and sends the old one.
* This will change in the future.
*/
require_once("include/items.php");
@ -135,6 +104,59 @@ class diaspora {
return($signature);
}
/**
* @brief verify the envelope and return the verified data
*
* @param string $envelope The magic envelope
*
* @return string verified data
*/
private function verify_magic_envelope($envelope) {
$basedom = parse_xml_string($envelope, false);
if (!is_object($basedom)) {
logger("Envelope is no XML file");
return false;
}
$children = $basedom->children('http://salmon-protocol.org/ns/magic-env');
if (sizeof($children) == 0) {
logger("XML has no children");
return false;
}
$handle = "";
$data = base64url_decode($children->data);
$type = $children->data->attributes()->type[0];
$encoding = $children->encoding;
$alg = $children->alg;
$sig = base64url_decode($children->sig);
$key_id = $children->sig->attributes()->key_id[0];
if ($key_id != "")
$handle = base64url_decode($key_id);
$b64url_data = base64url_encode($data);
$msg = str_replace(array("\n", "\r", " ", "\t"), array("", "", "", ""), $b64url_data);
$signable_data = $msg.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg);
$key = self::key($handle);
$verify = rsa_verify($signable_data, $sig, $key);
if (!$verify) {
logger('Message did not verify. Discarding.');
return false;
}
return $data;
}
/**
* @brief: Decodes incoming Diaspora message
*
@ -268,7 +290,6 @@ class diaspora {
return array('message' => (string)$inner_decrypted,
'author' => unxmlify($author_link),
'key' => (string)$key);
}
@ -395,8 +416,10 @@ class diaspora {
$data = parse_xml_string($msg["message"], false);
if (!is_object($data))
if (!is_object($data)) {
logger("No valid XML ".$msg["message"], LOGGER_DEBUG);
return false;
}
$first_child = $data->getName();
@ -413,6 +436,8 @@ class diaspora {
$type = $element->getName();
$orig_type = $type;
logger("Got message type ".$type.": ".$msg["message"], LOGGER_DATA);
// All retractions are handled identically from now on.
// In the new version there will only be "retraction".
if (in_array($type, array("signed_retraction", "relayable_retraction")))
@ -457,11 +482,11 @@ class diaspora {
}
}
if ($fieldname == "author_signature")
if (($fieldname == "author_signature") AND ($entry != ""))
$author_signature = base64_decode($entry);
elseif ($fieldname == "parent_author_signature")
elseif (($fieldname == "parent_author_signature") AND ($entry != ""))
$parent_author_signature = base64_decode($entry);
elseif ($fieldname != "target_author_signature") {
elseif (!in_array($fieldname, array("author_signature", "parent_author_signature", "target_author_signature"))) {
if ($signed_data != "") {
$signed_data .= ";";
$signed_data_parent .= ";";
@ -486,19 +511,27 @@ class diaspora {
return true;
// No author_signature? This is a must, so we quit.
if (!isset($author_signature))
if (!isset($author_signature)) {
logger("No author signature for type ".$type." - Message: ".$msg["message"], LOGGER_DEBUG);
return false;
}
if (isset($parent_author_signature)) {
$key = self::key($msg["author"]);
if (!rsa_verify($signed_data, $parent_author_signature, $key, "sha256"))
if (!rsa_verify($signed_data, $parent_author_signature, $key, "sha256")) {
logger("No valid parent author signature for author ".$msg["author"]. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$parent_author_signature, LOGGER_DEBUG);
return false;
}
}
$key = self::key($fields->author);
return rsa_verify($signed_data, $author_signature, $key, "sha256");
if (!rsa_verify($signed_data, $author_signature, $key, "sha256")) {
logger("No valid author signature for author ".$msg["author"]. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$author_signature, LOGGER_DEBUG);
return false;
} else
return true;
}
/**
@ -541,6 +574,9 @@ class diaspora {
$d = strtotime($person["updated"]." +00:00");
if ($d < strtotime("now - 14 days"))
$update = true;
if ($person["guid"] == "")
$update = true;
}
if (!$person OR $update) {
@ -574,6 +610,7 @@ class diaspora {
`request` = '%s',
`nick` = '%s',
`addr` = '%s',
`guid` = '%s',
`batch` = '%s',
`notify` = '%s',
`poll` = '%s',
@ -586,7 +623,8 @@ class diaspora {
dbesc($arr["photo"]),
dbesc($arr["request"]),
dbesc($arr["nick"]),
dbesc($arr["addr"]),
dbesc(strtolower($arr["addr"])),
dbesc($arr["guid"]),
dbesc($arr["batch"]),
dbesc($arr["notify"]),
dbesc($arr["poll"]),
@ -598,15 +636,16 @@ class diaspora {
dbesc($arr["network"])
);
} else {
$r = q("INSERT INTO `fcontact` (`url`,`name`,`photo`,`request`,`nick`,`addr`,
$r = q("INSERT INTO `fcontact` (`url`,`name`,`photo`,`request`,`nick`,`addr`, `guid`,
`batch`, `notify`,`poll`,`confirm`,`network`,`alias`,`pubkey`,`updated`)
VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')",
VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')",
dbesc($arr["url"]),
dbesc($arr["name"]),
dbesc($arr["photo"]),
dbesc($arr["request"]),
dbesc($arr["nick"]),
dbesc($arr["addr"]),
dbesc($arr["guid"]),
dbesc($arr["batch"]),
dbesc($arr["notify"]),
dbesc($arr["poll"]),
@ -638,7 +677,7 @@ class diaspora {
$r = q("SELECT `addr` FROM `gcontact` WHERE `id` = %d AND `addr` != ''",
intval($gcontact_id));
if ($r)
return $r[0]["addr"];
return strtolower($r[0]["addr"]);
}
$r = q("SELECT `network`, `addr`, `self`, `url`, `nick` FROM `contact` WHERE `id` = %d",
@ -658,7 +697,7 @@ class diaspora {
}
}
return $handle;
return strtolower($handle);
}
/**
@ -841,11 +880,30 @@ class diaspora {
if ($level > 5)
return false;
// This will work for Diaspora and newer Friendica servers
// This will work for new Diaspora servers and Friendica servers from 3.5
$source_url = $server."/fetch/post/".$guid;
logger("Fetch post from ".$source_url, LOGGER_DEBUG);
$envelope = fetch_url($source_url);
if($envelope) {
logger("Envelope was fetched.", LOGGER_DEBUG);
$x = self::verify_magic_envelope($envelope);
if (!$x)
logger("Envelope could not be verified.", LOGGER_DEBUG);
else
logger("Envelope was verified.", LOGGER_DEBUG);
} else
$x = false;
// This will work for older Diaspora and Friendica servers
if (!$x) {
$source_url = $server."/p/".$guid.".xml";
logger("Fetch post from ".$source_url, LOGGER_DEBUG);
$x = fetch_url($source_url);
if(!$x)
return false;
}
$source_xml = parse_xml_string($x, false);
@ -854,9 +912,11 @@ class diaspora {
if ($source_xml->post->reshare) {
// Reshare of a reshare - old Diaspora version
logger("Message is a reshare", LOGGER_DEBUG);
return self::message($source_xml->post->reshare->root_guid, $server, ++$level);
} elseif ($source_xml->getName() == "reshare") {
// Reshare of a reshare - new Diaspora version
logger("Message is a new reshare", LOGGER_DEBUG);
return self::message($source_xml->root_guid, $server, ++$level);
}
@ -869,8 +929,10 @@ class diaspora {
$author = (string)$source_xml->author;
// If this isn't a "status_message" then quit
if (!$author)
if (!$author) {
logger("Message doesn't seem to be a status message", LOGGER_DEBUG);
return false;
}
$msg = array("message" => $x, "author" => $author);
@ -1016,6 +1078,23 @@ class diaspora {
return true;
}
/**
* @brief Fetch the uri from our database if we already have this item (maybe from ourselves)
*
* @param string $author Author handle
* @param string $guid Message guid
*
* @return string The constructed uri or the one from our database
*/
private function get_uri_from_guid($author, $guid) {
$r = q("SELECT `uri` FROM `item` WHERE `guid` = '%s' LIMIT 1", dbesc($guid));
if ($r)
return $r[0]["uri"];
else
return $author.":".$guid;
}
/**
* @brief Processes an incoming comment
*
@ -1032,6 +1111,11 @@ class diaspora {
$text = unxmlify($data->text);
$author = notags(unxmlify($data->author));
if (isset($data->created_at))
$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
else
$created_at = datetime_convert();
$contact = self::allowed_contact_by_handle($importer, $sender, true);
if (!$contact)
return false;
@ -1068,7 +1152,7 @@ class diaspora {
$datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
$datarray["guid"] = $guid;
$datarray["uri"] = $author.":".$guid;
$datarray["uri"] = self::get_uri_from_guid($author, $guid);
$datarray["type"] = "remote-comment";
$datarray["verb"] = ACTIVITY_POST;
@ -1078,6 +1162,8 @@ class diaspora {
$datarray["object-type"] = ACTIVITY_OBJ_COMMENT;
$datarray["object"] = $xml;
$datarray["changed"] = $datarray["created"] = $datarray["edited"] = $created_at;
$datarray["body"] = diaspora2bb($text);
self::fetch_guid($datarray);
@ -1098,7 +1184,7 @@ class diaspora {
);
// notify others
proc_run("php", "include/notifier.php", "comment-import", $message_id);
proc_run(PRIORITY_HIGH, "include/notifier.php", "comment-import", $message_id);
}
return $message_id;
@ -1188,7 +1274,7 @@ class diaspora {
$r = q("SELECT `id` FROM `mail` WHERE `uri` = '%s' LIMIT 1",
dbesc($message_uri)
);
if($r) {
if(dbm::is_result($r)) {
logger("duplicate message already delivered.", LOGGER_DEBUG);
return false;
}
@ -1274,7 +1360,7 @@ class diaspora {
intval($importer["uid"]),
dbesc($guid),
dbesc($author),
dbesc(datetime_convert("UTC", "UTC", $created_at)),
dbesc($created_at),
dbesc(datetime_convert()),
dbesc($subject),
dbesc($participants)
@ -1405,7 +1491,7 @@ class diaspora {
$datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
$datarray["guid"] = $guid;
$datarray["uri"] = $author.":".$guid;
$datarray["uri"] = self::get_uri_from_guid($author, $guid);
$datarray["type"] = "activity";
$datarray["verb"] = $verb;
@ -1433,7 +1519,7 @@ class diaspora {
);
// notify others
proc_run("php", "include/notifier.php", "comment-import", $message_id);
proc_run(PRIORITY_HIGH, "include/notifier.php", "comment-import", $message_id);
}
return $message_id;
@ -1566,7 +1652,7 @@ class diaspora {
* @return bool Success
*/
private function receive_profile($importer, $data) {
$author = notags(unxmlify($data->author));
$author = strtolower(notags(unxmlify($data->author)));
$contact = self::contact_by_handle($importer["uid"], $author);
if (!$contact)
@ -1713,7 +1799,7 @@ class diaspora {
$i = item_store($arr);
if($i)
proc_run("php", "include/notifier.php", "activity", $i);
proc_run(PRIORITY_HIGH, "include/notifier.php", "activity", $i);
}
}
}
@ -1771,11 +1857,27 @@ class diaspora {
// That makes us friends.
if ($contact) {
if ($following AND $sharing) {
logger("Author ".$author." (Contact ".$contact["id"].") wants to have a bidirectional conection.", LOGGER_DEBUG);
self::receive_request_make_friend($importer, $contact);
// refetch the contact array
$contact = self::contact_by_handle($importer["uid"],$author);
// If we are now friends, we are sending a share message.
// Normally we needn't to do so, but the first message could have been vanished.
if (in_array($contact["rel"], array(CONTACT_IS_FRIEND, CONTACT_IS_FOLLOWER))) {
$u = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer["uid"]));
if($u) {
logger("Sending share message to author ".$author." - Contact: ".$contact["id"]." - User: ".$importer["uid"], LOGGER_DEBUG);
$ret = self::send_share($u[0], $contact);
}
}
return true;
} else /// @todo Handle all possible variations of adding and retracting of permissions
} else { /// @todo Handle all possible variations of adding and retracting of permissions
logger("Author ".$author." (Contact ".$contact["id"].") wants to change the relationship: Following: ".$following." - sharing: ".$sharing. "(By now unsupported)", LOGGER_DEBUG);
return false;
}
}
if (!$following AND $sharing AND in_array($importer["page-flags"], array(PAGE_SOAPBOX, PAGE_NORMAL))) {
logger("Author ".$author." wants to share with us - but doesn't want to listen. Request is ignored.", LOGGER_DEBUG);
@ -1783,6 +1885,12 @@ class diaspora {
} elseif (!$following AND !$sharing) {
logger("Author ".$author." doesn't want anything - and we don't know the author. Request is ignored.", LOGGER_DEBUG);
return false;
} elseif (!$following AND $sharing) {
logger("Author ".$author." wants to share with us.", LOGGER_DEBUG);
} elseif ($following AND $sharing) {
logger("Author ".$author." wants to have a bidirectional conection.", LOGGER_DEBUG);
} elseif ($following AND !$sharing) {
logger("Author ".$author." wants to listen to us.", LOGGER_DEBUG);
}
$ret = self::person_by_handle($author);
@ -1822,13 +1930,19 @@ class diaspora {
return;
}
logger("Author ".$author." was added as contact number ".$contact_record["id"].".", LOGGER_DEBUG);
$def_gid = get_default_group($importer['uid'], $ret["network"]);
if(intval($def_gid))
group_add_member($importer["uid"], "", $contact_record["id"], $def_gid);
update_contact_avatar($ret["photo"], $importer['uid'], $contact_record["id"], true);
if($importer["page-flags"] == PAGE_NORMAL) {
logger("Sending intra message for author ".$author.".", LOGGER_DEBUG);
$hash = random_string().(string)time(); // Generate a confirm_key
$ret = q("INSERT INTO `intro` (`uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime`)
@ -1845,6 +1959,8 @@ class diaspora {
// automatic friend approval
logger("Does an automatic friend approval for author ".$author.".", LOGGER_DEBUG);
update_contact_avatar($contact_record["photo"],$importer["uid"],$contact_record["id"]);
// technically they are sharing with us (CONTACT_IS_SHARING),
@ -1873,8 +1989,13 @@ class diaspora {
);
$u = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer["uid"]));
if($u)
if($u) {
logger("Sending share message (Relation: ".$new_relation.") to author ".$author." - Contact: ".$contact_record["id"]." - User: ".$importer["uid"], LOGGER_DEBUG);
$ret = self::send_share($u[0], $contact_record);
// Send the profile data, maybe it weren't transmitted before
self::send_profile($importer["uid"], array($contact_record));
}
}
return true;
@ -1918,35 +2039,28 @@ class diaspora {
if (!$r) {
$server = "https://".substr($orig_author, strpos($orig_author, "@") + 1);
logger("1st try: reshared message ".$guid." will be fetched from original server: ".$server);
logger("1st try: reshared message ".$guid." will be fetched via SSL from the server ".$server);
$item_id = self::store_by_guid($guid, $server);
if (!$item_id) {
$server = "http://".substr($orig_author, strpos($orig_author, "@") + 1);
logger("2nd try: reshared message ".$guid." will be fetched from original server: ".$server);
logger("2nd try: reshared message ".$guid." will be fetched without SLL from the server ".$server);
$item_id = self::store_by_guid($guid, $server);
}
// Deactivated by now since there is a risk that someone could manipulate postings through this method
/* if (!$item_id) {
$server = "https://".substr($author, strpos($author, "@") + 1);
logger("3rd try: reshared message ".$guid." will be fetched from sharer's server: ".$server);
$item_id = self::store_by_guid($guid, $server);
}
if (!$item_id) {
$server = "http://".substr($author, strpos($author, "@") + 1);
logger("4th try: reshared message ".$guid." will be fetched from sharer's server: ".$server);
$item_id = self::store_by_guid($guid, $server);
}
*/
if ($item_id) {
$r = q("SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`,
`author-name`, `author-link`, `author-avatar`
FROM `item` WHERE `id` = %d AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
intval($item_id));
if ($r)
if ($r) {
// If it is a reshared post from another network then reformat to avoid display problems with two share elements
if (self::is_reshare($r[0]["body"], false))
$r[0]["body"] = diaspora2bb(bb2diaspora($r[0]["body"]));
return $r[0];
}
}
}
@ -1968,7 +2082,7 @@ class diaspora {
$guid = notags(unxmlify($data->guid));
$author = notags(unxmlify($data->author));
$public = notags(unxmlify($data->public));
$created_at = notags(unxmlify($data->created_at));
$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
$contact = self::allowed_contact_by_handle($importer, $author, false);
if (!$contact)
@ -1999,7 +2113,7 @@ class diaspora {
$datarray["owner-avatar"] = $datarray["author-avatar"];
$datarray["guid"] = $guid;
$datarray["uri"] = $datarray["parent-uri"] = $author.":".$guid;
$datarray["uri"] = $datarray["parent-uri"] = self::get_uri_from_guid($author, $guid);
$datarray["verb"] = ACTIVITY_POST;
$datarray["gravity"] = GRAVITY_PARENT;
@ -2015,7 +2129,7 @@ class diaspora {
$datarray["plink"] = self::plink($author, $guid);
$datarray["private"] = (($public == "false") ? 1 : 0);
$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert("UTC", "UTC", $created_at);
$datarray["changed"] = $datarray["created"] = $datarray["edited"] = $created_at;
$datarray["object-type"] = $original_item["object-type"];
@ -2055,12 +2169,6 @@ class diaspora {
if (!$r)
return false;
// Only delete it if the author really fits
if (!link_compare($r[0]["author-link"], $person["url"])) {
logger("Item author ".$r[0]["author-link"]." doesn't fit to expected contact ".$person["url"], LOGGER_DEBUG);
return false;
}
// Check if the sender is the thread owner
$p = q("SELECT `id`, `author-link`, `origin` FROM `item` WHERE `id` = %d",
intval($r[0]["parent"]));
@ -2084,7 +2192,7 @@ class diaspora {
// Now check if the retraction needs to be relayed by us
if($p[0]["origin"]) {
// notify others
proc_run("php", "include/notifier.php", "drop", $r[0]["id"]);
proc_run(PRIORITY_HIGH, "include/notifier.php", "drop", $r[0]["id"]);
}
return true;
@ -2142,12 +2250,11 @@ class diaspora {
* @return int The message id of the newly created item
*/
private function receive_status_message($importer, $data, $xml) {
$raw_message = unxmlify($data->raw_message);
$guid = notags(unxmlify($data->guid));
$author = notags(unxmlify($data->author));
$public = notags(unxmlify($data->public));
$created_at = notags(unxmlify($data->created_at));
$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
$provider_display_name = notags(unxmlify($data->provider_display_name));
/// @todo enable support for polls
@ -2201,7 +2308,7 @@ class diaspora {
$datarray["owner-avatar"] = $datarray["author-avatar"];
$datarray["guid"] = $guid;
$datarray["uri"] = $datarray["parent-uri"] = $author.":".$guid;
$datarray["uri"] = $datarray["parent-uri"] = self::get_uri_from_guid($author, $guid);
$datarray["verb"] = ACTIVITY_POST;
$datarray["gravity"] = GRAVITY_PARENT;
@ -2215,7 +2322,7 @@ class diaspora {
$datarray["plink"] = self::plink($author, $guid);
$datarray["private"] = (($public == "false") ? 1 : 0);
$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert("UTC", "UTC", $created_at);
$datarray["changed"] = $datarray["created"] = $datarray["edited"] = $created_at;
if (isset($address["address"]))
$datarray["location"] = $address["address"];
@ -2257,6 +2364,40 @@ class diaspora {
return $nick."@".substr(App::get_baseurl(), strpos(App::get_baseurl(),"://") + 3);
}
/**
* @brief Creates the envelope for the "fetch" endpoint
*
* @param string $msg The message that is to be transmitted
* @param array $user The record of the sender
*
* @return string The envelope
*/
public static function build_magic_envelope($msg, $user) {
$b64url_data = base64url_encode($msg);
$data = str_replace(array("\n", "\r", " ", "\t"), array("", "", "", ""), $b64url_data);
$key_id = base64url_encode(diaspora::my_handle($user));
$type = "application/xml";
$encoding = "base64url";
$alg = "RSA-SHA256";
$signable_data = $data.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg);
$signature = rsa_sign($signable_data, $user["prvkey"]);
$sig = base64url_encode($signature);
$xmldata = array("me:env" => array("me:data" => $data,
"@attributes" => array("type" => $type),
"me:encoding" => $encoding,
"me:alg" => $alg,
"me:sig" => $sig,
"@attributes2" => array("key_id" => $key_id)));
$namespaces = array("me" => "http://salmon-protocol.org/ns/magic-env");
return xml::from_array($xmldata, $xml, false, $namespaces);
}
/**
* @brief Creates the envelope for a public message
*
@ -2288,10 +2429,10 @@ class diaspora {
$sig = base64url_encode($signature);
$xmldata = array("diaspora" => array("header" => array("author_id" => $handle),
"me:env" => array("me:encoding" => "base64url",
"me:alg" => "RSA-SHA256",
"me:env" => array("me:encoding" => $encoding,
"me:alg" => $alg,
"me:data" => $data,
"@attributes" => array("type" => "application/xml"),
"@attributes" => array("type" => $type),
"me:sig" => $sig)));
$namespaces = array("" => "https://joindiaspora.com/protocol",
@ -2378,10 +2519,10 @@ class diaspora {
$cipher_json = base64_encode($encrypted_header_json_object);
$xmldata = array("diaspora" => array("encrypted_header" => $cipher_json,
"me:env" => array("me:encoding" => "base64url",
"me:alg" => "RSA-SHA256",
"me:env" => array("me:encoding" => $encoding,
"me:alg" => $alg,
"me:data" => $data,
"@attributes" => array("type" => "application/xml"),
"@attributes" => array("type" => $type),
"me:sig" => $sig)));
$namespaces = array("" => "https://joindiaspora.com/protocol",
@ -2499,6 +2640,20 @@ class diaspora {
}
/**
* @brief Build the post xml
*
* @param string $type The message type
* @param array $message The message data
*
* @return string The post XML
*/
public static function build_post_xml($type, $message) {
$data = array("XML" => array("post" => array($type => $message)));
return xml::from_array($data, $xml);
}
/**
* @brief Builds and transmit messages
*
@ -2514,13 +2669,15 @@ class diaspora {
*/
private function build_and_transmit($owner, $contact, $type, $message, $public_batch = false, $guid = "", $spool = false) {
$data = array("XML" => array("post" => array($type => $message)));
$msg = xml::from_array($data, $xml);
$msg = self::build_post_xml($type, $message);
logger('message: '.$msg, LOGGER_DATA);
logger('send guid '.$guid, LOGGER_DEBUG);
// Fallback if the private key wasn't transmitted in the expected field
if ($owner['uprvkey'] == "")
$owner['uprvkey'] = $owner['prvkey'];
$slap = self::build_message($msg, $owner, $contact, $owner['uprvkey'], $contact['pubkey'], $public_batch);
if ($spool) {
@ -2547,6 +2704,8 @@ class diaspora {
$message = array("sender_handle" => self::my_handle($owner),
"recipient_handle" => $contact["addr"]);
logger("Send share ".print_r($message, true), LOGGER_DEBUG);
return self::build_and_transmit($owner, $contact, "request", $message);
}
@ -2564,6 +2723,8 @@ class diaspora {
"diaspora_handle" => self::my_handle($owner),
"type" => "Person");
logger("Send unshare ".print_r($message, true), LOGGER_DEBUG);
return self::build_and_transmit($owner, $contact, "retraction", $message);
}
@ -2580,7 +2741,7 @@ class diaspora {
// Skip if it isn't a pure repeated messages
// Does it start with a share?
if (strpos($body, "[share") > 0)
if ((strpos($body, "[share") > 0) AND $complete)
return(false);
// Does it end with a share?
@ -2648,16 +2809,16 @@ class diaspora {
}
/**
* @brief Sends a post
* @brief Create a post (status message or reshare)
*
* @param array $item The item that will be exported
* @param array $owner the array of the item owner
* @param array $contact Target of the communication
* @param bool $public_batch Is it a public post?
*
* @return int The result of the transmission
* @return array
* 'type' -> Message type ("status_message" or "reshare")
* 'message' -> Array of XML elements of the status
*/
public static function send_status($item, $owner, $contact, $public_batch = false) {
public static function build_status($item, $owner) {
$myaddr = self::my_handle($owner);
@ -2720,8 +2881,24 @@ class diaspora {
$type = "status_message";
}
return array("type" => $type, "message" => $message);
}
return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
/**
* @brief Sends a post
*
* @param array $item The item that will be exported
* @param array $owner the array of the item owner
* @param array $contact Target of the communication
* @param bool $public_batch Is it a public post?
*
* @return int The result of the transmission
*/
public static function send_status($item, $owner, $contact, $public_batch = false) {
$status = diaspora::build_status($item, $owner);
return self::build_and_transmit($owner, $contact, $status["type"], $status["message"], $public_batch, $item["guid"]);
}
/**
@ -2736,7 +2913,7 @@ class diaspora {
$p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1",
dbesc($item["thr-parent"]));
if(!$p)
if(!dbm::is_result($p))
return false;
$parent = $p[0];
@ -2767,7 +2944,7 @@ class diaspora {
intval($item["parent"])
);
if (!$p)
if (!dbm::is_result($p))
return false;
$parent = $p[0];
@ -2981,7 +3158,7 @@ class diaspora {
intval($item["uid"])
);
if (!$r) {
if (!dbm::is_result($r)) {
logger("conversation not found.");
return;
}
@ -3034,11 +3211,12 @@ class diaspora {
*
* @param int $uid The user id
*/
public static function send_profile($uid) {
public static function send_profile($uid, $recips = false) {
if (!$uid)
return;
if (!$recips)
$recips = q("SELECT `id`,`name`,`network`,`pubkey`,`notify` FROM `contact` WHERE `network` = '%s'
AND `uid` = %d AND `rel` != %d",
dbesc(NETWORK_DIASPORA),
@ -3108,9 +3286,11 @@ class diaspora {
"searchable" => $searchable,
"tag_string" => $tags);
foreach($recips as $recip)
foreach($recips as $recip) {
logger("Send updated profile data for user ".$uid." to contact ".$recip["id"], LOGGER_DEBUG);
self::build_and_transmit($profile, $recip, "profile", $message, false, "", true);
}
}
/**
* @brief Stores the signature for likes that are created on our system

View file

@ -4,27 +4,33 @@ require_once('include/email.php');
require_once('include/bbcode.php');
require_once('include/html2bbcode.php');
/**
* @brief Creates a notification entry and possibly sends a mail
*
* @param array $params Array with the elements:
uid, item, parent, type, otype, verb, event,
link, subject, body, to_name, to_email, source_name,
source_link, activity, preamble, notify_flags,
language, show_in_notification_page
*/
function notification($params) {
#logger('notification()', LOGGER_DEBUG);
$a = get_app();
// from here on everything is in the recipients language
push_lang($params['language']);
$banner = t('Friendica Notification');
$product = FRIENDICA_PLATFORM;
$siteurl = $a->get_baseurl(true);
$thanks = t('Thank You,');
$sitename = $a->config['sitename'];
if (!x($a->config['admin_name'])) {
if (!x($a->config['admin_name']))
$site_admin = sprintf(t('%s Administrator'), $sitename);
} else {
else
$site_admin = sprintf(t('%1$s, %2$s Administrator'), $a->config['admin_name'], $sitename);
}
$nickname = "";
$sender_name = $sitename;
@ -33,9 +39,8 @@ function notification($params) {
$hostname = substr($hostname, 0, strpos($hostname, ':'));
$sender_email = $a->config['sender_email'];
if (empty($sender_email)) {
if (empty($sender_email))
$sender_email = t('noreply').'@'.$hostname;
}
$user = q("SELECT `nickname` FROM `user` WHERE `uid` = %d", intval($params['uid']));
if ($user)
@ -55,14 +60,11 @@ function notification($params) {
$additional_mail_header .= "List-ID: <notification.".$hostname.">\n";
$additional_mail_header .= "List-Archive: <".$a->get_baseurl()."/notifications/system>\n";
if (array_key_exists('item', $params)) {
$title = $params['item']['title'];
$body = $params['item']['body'];
}
else {
} else
$title = $body = '';
}
// e.g. "your post", "David's photo", etc.
$possess_desc = t('%s <!item_type!>');
@ -78,11 +80,11 @@ function notification($params) {
$parent_id = 0;
if ($params['type'] == NOTIFY_MAIL) {
$subject = sprintf(t('[Friendica:Notify] New mail received at %s'), $sitename);
$preamble = sprintf(t('%1$s sent you a new private message at %2$s.'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%1$s sent you %2$s.'), '[url='.$params['source_link'].']'.$params['source_name'].'[/url]', '[url=$itemlink]'.t('a private message').'[/url]');
$sitelink = t('Please visit %s to view and/or reply to your private messages.');
$tsitelink = sprintf($sitelink, $siteurl.'/message/'.$params['item']['id']);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'/message/'.$params['item']['id'].'">'.$sitename.'</a>');
@ -90,10 +92,6 @@ function notification($params) {
}
if ($params['type'] == NOTIFY_COMMENT) {
// logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
//$parent_id = $params['parent'];
$p = q("SELECT `ignored` FROM `thread` WHERE `iid` = %d AND `uid` = %d LIMIT 1",
intval($parent_id),
intval($params['uid'])
@ -107,7 +105,7 @@ function notification($params) {
// If so don't create a second notification
$p = null;
$p = q("select id from notify where (type = %d or type = %d or type = %d) and link = '%s' and uid = %d limit 1",
$p = q("SELECT `id` FROM `notify` WHERE (`type` = %d OR `type` = %d OR `type` = %d) AND `link` = '%s' AND `uid` = %d LIMIT 1",
intval(NOTIFY_TAGSELF),
intval(NOTIFY_COMMENT),
intval(NOTIFY_SHARE),
@ -119,20 +117,18 @@ function notification($params) {
return;
}
// if it's a post figure out who's post it is.
$p = null;
if ($params['otype'] === 'item' && $parent_id) {
$p = q("select * from item where id = %d and uid = %d limit 1",
$p = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($parent_id),
intval($params['uid'])
);
}
$item_post_type = item_post_type($p[0]);
//$possess_desc = str_replace('<!item_type!>',$possess_desc);
// "a post"
$dest_str = sprintf(t('%1$s commented on [url=%2$s]a %3$s[/url]'),
@ -161,6 +157,7 @@ function notification($params) {
// differents subjects for messages on the same thread.
$subject = sprintf(t('[Friendica:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $params['source_name']);
$preamble = sprintf(t('%s commented on an item/conversation you have been following.'), $params['source_name']);
$epreamble = $dest_str;
@ -174,7 +171,6 @@ function notification($params) {
$subject = sprintf(t('[Friendica:Notify] %s posted to your profile wall'), $params['source_name']);
$preamble = sprintf(t('%1$s posted to your profile wall at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%1$s posted to [url=%2$s]your wall[/url]'),
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$params['link']);
@ -187,6 +183,7 @@ function notification($params) {
if ($params['type'] == NOTIFY_TAGSELF) {
$subject = sprintf(t('[Friendica:Notify] %s tagged you'), $params['source_name']);
$preamble = sprintf(t('%1$s tagged you at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%1$s [url=%2$s]tagged you[/url].'),
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
@ -200,6 +197,7 @@ function notification($params) {
if ($params['type'] == NOTIFY_SHARE) {
$subject = sprintf(t('[Friendica:Notify] %s shared a new post'), $params['source_name']);
$preamble = sprintf(t('%1$s shared a new post at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%1$s [url=%2$s]shared a post[/url].'),
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
@ -212,8 +210,8 @@ function notification($params) {
}
if ($params['type'] == NOTIFY_POKE) {
$subject = sprintf(t('[Friendica:Notify] %1$s poked you'), $params['source_name']);
$preamble = sprintf(t('%1$s poked you at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%1$s [url=%2$s]poked you[/url].'),
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
@ -231,6 +229,7 @@ function notification($params) {
if ($params['type'] == NOTIFY_TAGSHARE) {
$subject = sprintf(t('[Friendica:Notify] %s tagged your post'), $params['source_name']);
$preamble = sprintf(t('%1$s tagged your post at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%1$s tagged [url=%2$s]your post[/url]'),
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
@ -244,10 +243,12 @@ function notification($params) {
if ($params['type'] == NOTIFY_INTRO) {
$subject = sprintf(t('[Friendica:Notify] Introduction received'));
$preamble = sprintf(t('You\'ve received an introduction from \'%1$s\' at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('You\'ve received [url=%1$s]an introduction[/url] from %2$s.'),
$itemlink,
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]');
$body = sprintf(t('You may visit their profile at %s'), $params['source_link']);
$sitelink = t('Please visit %s to approve or reject the introduction.');
@ -259,6 +260,7 @@ function notification($params) {
case ACTIVITY_FRIEND:
// someone started to share with user (mostly OStatus)
$subject = sprintf(t('[Friendica:Notify] A new person is sharing with you'));
$preamble = sprintf(t('%1$s is sharing with you at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%1$s is sharing with you at %2$s'),
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
@ -267,6 +269,7 @@ function notification($params) {
case ACTIVITY_FOLLOW:
// someone started to follow the user (mostly OStatus)
$subject = sprintf(t('[Friendica:Notify] You have a new follower'));
$preamble = sprintf(t('You have a new follower at %2$s : %1$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('You have a new follower at %2$s : %1$s'),
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
@ -276,12 +279,11 @@ function notification($params) {
// ACTIVITY_REQ_FRIEND is default activity for notifications
break;
}
}
if ($params['type'] == NOTIFY_SUGGEST) {
$subject = sprintf(t('[Friendica:Notify] Friend suggestion received'));
$preamble = sprintf(t('You\'ve received a friend suggestion from \'%1$s\' at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('You\'ve received [url=%1$s]a friend suggestion[/url] for %2$s from %3$s.'),
$itemlink,
@ -301,12 +303,13 @@ function notification($params) {
if ($params['type'] == NOTIFY_CONFIRM) {
if ($params['verb'] == ACTIVITY_FRIEND) { // mutual connection
$subject = sprintf(t('[Friendica:Notify] Connection accepted'));
$preamble = sprintf(t('\'%1$s\' has accepted your connection request at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%2$s has accepted your [url=%1$s]connection request[/url].'),
$itemlink,
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]');
$body = t('You are now mutual friends and may exchange status updates, photos, and email
without restriction.');
$body = t('You are now mutual friends and may exchange status updates, photos, and email without restriction.');
$sitelink = t('Please visit %s if you wish to make any changes to this relationship.');
$tsitelink = sprintf($sitelink, $siteurl);
@ -314,10 +317,12 @@ function notification($params) {
$itemlink = $params['link'];
} else { // ACTIVITY_FOLLOW
$subject = sprintf(t('[Friendica:Notify] Connection accepted'));
$preamble = sprintf(t('\'%1$s\' has accepted your connection request at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%2$s has accepted your [url=%1$s]connection request[/url].'),
$itemlink,
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]');
$body = sprintf(t('\'%1$s\' has chosen to accept you a "fan", which restricts some forms of communication - such as private messaging and some profile interactions. If this is a celebrity or community page, these settings were applied automatically.'), $params['source_name']);
$body .= "\n\n";
$body .= sprintf(t('\'%1$s\' may choose to extend this into a two-way or more permissive relationship in the future.'), $params['source_name']);
@ -327,17 +332,18 @@ function notification($params) {
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
$itemlink = $params['link'];
}
}
if ($params['type'] == NOTIFY_SYSTEM) {
switch($params['event']) {
case "SYSTEM_REGISTER_REQUEST":
$subject = sprintf(t('[Friendica System:Notify] registration request'));
$preamble = sprintf(t('You\'ve received a registration request from \'%1$s\' at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('You\'ve received a [url=%1$s]registration request[/url] from %2$s.'),
$itemlink,
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]');
$body = sprintf(t('Full Name: %1$s\nSite Location: %2$s\nLogin Name: %3$s (%4$s)'),
$params['source_name'], $siteurl, $params['source_mail'], $params['source_nick']);
@ -358,8 +364,11 @@ function notification($params) {
// password reset, invitations and so) using one look (but without
// add a notification to the user, with could be inexistent)
$subject = $params['subject'];
$preamble = $params['preamble'];
$body = $params['body'];
$sitelink = "";
$tsitelink = "";
$hsitelink = "";
@ -384,16 +393,17 @@ function notification($params) {
call_hooks('enotify', $h);
$subject = $h['subject'];
$preamble = $h['preamble'];
$epreamble = $h['epreamble'];
$body = $h['body'];
$sitelink = $h['sitelink'];
$tsitelink = $h['tsitelink'];
$hsitelink = $h['hsitelink'];
$itemlink = $h['itemlink'];
if ($show_in_notification_page) {
logger("adding notification entry", LOGGER_DEBUG);
do {
@ -401,11 +411,10 @@ function notification($params) {
$hash = random_string();
$r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' LIMIT 1",
dbesc($hash));
if(dba::is_result($r))
if(dbm::is_result($r))
$dups = true;
} while($dups == true);
$datarray = array();
$datarray['hash'] = $hash;
$datarray['name'] = $params['source_name'];
@ -430,7 +439,7 @@ function notification($params) {
// create notification entry in DB
$r = q("insert into notify (hash,name,url,photo,date,uid,link,iid,parent,type,verb,otype)
$r = q("INSERT INTO `notify` (`hash`, `name`, `url`, `photo`, `date`, `uid`, `link`, `iid`, `parent`, `type`, `verb`, `otype`)
values('%s', '%s', '%s', '%s', '%s', %d, '%s', %d, %d, %d, '%s', '%s')",
dbesc($datarray['hash']),
dbesc($datarray['name']),
@ -446,7 +455,7 @@ function notification($params) {
dbesc($datarray['otype'])
);
$r = q("select id from notify where hash = '%s' and uid = %d limit 1",
$r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' AND `uid` = %d LIMIT 1",
dbesc($hash),
intval($params['uid'])
);
@ -461,7 +470,7 @@ function notification($params) {
// After we've stored everything, look again to see if there are any duplicates and if so remove them
$p = null;
$p = q("select id from notify where ( type = %d or type = %d ) and link = '%s' and uid = %d order by id",
$p = q("SELECT `id` FROM `notify` WHERE (`type` = %d OR `type` = %d) AND `link` = '%s' AND `uid` = %d ORDER BY `id`",
intval(NOTIFY_TAGSELF),
intval(NOTIFY_COMMENT),
dbesc($params['link']),
@ -469,7 +478,7 @@ function notification($params) {
);
if ($p && (count($p) > 1)) {
for ($d = 1; $d < count($p); $d ++) {
q("delete from notify where id = %d",
q("DELETE FROM `notify` WHERE `id` = %d",
intval($p[$d]['id'])
);
}
@ -485,12 +494,11 @@ function notification($params) {
$itemlink = $a->get_baseurl().'/notify/view/'.$notify_id;
$msg = replace_macros($epreamble, array('$itemlink' => $itemlink));
$r = q("update notify set msg = '%s' where id = %d and uid = %d",
$r = q("UPDATE `notify` SET `msg` = '%s' WHERE `id` = %d AND `uid` = %d",
dbesc($msg),
intval($notify_id),
intval($params['uid'])
);
}
// send email notification if notification preferences permit
@ -505,7 +513,7 @@ function notification($params) {
// Is this the first email notification for this parent item and user?
$r = q("select `id` from `notify-threads` where `master-parent-item` = %d and `receiver-uid` = %d limit 1",
$r = q("SELECT `id` FROM `notify-threads` WHERE `master-parent-item` = %d AND `receiver-uid` = %d LIMIT 1",
intval($params['parent']),
intval($params['uid']));
@ -513,7 +521,7 @@ function notification($params) {
if (!$r) {
logger("notify_id:".intval($notify_id).", parent: ".intval($params['parent'])."uid: ".intval($params['uid']), LOGGER_DEBUG);
$r = q("insert into `notify-threads` (`notify-id`, `master-parent-item`, `receiver-uid`, `parent-item`)
$r = q("INSERT INTO `notify-threads` (`notify-id`, `master-parent-item`, `receiver-uid`, `parent-item`)
values(%d, %d, %d, %d)",
intval($notify_id),
intval($params['parent']),
@ -531,14 +539,12 @@ function notification($params) {
}
}
// textversion keeps linebreaks
$textversion = strip_tags(str_replace("<br>", "\n", html_entity_decode(bbcode(stripslashes(str_replace(array("\\r\\n", "\\r", "\\n"), "\n",
$body))),ENT_QUOTES, 'UTF-8')));
$htmlversion = html_entity_decode(bbcode(stripslashes(str_replace(array("\\r\\n", "\\r", "\\n\\n", "\\n"),
"<br />\n", $body))), ENT_QUOTES, 'UTF-8');
$datarray = array();
$datarray['banner'] = $banner;
$datarray['product'] = $product;
@ -612,8 +618,6 @@ function notification($params) {
'$content_allowed' => $content_allowed,
));
// logger('text: ' . $email_text_body);
// use the Emailer class to send the message
return Emailer::send(array(
@ -630,7 +634,6 @@ function notification($params) {
}
return False;
}
/**
@ -647,7 +650,7 @@ function check_item_notification($itemid, $uid, $defaulttype = "") {
$profiles = $notification_data["profiles"];
$user = q("SELECT `notify-flags`, `language`, `username`, `email` FROM `user` WHERE `uid` = %d", intval($uid));
$user = q("SELECT `notify-flags`, `language`, `username`, `email`, `nickname` FROM `user` WHERE `uid` = %d", intval($uid));
if (!$user)
return false;
@ -655,13 +658,30 @@ function check_item_notification($itemid, $uid, $defaulttype = "") {
if (!$owner)
return false;
// This is our regular URL format
$profiles[] = $owner[0]["url"];
// Notifications from Diaspora are often with an URL in the Diaspora format
$profiles[] = App::get_baseurl()."/u/".$user[0]["nickname"];
$profiles2 = array();
foreach ($profiles AS $profile) {
$profiles2[] = normalise_link($profile);
$profiles2[] = str_replace("http://", "https://", normalise_link($profile));
// Check for invalid profile urls. 13 should be the shortest possible profile length:
// http://a.bc/d
// Additionally check for invalid urls that would return the normalised value "http:"
if ((strlen($profile) >= 13) AND (normalise_link($profile) != "http:")) {
if (!in_array($profile, $profiles2))
$profiles2[] = $profile;
$profile = normalise_link($profile);
if (!in_array($profile, $profiles2))
$profiles2[] = $profile;
$profile = str_replace("http://", "https://", $profile);
if (!in_array($profile, $profiles2))
$profiles2[] = $profile;
}
}
$profiles = $profiles2;
@ -708,17 +728,17 @@ function check_item_notification($itemid, $uid, $defaulttype = "") {
intval($item[0]['contact-id']),
intval($uid)
);
$send_notification = count($r);
$send_notification = dbm::is_result($r);
if (!$send_notification) {
$tags = q("SELECT `url` FROM `term` WHERE `otype` = %d AND `oid` = %d AND `type` = %d AND `uid` = %d",
intval(TERM_OBJ_POST), intval($itemid), intval(TERM_MENTION), intval($uid));
if (count($tags)) {
if (dbm::is_result($tags)) {
foreach ($tags AS $tag) {
$r = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND `notify_new_posts`",
normalise_link($tag["url"]), intval($uid));
if (dba::is_result($r))
if (dbm::is_result($r))
$send_notification = true;
}
}

View file

@ -1,12 +1,15 @@
<?php
/**
* @file include/event.php
* @brief functions specific to event handling
*/
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)))
return '';
@ -276,7 +279,7 @@ function event_store($arr) {
intval($arr['id']),
intval($arr['uid'])
);
return((dba::is_result($r)) ? $r[0]['id'] : 0);
return((dbm::is_result($r)) ? $r[0]['id'] : 0);
}
// The event changed. Update it.
@ -290,11 +293,7 @@ function event_store($arr) {
`location` = '%s',
`type` = '%s',
`adjust` = %d,
`nofinish` = %d,
`allow_cid` = '%s',
`allow_gid` = '%s',
`deny_cid` = '%s',
`deny_gid` = '%s'
`nofinish` = %d
WHERE `id` = %d AND `uid` = %d",
dbesc($arr['edited']),
@ -306,10 +305,6 @@ function event_store($arr) {
dbesc($arr['type']),
intval($arr['adjust']),
intval($arr['nofinish']),
dbesc($arr['allow_cid']),
dbesc($arr['allow_gid']),
dbesc($arr['deny_cid']),
dbesc($arr['deny_gid']),
intval($arr['id']),
intval($arr['uid'])
);
@ -317,28 +312,22 @@ function event_store($arr) {
intval($arr['id']),
intval($arr['uid'])
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$object = '<object><type>' . xmlify(ACTIVITY_OBJ_EVENT) . '</type><title></title><id>' . xmlify($arr['uri']) . '</id>';
$object .= '<content>' . xmlify(format_event_bbcode($arr)) . '</content>';
$object .= '</object>' . "\n";
q("UPDATE `item` SET `body` = '%s', `object` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `edited` = '%s', `private` = %d WHERE `id` = %d AND `uid` = %d",
q("UPDATE `item` SET `body` = '%s', `object` = '%s', `edited` = '%s' WHERE `id` = %d AND `uid` = %d",
dbesc(format_event_bbcode($arr)),
dbesc($object),
dbesc($arr['allow_cid']),
dbesc($arr['allow_gid']),
dbesc($arr['deny_cid']),
dbesc($arr['deny_gid']),
dbesc($arr['edited']),
intval($arr['private']),
intval($r[0]['id']),
intval($arr['uid'])
);
$item_id = $r[0]['id'];
}
else
} else
$item_id = 0;
call_hooks("event_updated", $arr['id']);
@ -376,7 +365,7 @@ function event_store($arr) {
dbesc($arr['uri']),
intval($arr['uid'])
);
if(dba::is_result($r))
if(dbm::is_result($r))
$event = $r[0];
$item_arr = array();
@ -418,7 +407,7 @@ function event_store($arr) {
$r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1",
intval($arr['uid'])
);
//if(dba::is_result($r))
//if(dbm::is_result($r))
// $plink = $a->get_baseurl() . '/display/' . $r[0]['nickname'] . '/' . $item_id;
@ -441,3 +430,420 @@ function event_store($arr) {
return $item_id;
}
}
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;
$i18n = array(
"firstDay" => $firstDay,
"Sun" => t("Sun"),
"Mon" => t("Mon"),
"Tue" => t("Tue"),
"Wed" => t("Wed"),
"Thu" => t("Thu"),
"Fri" => t("Fri"),
"Sat" => t("Sat"),
"Sunday" => t("Sunday"),
"Monday" => t("Monday"),
"Tuesday" => t("Tuesday"),
"Wednesday" => t("Wednesday"),
"Thursday" => t("Thursday"),
"Friday" => t("Friday"),
"Saturday" => t("Saturday"),
"Jan" => t("Jan"),
"Feb" => t("Feb"),
"Mar" => t("Mar"),
"Apr" => t("Apr"),
"May" => t("May"),
"Jun" => t("Jun"),
"Jul" => t("Jul"),
"Aug" => t("Aug"),
"Sep" => t("Sept"),
"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"),
"September" => t("September"),
"October" => t("October"),
"November" => t("November"),
"December" => t("December"),
"today" => t("today"),
"month" => t("month"),
"week" => t("week"),
"day" => t("day"),
);
return $i18n;
}
/**
* @brief Get an event by its event ID
*
* @param type $owner_uid The User ID of the owner of the event
* @param type $event_params An assoziative array with
* int 'event_id' => The ID of the event in the event table
* @param type $sql_extra
* @return array Query result
*/
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)
return;
// 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`
WHERE `event`.`uid` = %d AND `event`.`id` = %d $sql_extra",
intval($owner_uid),
intval($event_params["event_id"])
);
if(count($r))
return $r;
}
/**
* @brief Get all events in a specific timeframe
*
* @param int $owner_uid The User ID of the owner of the events
* @param array $event_params An assoziative array with
* int 'ignored' =>
* string 'start' => Start time of the timeframe
* string 'finish' => Finish time of the timeframe
* string 'adjust_start' =>
* string 'adjust_start' =>
*
* @param string $sql_extra Additional sql conditions (e.g. permission request)
* @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)
return;
// 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`
WHERE `event`.`uid` = %d AND event.ignore = %d
AND ((`adjust` = 0 AND (`finish` >= '%s' OR (nofinish AND start >= '%s')) AND `start` <= '%s')
OR (`adjust` = 1 AND (`finish` >= '%s' OR (nofinish AND start >= '%s')) AND `start` <= '%s'))
$sql_extra ",
intval($owner_uid),
intval($event_params["ignored"]),
dbesc($event_params["start"]),
dbesc($event_params["start"]),
dbesc($event_params["finish"]),
dbesc($event_params["adjust_start"]),
dbesc($event_params["adjust_start"]),
dbesc($event_params["adjust_finish"])
);
if(count($r))
return $r;
}
/**
* @brief Convert an array query results in an arry which could be used by the events template
*
* @param array $arr Event query array
* @return array Event array for the template
*/
function process_events ($arr) {
$events=array();
$last_date = '';
$fmt = t('l, F j');
if (count($arr)) {
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));
$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']){
$end = null;
} else {
$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'));
}
$html = format_event_html($rr);
$rr['desc'] = bbcode($rr['desc']);
$rr['location'] = bbcode($rr['location']);
$events[] = array(
'id'=>$rr['id'],
'start'=> $start,
'end' => $end,
'allDay' => false,
'title' => $title,
'j' => $j,
'd' => $d,
'is_first'=>$is_first,
'item'=>$rr,
'html'=>$html,
'plink' => array($rr['plink'],t('link to source'),'',''),
);
}
}
return $events;
}
/**
* @brief Format event to export format (ical/csv)
*
* @param array $events Query result for events
* @param string $format The output format (ical/csv)
* @param string $timezone The timezone of the user (not implemented yet)
*
* @return string Content according to selected export format
*/
function event_format_export ($events, $format = 'ical', $timezone) {
if(! ((is_array($events)) && count($events)))
return;
switch ($format) {
// 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 :-/
$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;
}
break;
// format the exported data as a ics file
case "ical":
header("Content-type: text/ics");
$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
// see http://tools.ietf.org/html/rfc2445#section-4.8.3
// . 'BEGIN:VTIMEZONE' . PHP_EOL
// . 'TZID:' . $timezone . PHP_EOL
// . 'END:VTIMEZONE' . PHP_EOL;
// TODO instead of PHP_EOL CRLF should be used for long entries
// 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]) {
$tmp = strtotime($event['start']);
$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;
}
if ($event['summary'])
$tmp = $event['summary'];
$tmp = str_replace(PHP_EOL, PHP_EOL.' ',$tmp);
$tmp = addcslashes($tmp, ',;');
$o .= 'SUMMARY:' . $tmp . PHP_EOL;
if ($event['desc'])
$tmp = $event['desc'];
$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 = addcslashes($tmp, ',;');
$o .= 'LOCATION:' . $tmp . PHP_EOL;
}
$o .= 'END:VEVENT' . PHP_EOL;
$o .= PHP_EOL;
}
$o .= 'END:VCALENDAR' . PHP_EOL;
break;
}
return $o;
}
/**
* @brief Get all events for a user ID
*
* The query for events is done permission sensitive
* If the user is the owner of the calendar he/she
* will get all of his/her available events.
* If the user is only a visitor only the public events will
* be available
*
* @param int $uid The user ID
* @param int $sql_extra Additional sql conditions for permission
*
* @return array Query results
*/
function events_by_uid($uid = 0, $sql_extra = '') {
if($uid == 0)
return;
// The permission condition if no condition was transmitted
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
if (local_user() == $uid) {
$r = q("SELECT `start`, `finish`, `adjust`, `summary`, `desc`, `location`, `nofinish`
FROM `event` WHERE `uid`= %d AND `cid` = 0 ",
intval($uid)
);
} else {
$r = q("SELECT `start`, `finish`, `adjust`, `summary`, `desc`, `location`, `nofinish`
FROM `event` WHERE `uid`= %d AND `cid` = 0 $sql_extra ",
intval($uid)
);
}
if(count($r))
return $r;
}
/**
*
* @param int $uid The user ID
* @param string $format Output format (ical/csv)
* @return array With the results
* bool 'success' => True if the processing was successful
* string 'format' => The output format
* string 'extension' => The file extension of the output format
* string 'content' => The formatted output content
*
* @todo Respect authenticated users with events_by_uid()
*/
function event_export($uid, $format = 'ical') {
$process = false;
// 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 (count($r))
$timezone = $r[0]['timezone'];
// 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))
$res = event_format_export($events, $format, $timezone);
// If there are results the precess was successfull
if(x($res))
$process = true;
// get the file extension for the format
switch ($format) {
case "ical":
$file_ext = "ics";
break;
case "csv":
$file_ext = "csv";
break;
default:
$file_ext = "";
}
$arr = array(
'success' => $process,
'format' => $format,
'extension' => $file_ext,
'content' => $res,
);
return $arr;
}
/**
* @brief Get the events widget
*
* @return string Formated html of the evens widget
*/
function widget_events() {
$a = get_app();
$owner_uid = $a->data['user']['uid'];
// $a->data is only available if the profile page is visited. If the visited page is not part
// of the profile page it should be the personal /events page. So we can use $a->user
$user = ($a->data['user']['nickname'] ? $a->data['user']['nickname'] : $a->user['nickname']);
// 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)
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)
// So we have to test if if it's the own profile page of the logged in user
// 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"))
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"))
return;
return replace_macros(get_markup_template("events_aside.tpl"), array(
'$etitle' => t("Export"),
'$export_ical' => t("Export calendar as ical"),
'$export_csv' => t("Export calendar as csv"),
'$user' => $user
));
}

View file

@ -39,7 +39,7 @@ function expire_run(&$argv, &$argc){
logger('expire: start');
$r = q("SELECT `uid`,`username`,`expire` FROM `user` WHERE `expire` != 0");
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $rr) {
logger('Expire: ' . $rr['username'] . ' interval: ' . $rr['expire'], LOGGER_DEBUG);
item_expire($rr['uid'],$rr['expire']);

View file

@ -10,7 +10,7 @@ function fcontact_store($url,$name,$photo) {
dbesc($nurl)
);
if(dba::is_result($r))
if(dbm::is_result($r))
return $r[0]['id'];
$r = q("INSERT INTO `fcontact` ( `url`, `name`, `photo` ) VALUES ( '%s', '%s', '%s' ) ",
@ -23,7 +23,7 @@ function fcontact_store($url,$name,$photo) {
$r = q("SELECT `id` FROM `fcontact` WHERE `url` = '%s' LIMIT 1",
dbesc($nurl)
);
if(dba::is_result($r))
if(dbm::is_result($r))
return $r[0]['id'];
}

View file

@ -64,6 +64,7 @@ function get_features($filtered = true) {
//array('expire', t('Content Expiration'), t('Remove old posts/comments after a period of time')),
array('multi_profiles', t('Multiple Profiles'), t('Ability to create multiple profiles'), false, get_config('feature_lock','multi_profiles')),
array('photo_location', t('Photo Location'), t('Photo metadata is normally stripped. This extracts the location (if present) prior to stripping metadata and links it to a map.'), false, get_config('feature_lock','photo_location')),
array('export_calendar', t('Export Public Calendar'), t('Ability for visitors to download the public calendar'), false, get_config('feature_lock','export_calendar')),
),
// Post composition

View file

@ -17,10 +17,15 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
$a = get_app();
logger("Import Atom/RSS feed", LOGGER_DEBUG);
if (!$simulate)
logger("Import Atom/RSS feed '".$contact["name"]."' (Contact ".$contact["id"].") for user ".$importer["uid"], LOGGER_DEBUG);
else
logger("Test Atom/RSS feed", LOGGER_DEBUG);
if ($xml == "")
if ($xml == "") {
logger('XML is empty.', LOGGER_DEBUG);
return;
}
$doc = new DOMDocument();
@$doc->loadXML($xml);
@ -84,10 +89,23 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
if ($value != "")
$author["author-name"] = $value;
if ($simulate) {
$author["author-id"] = $xpath->evaluate('/atom:feed/atom:author/atom:uri/text()')->item(0)->nodeValue;
$value = $xpath->evaluate('atom:author/poco:preferredUsername/text()')->item(0)->nodeValue;
if ($value != "")
$author["author-nick"] = $value;
$value = $xpath->evaluate('atom:author/poco:address/poco:formatted/text()', $context)->item(0)->nodeValue;
if ($value != "")
$author["author-location"] = $value;
$value = $xpath->evaluate('atom:author/poco:note/text()')->item(0)->nodeValue;
if ($value != "")
$author["author-about"] = $value;
}
$author["edited"] = $author["created"] = $xpath->query('/atom:feed/atom:updated/text()')->item(0)->nodeValue;
$author["app"] = $xpath->evaluate('/atom:feed/atom:generator/text()')->item(0)->nodeValue;
@ -150,8 +168,10 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
$header["last-child"] = 0;
}
if (!is_object($entries))
if (!is_object($entries)) {
logger("There are no entries in this feed.", LOGGER_DEBUG);
return;
}
$items = array();

View file

@ -178,7 +178,7 @@ function new_contact($uid,$url,$interactive = false) {
intval($uid), dbesc(normalise_link($url)), dbesc($ret['network'])
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
// update contact
if($r[0]['rel'] == CONTACT_IS_FOLLOWER || ($network === NETWORK_DIASPORA && $r[0]['rel'] == CONTACT_IS_SHARING)) {
q("UPDATE `contact` SET `rel` = %d , `subhub` = %d, `readonly` = 0 WHERE `id` = %d AND `uid` = %d",
@ -196,7 +196,7 @@ function new_contact($uid,$url,$interactive = false) {
$r = q("select count(*) as total from contact where uid = %d and pending = 0 and self = 0",
intval($uid)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$total_contacts = $r[0]['total'];
if(! service_class_allows($uid,'total_contacts',$total_contacts)) {
@ -208,7 +208,7 @@ function new_contact($uid,$url,$interactive = false) {
intval($uid),
dbesc($network)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$total_network = $r[0]['total'];
if(! service_class_allows($uid,'total_contacts_' . $network,$total_network)) {
@ -270,7 +270,7 @@ function new_contact($uid,$url,$interactive = false) {
// pull feed and consume it, which should subscribe to the hub.
proc_run('php',"include/onepoll.php","$contact_id", "force");
proc_run(PRIORITY_MEDIUM, "include/onepoll.php", $contact_id, "force");
// create a follow slap
@ -295,7 +295,7 @@ function new_contact($uid,$url,$interactive = false) {
intval($uid)
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
if(($contact['network'] == NETWORK_OSTATUS) && (strlen($contact['notify']))) {
require_once('include/salmon.php');
slapper($r[0],$contact['notify'],$slap);

View file

@ -65,7 +65,7 @@ function gprobe_run(&$argv, &$argc){
dbesc(normalise_link($url))
);
}
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
// Check for accessibility and do a poco discovery
if (poco_last_updated($r[0]['url'], true) AND ($r[0]["network"] == NETWORK_DFRN))
poco_load(0,0,$r[0]['id'], str_replace('/profile/','/poco/',$r[0]['url']));

View file

@ -44,7 +44,7 @@ function group_rmv($uid,$name) {
intval($uid),
dbesc($name)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$group_id = $r[0]['id'];
if(! $group_id)
return false;
@ -106,7 +106,7 @@ function group_byname($uid,$name) {
intval($uid),
dbesc($name)
);
if(dba::is_result($r))
if(dbm::is_result($r))
return $r[0]['id'];
return false;
}
@ -139,7 +139,7 @@ function group_add_member($uid,$name,$member,$gid = 0) {
intval($gid),
intval($member)
);
if(dba::is_result($r))
if(dbm::is_result($r))
return true; // You might question this, but
// we indicate success because the group member was in fact created
// -- It was just created at another time
@ -164,7 +164,7 @@ function group_get_members($gid) {
intval($gid),
intval(local_user())
);
if(dba::is_result($r))
if(dbm::is_result($r))
$ret = $r;
}
return $ret;
@ -181,7 +181,7 @@ function group_public_members($gid) {
intval(local_user()),
dbesc(NETWORK_OSTATUS)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$ret = count($r);
}
return $ret;
@ -197,7 +197,7 @@ function mini_group_select($uid,$gid = 0, $label = "") {
intval($uid)
);
$grps[] = array('name' => '', 'id' => '0', 'selected' => '');
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $rr) {
$grps[] = array('name' => $rr['name'], 'id' => $rr['id'], 'selected' => (($gid == $rr['id']) ? 'true' : ''));
}
@ -255,7 +255,7 @@ function group_side($every="contacts",$each="group",$editmode = "standard", $gro
$member_of = groups_containing(local_user(),$cid);
}
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $rr) {
$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
@ -316,7 +316,7 @@ function expand_groups($a,$check_dead = false, $use_gcontact = false) {
$ret = array();
if(dba::is_result($r))
if(dbm::is_result($r))
foreach($r as $rr)
$ret[] = $rr['contact-id'];
if($check_dead AND !$use_gcontact) {
@ -345,7 +345,7 @@ function groups_containing($uid,$c) {
);
$ret = array();
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $rr)
$ret[] = $rr['gid'];
}
@ -366,7 +366,7 @@ function groups_containing($uid,$c) {
function groups_count_unseen() {
$r = q("SELECT `group`.`id`, `group`.`name`,
(SELECT COUNT(*) FROM `item`
(SELECT COUNT(*) FROM `item` FORCE INDEX (`uid_unseen_contactid`)
WHERE `uid` = %d AND `unseen` AND
`contact-id` IN (SELECT `contact-id` FROM `group_member`
WHERE `group_member`.`gid` = `group`.`id` AND `group_member`.`uid` = %d)) AS `count`

View file

@ -71,8 +71,8 @@ function profile_load(&$a, $nickname, $profile = 0, $profiledata = array()) {
$a->page['title'] = $a->profile['name'] . " @ " . $a->config['sitename'];
// if (!$profiledata)
// $_SESSION['theme'] = $a->profile['theme'];
if (!$profiledata && !get_pconfig(local_user(),'system','always_my_theme'))
$_SESSION['theme'] = $a->profile['theme'];
$_SESSION['mobile-theme'] = $a->profile['mobile-theme'];
@ -138,7 +138,7 @@ function get_profiledata_by_nick($nickname, $uid = 0, $profile = 0) {
$r = q("SELECT `profile-id` FROM `contact` WHERE `id` = %d LIMIT 1",
intval($visitor['cid'])
);
if(dba::is_result($r))
if(dbm::is_result($r))
$profile = $r[0]['profile-id'];
break;
}
@ -230,7 +230,7 @@ function profile_sidebar($profile, $block = 0) {
$r = q("SELECT * FROM `contact` WHERE NOT `pending` AND `uid` = %d AND `nurl` = '%s'",
local_user(), $profile_url);
if (dba::is_result($r))
if (dbm::is_result($r))
$connect = false;
}
@ -246,10 +246,30 @@ function profile_sidebar($profile, $block = 0) {
else
$subscribe_feed = false;
if(get_my_url() && $profile['unkmail'] && ($profile['uid'] != local_user()))
if (remote_user() OR (get_my_url() && $profile['unkmail'] && ($profile['uid'] != local_user()))) {
$wallmessage = t('Message');
else
$wallmessage_link = "wallmessage/".$profile["nickname"];
if (remote_user()) {
$r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND `id` = '%s' AND `rel` = %d",
intval($profile['uid']),
intval(remote_user()),
intval(CONTACT_IS_FRIEND));
} else {
$r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `rel` = %d",
intval($profile['uid']),
dbesc(normalise_link(get_my_url())),
intval(CONTACT_IS_FRIEND));
}
if ($r) {
$remote_url = $r[0]["url"];
$message_path = preg_replace("=(.*)/profile/(.*)=ism", "$1/message/new/", $remote_url);
$wallmessage_link = $message_path.base64_encode($profile["addr"]);
}
} else {
$wallmessage = false;
$wallmessage_link = false;
}
// show edit profile to yourself
if ($profile['uid'] == local_user() && feature_enabled(local_user(),'multi_profiles')) {
@ -263,7 +283,7 @@ function profile_sidebar($profile, $block = 0) {
'entries' => array(),
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $rr) {
$profile['menu']['entries'][] = array(
@ -325,6 +345,7 @@ function profile_sidebar($profile, $block = 0) {
? trim(substr($profile['name'],0,strpos($profile['name'],' '))) : $profile['name']);
$lastname = (($firstname === $profile['name']) ? '' : trim(substr($profile['name'],strlen($firstname))));
if ($profile['guid'] != "")
$diaspora = array(
'guid' => $profile['guid'],
'podloc' => $a->get_baseurl(),
@ -337,6 +358,8 @@ function profile_sidebar($profile, $block = 0) {
'photo100' => $a->get_baseurl() . '/photo/custom/100/' . $profile['uid'] . '.jpg',
'photo50' => $a->get_baseurl() . '/photo/custom/50/' . $profile['uid'] . '.jpg',
);
else
$diaspora = false;
if (!$block){
$contact_block = contact_block();
@ -344,7 +367,7 @@ function profile_sidebar($profile, $block = 0) {
if(is_array($a->profile) AND !$a->profile['hide-friends']) {
$r = q("SELECT `gcontact`.`updated` FROM `contact` INNER JOIN `gcontact` WHERE `gcontact`.`nurl` = `contact`.`nurl` AND `self` AND `uid` = %d LIMIT 1",
intval($a->profile['uid']));
if(dba::is_result($r))
if(dbm::is_result($r))
$updated = date("c", strtotime($r[0]['updated']));
$r = q("SELECT COUNT(*) AS `total` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `hidden` = 0 AND `archive` = 0
@ -354,7 +377,7 @@ function profile_sidebar($profile, $block = 0) {
dbesc(NETWORK_DIASPORA),
dbesc(NETWORK_OSTATUS)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$contacts = intval($r[0]['total']);
}
}
@ -386,6 +409,7 @@ function profile_sidebar($profile, $block = 0) {
'$remoteconnect' => $remoteconnect,
'$subscribe_feed' => $subscribe_feed,
'$wallmessage' => $wallmessage,
'$wallmessage_link' => $wallmessage_link,
'$account_type' => $account_type,
'$location' => $location,
'$gender' => $gender,
@ -400,7 +424,6 @@ function profile_sidebar($profile, $block = 0) {
'$contact_block' => $contact_block,
));
$arr = array('profile' => &$profile, 'entry' => &$o);
call_hooks('profile_sidebar', $arr);
@ -664,6 +687,8 @@ function advanced_profile(&$a) {
return replace_macros($tpl, array(
'$title' => t('Profile'),
'$basic' => t('Basic'),
'$advanced' => t('Advanced'),
'$profile' => $profile
));
}
@ -717,8 +742,8 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){
),
);
if ($is_owner){
if ($a->theme_events_in_profile)
// the calendar link for the full featured events calendar
if ($is_owner && $a->theme_events_in_profile) {
$tabs[] = array(
'label' => t('Events'),
'url' => $a->get_baseurl() . '/events',
@ -727,6 +752,20 @@ function profile_tabs($a, $is_owner=False, $nickname=Null){
'id' => 'events-tab',
'accesskey' => 'e',
);
// if the user is not the owner of the calendar we only show a calendar
// with the public events of the calendar owner
} elseif (! $is_owner) {
$tabs[] = array(
'label' => t('Events'),
'url' => $a->get_baseurl() . '/cal/' . $nickname,
'sel' =>((!isset($tab)&&$a->argv[0]=='cal')?'active':''),
'title' => t('Events and Calendar'),
'id' => 'events-tab',
'accesskey' => 'e',
);
}
if ($is_owner){
$tabs[] = array(
'label' => t('Personal Notes'),
'url' => $a->get_baseurl() . '/notes',
@ -779,7 +818,7 @@ function zrl_init(&$a) {
}
}
proc_run('php','include/gprobe.php',bin2hex($tmp_str));
proc_run(PRIORITY_LOW, 'include/gprobe.php',bin2hex($tmp_str));
$arr = array('zrl' => $tmp_str, 'url' => $a->cmd);
call_hooks('zrl_init',$arr);
}

View file

@ -413,7 +413,7 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
/* check for create date and expire time */
$uid = intval($arr['uid']);
$r = q("SELECT expire FROM user WHERE uid = %d", intval($uid));
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$expire_interval = $r[0]['expire'];
if ($expire_interval>0) {
$expire_date = new DateTime( '- '.$expire_interval.' days', new DateTimeZone('UTC'));
@ -507,6 +507,13 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
$arr['inform'] = ((x($arr,'inform')) ? trim($arr['inform']) : '');
$arr['file'] = ((x($arr,'file')) ? trim($arr['file']) : '');
// Items cannot be stored before they happen ...
if ($arr['created'] > datetime_convert())
$arr['created'] = datetime_convert();
// We haven't invented time travel by now.
if ($arr['edited'] > datetime_convert())
$arr['edited'] = datetime_convert();
if (($arr['author-link'] == "") AND ($arr['owner-link'] == ""))
logger("Both author-link and owner-link are empty. Called by: ".App::callstack(), LOGGER_DEBUG);
@ -535,7 +542,7 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
intval($arr['uid'])
);
if(dba::is_result($r))
if(dbm::is_result($r))
$arr['network'] = $r[0]["network"];
// Fallback to friendica (why is it empty in some cases?)
@ -577,13 +584,19 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
"photo" => $arr['author-avatar'], "name" => $arr['author-name']));
}
if ($arr["author-id"] == 0)
$arr["author-id"] = get_contact($arr["author-link"], 0);
if ($arr["owner-id"] == 0)
$arr["owner-id"] = get_contact($arr["owner-link"], 0);
if ($arr['guid'] != "") {
// Checking if there is already an item with the same guid
logger('checking for an item for user '.$arr['uid'].' on network '.$arr['network'].' with the guid '.$arr['guid'], LOGGER_DEBUG);
$r = q("SELECT `guid` FROM `item` WHERE `guid` = '%s' AND `network` = '%s' AND `uid` = '%d' LIMIT 1",
dbesc($arr['guid']), dbesc($arr['network']), intval($arr['uid']));
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
logger('found item with guid '.$arr['guid'].' for user '.$arr['uid'].' on network '.$arr['network'], LOGGER_DEBUG);
return 0;
}
@ -612,7 +625,7 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
intval($arr['uid'])
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
// is the new message multi-level threaded?
// even though we don't support it now, preserve the info
@ -768,7 +781,7 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
intval($r[0]["id"])
);
return 0;
} elseif(dba::is_result($r)) {
} elseif(dbm::is_result($r)) {
$current_post = $r[0]['id'];
logger('item_store: created item ' . $current_post);
@ -904,7 +917,7 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
check_item_notification($current_post, $uid);
if ($notify)
proc_run('php', "include/notifier.php", $notify_type, $current_post);
proc_run(PRIORITY_HIGH, "include/notifier.php", $notify_type, $current_post);
return $current_post;
}
@ -979,7 +992,7 @@ function item_body_set_hashtags(&$item) {
function get_item_guid($id) {
$r = q("SELECT `guid` FROM `item` WHERE `id` = %d LIMIT 1", intval($id));
if (dba::is_result($r))
if (dbm::is_result($r))
return($r[0]["guid"]);
else
return("");
@ -998,7 +1011,7 @@ function get_item_id($guid, $uid = 0) {
$r = q("SELECT `item`.`id`, `user`.`nickname` FROM `item` INNER JOIN `user` ON `user`.`uid` = `item`.`uid`
WHERE `item`.`visible` = 1 AND `item`.`deleted` = 0 and `item`.`moderated` = 0
AND `item`.`guid` = '%s' AND `item`.`uid` = %d", dbesc($guid), intval($uid));
if (dba::is_result($r)) {
if (dbm::is_result($r)) {
$id = $r[0]["id"];
$nick = $r[0]["nickname"];
}
@ -1012,7 +1025,7 @@ function get_item_id($guid, $uid = 0) {
AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = ''
AND `item`.`private` = 0 AND `item`.`wall` = 1
AND `item`.`guid` = '%s'", dbesc($guid));
if (dba::is_result($r)) {
if (dbm::is_result($r)) {
$id = $r[0]["id"];
$nick = $r[0]["nickname"];
}
@ -1143,7 +1156,7 @@ function tag_deliver($uid,$item_id) {
);
update_thread($item_id);
proc_run('php','include/notifier.php','tgroup',$item_id);
proc_run(PRIORITY_HIGH,'include/notifier.php', 'tgroup', $item_id);
}
@ -1313,7 +1326,7 @@ function item_is_remote_self($contact, &$datarray) {
if ($contact['remote_self'] == 2) {
$r = q("SELECT `id`,`url`,`name`,`thumb` FROM `contact` WHERE `uid` = %d AND `self`",
intval($contact['uid']));
if (dba::is_result($r)) {
if (dbm::is_result($r)) {
$datarray['contact-id'] = $r[0]["id"];
$datarray['owner-name'] = $r[0]["name"];
@ -1390,17 +1403,9 @@ function new_follower($importer,$contact,$datarray,$item,$sharing = false) {
intval($importer['uid']),
dbesc($url)
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$contact_record = $r[0];
$photos = import_profile_photo($photo,$importer["uid"],$contact_record["id"]);
q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s' WHERE `id` = %d",
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
intval($contact_record["id"])
);
update_contact_avatar($photo, $importer["uid"], $contact_record["id"], true);
}
@ -1408,7 +1413,8 @@ function new_follower($importer,$contact,$datarray,$item,$sharing = false) {
intval($importer['uid'])
);
$a = get_app();
if(count($r) AND !in_array($r[0]['page-flags'], array(PAGE_SOAPBOX, PAGE_FREELOVE))) {
if(dbm::is_result($r) AND !in_array($r[0]['page-flags'], array(PAGE_SOAPBOX, PAGE_FREELOVE))) {
// create notification
$hash = random_string();
@ -1707,7 +1713,7 @@ function item_expire($uid, $days, $network = "", $force = false) {
} else
$range = "AND `created` < UTC_TIMESTAMP() - INTERVAL %d DAY ";
$r = q("SELECT * FROM `item`
$r = q("SELECT `file`, `resource-id`, `starred`, `type`, `id` FROM `item`
WHERE `uid` = %d $range
AND `id` = `parent`
$sql_extra
@ -1758,7 +1764,7 @@ function item_expire($uid, $days, $network = "", $force = false) {
drop_item($item['id'],false);
}
proc_run('php',"include/notifier.php","expire","$uid");
proc_run(PRIORITY_HIGH,"include/notifier.php", "expire", $uid);
}
@ -1780,7 +1786,7 @@ function drop_items($items) {
// multiple threads may have been deleted, send an expire notification
if($uid)
proc_run('php',"include/notifier.php","expire","$uid");
proc_run(PRIORITY_HIGH,"include/notifier.php", "expire", $uid);
}
@ -1982,7 +1988,7 @@ function drop_item($id,$interactive = true) {
dbesc($item['parent-uri']),
intval($item['uid'])
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d",
intval($r[0]['id'])
);
@ -1993,7 +1999,7 @@ function drop_item($id,$interactive = true) {
// send the notification upstream/downstream as the case may be
proc_run('php',"include/notifier.php","drop","$drop_id");
proc_run(PRIORITY_HIGH,"include/notifier.php", "drop", $drop_id);
if(! $interactive)
return $owner;
@ -2019,7 +2025,7 @@ function first_post_date($uid,$wall = false) {
intval($uid),
intval($wall ? 1 : 0)
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
// logger('first_post_date: ' . $r[0]['id'] . ' ' . $r[0]['created'], LOGGER_DATA);
return substr(datetime_convert('',date_default_timezone_get(),$r[0]['created']),0,10);
}

View file

@ -90,7 +90,7 @@ function do_like($item_id, $verb) {
WHERE `contact`.`self` = 1 AND `contact`.`uid` = %d LIMIT 1",
intval($owner_uid)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$owner = $r[0];
if(! $owner) {
@ -112,7 +112,7 @@ function do_like($item_id, $verb) {
intval($_SESSION['visitor_id']),
intval($owner_uid)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$contact = $r[0];
}
if(! $contact) {
@ -135,7 +135,7 @@ function do_like($item_id, $verb) {
dbesc($item_id), dbesc($item_id), dbesc($item['uri'])
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$like_item = $r[0];
// Already voted, undo it
@ -153,7 +153,7 @@ function do_like($item_id, $verb) {
);
$like_item_id = $like_item['id'];
proc_run('php',"include/notifier.php","like","$like_item_id");
proc_run(PRIORITY_HIGH, "include/notifier.php", "like", $like_item_id);
return true;
}
@ -161,7 +161,7 @@ function do_like($item_id, $verb) {
$uri = item_new_uri($a->get_hostname(),$owner_uid);
$post_type = (($item['resource-id']) ? t('photo') : t('status'));
if($item['obj_type'] === ACTIVITY_OBJ_EVENT)
if($item['object-type'] === ACTIVITY_OBJ_EVENT)
$post_type = t('event');
$objtype = (($item['resource-id']) ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
$link = xmlify('<link rel="alternate" type="text/html" href="' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . '" />' . "\n") ;
@ -245,7 +245,7 @@ EOT;
call_hooks('post_local_end', $arr);
proc_run('php',"include/notifier.php","like","$post_id");
proc_run(PRIORITY_HIGH, "include/notifier.php", "like", $post_id);
return true;
}

View file

@ -16,7 +16,7 @@ function lock_function($fn_name, $block = true, $wait_sec = 2, $timeout = 30) {
dbesc($fn_name)
);
if((dba::is_result($r)) AND (!$r[0]['locked'] OR (strtotime($r[0]['created']) < time() - 3600))) {
if((dbm::is_result($r)) AND (!$r[0]['locked'] OR (strtotime($r[0]['created']) < time() - 3600))) {
q("UPDATE `locks` SET `locked` = 1, `created` = '%s' WHERE `name` = '%s'",
dbesc(datetime_convert()),
dbesc($fn_name)

View file

@ -41,7 +41,7 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){
dbesc($replyto),
dbesc($replyto)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$convid = $r[0]['convid'];
}
@ -74,7 +74,7 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){
dbesc($conv_guid),
intval(local_user())
);
if(dba::is_result($r))
if(dbm::is_result($r))
$convid = $r[0]['id'];
}
@ -113,7 +113,7 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){
dbesc($uri),
intval(local_user())
);
if(dba::is_result($r))
if(dbm::is_result($r))
$post_id = $r[0]['id'];
/**
@ -150,7 +150,7 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){
}
if($post_id) {
proc_run('php',"include/notifier.php","mail","$post_id");
proc_run(PRIORITY_HIGH, "include/notifier.php", "mail", $post_id);
return intval($post_id);
} else {
return -3;
@ -210,7 +210,7 @@ function send_wallmessage($recipient='', $body='', $subject='', $replyto=''){
dbesc($conv_guid),
intval($recipient['uid'])
);
if(dba::is_result($r))
if(dbm::is_result($r))
$convid = $r[0]['id'];
if(! $convid) {

View file

@ -170,7 +170,7 @@ function nav_info(&$a) {
if(in_array($_SESSION['page_flags'], array(PAGE_NORMAL, PAGE_SOAPBOX, PAGE_FREELOVE))) {
$nav['notifications'] = array('notifications', t('Notifications'), "", t('Notifications'));
$nav['notifications']['all']=array('notifications/system', t('See all notifications'), "", "");
$nav['notifications']['mark'] = array('', t('Mark all system notifications seen'), '','');
$nav['notifications']['mark'] = array('', t('Mark as seen'), '',t('Mark all system notifications seen'));
}
}

View file

@ -5,7 +5,7 @@
*/
require_once("include/xml.php");
require_once('include/Probe.php');
/**
* @brief Curl wrapper
@ -338,7 +338,6 @@ function xml_status($st, $message = '') {
killme();
}
/**
* @brief Send HTTP status header and exit.
*
@ -348,6 +347,14 @@ function xml_status($st, $message = '') {
* 'description' => optional message
*/
/**
* @brief Send HTTP status header and exit.
*
* @param integer $val HTTP status result value
* @param array $description optional message
* 'title' => header title
* 'description' => optional message
*/
function http_status_exit($val, $description = array()) {
$err = '';
if($val >= 400) {
@ -371,325 +378,6 @@ function http_status_exit($val, $description = array()) {
}
// Given an email style address, perform webfinger lookup and
// return the resulting DFRN profile URL, or if no DFRN profile URL
// is located, returns an OStatus subscription template (prefixed
// with the string 'stat:' to identify it as on OStatus template).
// If this isn't an email style address just return $webbie.
// Return an empty string if email-style addresses but webfinger fails,
// or if the resultant personal XRD doesn't contain a supported
// subscription/friend-request attribute.
// amended 7/9/2011 to return an hcard which could save potentially loading
// a lengthy content page to scrape dfrn attributes
function webfinger_dfrn($webbie,&$hcard) {
if(! strstr($webbie,'@')) {
return $webbie;
}
$profile_link = '';
$links = webfinger($webbie);
logger('webfinger_dfrn: ' . $webbie . ':' . print_r($links,true), LOGGER_DATA);
if(count($links)) {
foreach($links as $link) {
if(empty($profile_link) && $link['@attributes']['rel'] === NAMESPACE_DFRN) {
$profile_link = $link['@attributes']['href'];
} elseif(empty($profile_link) && $link['@attributes']['rel'] === NAMESPACE_OSTATUSSUB) {
$profile_link = 'stat:' . $link['@attributes']['template'];
} elseif(empty($hcard) && $link['@attributes']['rel'] === 'http://microformats.org/profile/hcard') {
$hcard = $link['@attributes']['href'];
}
}
}
return $profile_link;
}
/**
* @brief Perform webfinger lookup on an email style address
*
* @param string $webbi An email style address
* @param boolean $debug
*
* @return array of link attributes from the personal XRD file
* empty array on error/failure
*/
function webfinger($webbie, $debug = false) {
$host = '';
if(strstr($webbie,'@')) {
$host = substr($webbie,strpos($webbie,'@') + 1);
}
if(strlen($host)) {
$tpl = fetch_lrdd_template($host);
logger('webfinger: lrdd template: ' . $tpl);
if(strlen($tpl)) {
$pxrd = str_replace('{uri}', urlencode('acct:' . $webbie), $tpl);
logger('webfinger: pxrd: ' . $pxrd);
$links = fetch_xrd_links($pxrd);
if(! count($links)) {
// try with double slashes
$pxrd = str_replace('{uri}', urlencode('acct://' . $webbie), $tpl);
logger('webfinger: pxrd: ' . $pxrd);
$links = fetch_xrd_links($pxrd);
}
return $links;
}
}
return array();
}
function lrdd($uri, $debug = false) {
$a = get_app();
// default priority is host priority, host-meta first
$priority = 'host';
// All we have is an email address. Resource-priority is irrelevant
// because our URI isn't directly resolvable.
if(strstr($uri,'@')) {
return(webfinger($uri));
}
// get the host meta file
$host = @parse_url($uri);
if($host) {
$url = ((x($host,'scheme')) ? $host['scheme'] : 'http') . '://';
$url .= $host['host'] . '/.well-known/host-meta' ;
}
else
return array();
logger('lrdd: constructed url: ' . $url);
$xml = fetch_url($url);
$headers = $a->get_curl_headers();
if (! $xml)
return array();
logger('lrdd: host_meta: ' . $xml, LOGGER_DATA);
if(! stristr($xml,'<xrd'))
return array();
$h = parse_xml_string($xml);
if(! $h)
return array();
$arr = xml::element_to_array($h);
if(isset($arr['xrd']['property'])) {
$property = $arr['crd']['property'];
if(! isset($property[0]))
$properties = array($property);
else
$properties = $property;
foreach($properties as $prop)
if((string) $prop['@attributes'] === 'http://lrdd.net/priority/resource')
$priority = 'resource';
}
// save the links in case we need them
$links = array();
if(isset($arr['xrd']['link'])) {
$link = $arr['xrd']['link'];
if(! isset($link[0]))
$links = array($link);
else
$links = $link;
}
// do we have a template or href?
if(count($links)) {
foreach($links as $link) {
if($link['@attributes']['rel'] && attribute_contains($link['@attributes']['rel'],'lrdd')) {
if(x($link['@attributes'],'template'))
$tpl = $link['@attributes']['template'];
elseif(x($link['@attributes'],'href'))
$href = $link['@attributes']['href'];
}
}
}
if((! isset($tpl)) || (! strpos($tpl,'{uri}')))
$tpl = '';
if($priority === 'host') {
if(strlen($tpl))
$pxrd = str_replace('{uri}', urlencode($uri), $tpl);
elseif(isset($href))
$pxrd = $href;
if(isset($pxrd)) {
logger('lrdd: (host priority) pxrd: ' . $pxrd);
$links = fetch_xrd_links($pxrd);
return $links;
}
$lines = explode("\n",$headers);
if(count($lines)) {
foreach($lines as $line) {
if((stristr($line,'link:')) && preg_match('/<([^>].*)>.*rel\=[\'\"]lrdd[\'\"]/',$line,$matches)) {
return(fetch_xrd_links($matches[1]));
break;
}
}
}
}
// priority 'resource'
$html = fetch_url($uri);
$headers = $a->get_curl_headers();
logger('lrdd: headers=' . $headers, LOGGER_DEBUG);
// don't try and parse raw xml as html
if(! strstr($html,'<?xml')) {
require_once('library/HTML5/Parser.php');
try {
$dom = HTML5_Parser::parse($html);
} catch (DOMException $e) {
logger('lrdd: parse error: ' . $e);
}
if(isset($dom) && $dom) {
$items = $dom->getElementsByTagName('link');
foreach($items as $item) {
$x = $item->getAttribute('rel');
if($x == "lrdd") {
$pagelink = $item->getAttribute('href');
break;
}
}
}
}
if(isset($pagelink))
return(fetch_xrd_links($pagelink));
// next look in HTTP headers
$lines = explode("\n",$headers);
if(count($lines)) {
foreach($lines as $line) {
/// @TODO Alter the following regex to support multiple relations (space separated)
if((stristr($line,'link:')) && preg_match('/<([^>].*)>.*rel\=[\'\"]lrdd[\'\"]/',$line,$matches)) {
$pagelink = $matches[1];
break;
}
// don't try and run feeds through the html5 parser
if(stristr($line,'content-type:') && ((stristr($line,'application/atom+xml')) || (stristr($line,'application/rss+xml'))))
return array();
if(stristr($html,'<rss') || stristr($html,'<feed'))
return array();
}
}
if(isset($pagelink))
return(fetch_xrd_links($pagelink));
// If we haven't found any links, return the host xrd links (which we have already fetched)
if(isset($links))
return $links;
return array();
}
// Given a host name, locate the LRDD template from that
// host. Returns the LRDD template or an empty string on
// error/failure.
function fetch_lrdd_template($host) {
$tpl = '';
$url1 = 'https://' . $host . '/.well-known/host-meta' ;
$url2 = 'http://' . $host . '/.well-known/host-meta' ;
$links = fetch_xrd_links($url1);
logger('fetch_lrdd_template from: ' . $url1);
logger('template (https): ' . print_r($links,true));
if(! count($links)) {
logger('fetch_lrdd_template from: ' . $url2);
$links = fetch_xrd_links($url2);
logger('template (http): ' . print_r($links,true));
}
if(count($links)) {
foreach($links as $link)
if($link['@attributes']['rel'] && $link['@attributes']['rel'] === 'lrdd' && (!$link['@attributes']['type'] || $link['@attributes']['type'] === 'application/xrd+xml'))
$tpl = $link['@attributes']['template'];
}
if(! strpos($tpl,'{uri}'))
$tpl = '';
return $tpl;
}
/**
* @brief Given a URL, retrieve the page as an XRD document.
*
* @param string $url An url
* @return array of links
* return empty array on error/failure
*/
function fetch_xrd_links($url) {
$xrd_timeout = intval(get_config('system','xrd_timeout'));
$redirects = 0;
$xml = fetch_url($url,false,$redirects,(($xrd_timeout) ? $xrd_timeout : 20), "application/xrd+xml");
logger('fetch_xrd_links: ' . $xml, LOGGER_DATA);
if ((! $xml) || (! stristr($xml,'<xrd')))
return array();
// fix diaspora's bad xml
$xml = str_replace(array('href=&quot;','&quot;/>'),array('href="','"/>'),$xml);
$h = parse_xml_string($xml);
if(! $h)
return array();
$arr = xml::element_to_array($h);
$links = array();
if(isset($arr['xrd']['link'])) {
$link = $arr['xrd']['link'];
if(! isset($link[0]))
$links = array($link);
else
$links = $link;
}
if(isset($arr['xrd']['alias'])) {
$alias = $arr['xrd']['alias'];
if(! isset($alias[0]))
$aliases = array($alias);
else
$aliases = $alias;
if(is_array($aliases) && count($aliases)) {
foreach($aliases as $alias) {
$links[]['@attributes'] = array('rel' => 'alias' , 'href' => $alias);
}
}
}
logger('fetch_xrd_links: ' . print_r($links,true), LOGGER_DATA);
return $links;
}
/**
* @brief Check URL to se if ts's real
*
@ -1145,3 +833,57 @@ function json_return_and_die($x) {
echo json_encode($x);
killme();
}
/**
* @brief Find the matching part between two url
*
* @param string $url1
* @param string $url2
* @return string The matching part
*/
function matching_url($url1, $url2) {
if (($url1 == "") OR ($url2 == ""))
return "";
$url1 = normalise_link($url1);
$url2 = normalise_link($url2);
$parts1 = parse_url($url1);
$parts2 = parse_url($url2);
if (!isset($parts1["host"]) OR !isset($parts2["host"]))
return "";
if ($parts1["scheme"] != $parts2["scheme"])
return "";
if ($parts1["host"] != $parts2["host"])
return "";
if ($parts1["port"] != $parts2["port"])
return "";
$match = $parts1["scheme"]."://".$parts1["host"];
if ($parts1["port"])
$match .= ":".$parts1["port"];
$pathparts1 = explode("/", $parts1["path"]);
$pathparts2 = explode("/", $parts2["path"]);
$i = 0;
$path = "";
do {
$path1 = $pathparts1[$i];
$path2 = $pathparts2[$i];
if ($path1 == $path2)
$path .= $path1."/";
} while (($path1 == $path2) AND ($i++ <= count($pathparts1)));
$match .= $path;
return normalise_link($match);
}

View file

@ -16,7 +16,7 @@ require_once('include/salmon.php');
/*
* The notifier is typically called with:
*
* proc_run('php', "include/notifier.php", COMMAND, ITEM_ID);
* proc_run(PRIORITY_HIGH, "include/notifier.php", COMMAND, ITEM_ID);
*
* where COMMAND is one of the following:
*
@ -132,17 +132,24 @@ function notifier_run(&$argv, &$argc){
$recipients[] = $suggest[0]['cid'];
$item = $suggest[0];
} elseif($cmd === 'removeme') {
$r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($item_id));
$r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`,
`user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`,
`user`.`page-flags`, `user`.`prvnets`, `user`.`guid`
FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
WHERE `contact`.`uid` = %d AND `contact`.`self` LIMIT 1",
intval($item_id));
if (!$r)
return;
$user = $r[0];
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval($item_id));
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1", intval($item_id));
if (!$r)
return;
$self = $r[0];
$r = q("SELECT * FROM `contact` WHERE `self` = 0 AND `uid` = %d", intval($item_id));
$r = q("SELECT * FROM `contact` WHERE NOT `self` AND `uid` = %d", intval($item_id));
if(!$r)
return;
@ -314,7 +321,7 @@ function notifier_run(&$argv, &$argc){
intval($uid),
dbesc(NETWORK_DFRN)
);
if(dba::is_result($r))
if(dbm::is_result($r))
foreach($r as $rr)
$recipients_followup[] = $rr['id'];
}
@ -348,7 +355,7 @@ function notifier_run(&$argv, &$argc){
// a delivery fork. private groups (forum_mode == 2) do not uplink
if((intval($parent['forum_mode']) == 1) && (! $top_level) && ($cmd !== 'uplink')) {
proc_run('php','include/notifier.php','uplink',$item_id);
proc_run(PRIORITY_HIGH,'include/notifier.php','uplink',$item_id);
}
$conversants = array();
@ -388,7 +395,34 @@ function notifier_run(&$argv, &$argc){
// We have not only to look at the parent, since it could be a Friendica thread.
if (($thr_parent AND ($thr_parent[0]['network'] == NETWORK_OSTATUS)) OR ($parent['network'] == NETWORK_OSTATUS)) {
logger('Some parent is OStatus for '.$target_item["guid"], LOGGER_DEBUG);
logger('Some parent is OStatus for '.$target_item["guid"]." - Author: ".$thr_parent[0]['author-link']." - Owner: ".$thr_parent[0]['owner-link'], LOGGER_DEBUG);
// Send a salmon to the parent author
$r = q("SELECT `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''",
dbesc(normalise_link($thr_parent[0]['author-link'])),
intval($uid));
if ($r)
$probed_contact = $r[0];
else
$probed_contact = probe_url($thr_parent[0]['author-link']);
if ($probed_contact["notify"] != "") {
logger('Notify parent author '.$probed_contact["url"].': '.$probed_contact["notify"]);
$url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
}
// Send a salmon to the parent owner
$r = q("SELECT `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''",
dbesc(normalise_link($thr_parent[0]['owner-link'])),
intval($uid));
if ($r)
$probed_contact = $r[0];
else
$probed_contact = probe_url($thr_parent[0]['owner-link']);
if ($probed_contact["notify"] != "") {
logger('Notify parent owner '.$probed_contact["url"].': '.$probed_contact["notify"]);
$url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
}
// Send a salmon to the parent author
$probed_contact = probe_url($thr_parent[0]['author-link']);
@ -425,7 +459,7 @@ function notifier_run(&$argv, &$argc){
$r = q("SELECT * FROM `contact` WHERE `id` IN ($conversant_str) AND NOT `blocked` AND NOT `pending` AND NOT `archive`".$sql_extra);
if(dba::is_result($r))
if(dbm::is_result($r))
$contacts = $r;
} else
@ -443,7 +477,7 @@ function notifier_run(&$argv, &$argc){
intval($uid),
dbesc(NETWORK_MAIL)
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $rr)
$recipients[] = $rr['id'];
}
@ -471,7 +505,7 @@ function notifier_run(&$argv, &$argc){
// delivery loop
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $contact) {
if(!$contact['self']) {
@ -518,7 +552,7 @@ function notifier_run(&$argv, &$argc){
$this_batch[] = $contact['id'];
if(count($this_batch) >= $deliveries_per_process) {
proc_run('php','include/delivery.php',$cmd,$item_id,$this_batch);
proc_run(PRIORITY_HIGH,'include/delivery.php',$cmd,$item_id,$this_batch);
$this_batch = array();
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
@ -528,7 +562,7 @@ function notifier_run(&$argv, &$argc){
// be sure to pick up any stragglers
if(count($this_batch))
proc_run('php','include/delivery.php',$cmd,$item_id,$this_batch);
proc_run(PRIORITY_HIGH,'include/delivery.php',$cmd,$item_id,$this_batch);
}
// send salmon slaps to mentioned remote tags (@foo@example.com) in OStatus posts
@ -549,7 +583,7 @@ function notifier_run(&$argv, &$argc){
if($public_message) {
if (!$followup AND $top_level)
if (!$followup)
$r0 = diaspora::relay_list();
else
$r0 = array();
@ -572,7 +606,7 @@ function notifier_run(&$argv, &$argc){
$r = array_merge($r2,$r1,$r0);
if(dba::is_result($r)) {
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
@ -599,7 +633,7 @@ function notifier_run(&$argv, &$argc){
if((! $mail) && (! $fsuggest) && (! $followup)) {
logger('notifier: delivery agent: '.$rr['name'].' '.$rr['id'].' '.$rr['network'].' '.$target_item["guid"]);
proc_run('php','include/delivery.php',$cmd,$item_id,$rr['id']);
proc_run(PRIORITY_HIGH,'include/delivery.php',$cmd,$item_id,$rr['id']);
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
@ -623,7 +657,7 @@ function notifier_run(&$argv, &$argc){
// Set push flag for PuSH subscribers to this topic,
// they will be notified in queue.php
q("UPDATE `push_subscriber` SET `push` = 1 ".
"WHERE `nickname` = '%s'", dbesc($owner['nickname']));
"WHERE `nickname` = '%s' AND `push` = 0", dbesc($owner['nickname']));
logger('Activating internal PuSH for item '.$item_id, LOGGER_DEBUG);
@ -639,7 +673,7 @@ function notifier_run(&$argv, &$argc){
}
// Handling the pubsubhubbub requests
proc_run('php','include/pubsubpublish.php');
proc_run(PRIORITY_HIGH,'include/pubsubpublish.php');
}
logger('notifier: calling hooks', LOGGER_DEBUG);

View file

@ -23,7 +23,7 @@ class FKOAuthDataStore extends OAuthDataStore {
$r = q("SELECT client_id, pw, redirect_uri FROM clients WHERE client_id='%s'",
dbesc($consumer_key)
);
if (dba::is_result($r))
if (dbm::is_result($r))
return new OAuthConsumer($r[0]['client_id'],$r[0]['pw'],$r[0]['redirect_uri']);
return null;
}
@ -35,7 +35,7 @@ class FKOAuthDataStore extends OAuthDataStore {
dbesc($token_type),
dbesc($token)
);
if (dba::is_result($r)){
if (dbm::is_result($r)){
$ot=new OAuthToken($r[0]['id'],$r[0]['secret']);
$ot->scope=$r[0]['scope'];
$ot->expires = $r[0]['expires'];
@ -52,7 +52,7 @@ class FKOAuthDataStore extends OAuthDataStore {
dbesc($nonce),
intval($timestamp)
);
if (dba::is_result($r))
if (dbm::is_result($r))
return new OAuthToken($r[0]['id'],$r[0]['secret']);
return null;
}
@ -136,7 +136,7 @@ class FKOAuth1 extends OAuthServer {
$r = q("SELECT * FROM `user` WHERE uid=%d AND `blocked` = 0 AND `account_expired` = 0 AND `account_removed` = 0 AND `verified` = 1 LIMIT 1",
intval($uid)
);
if(dba::is_result($r)){
if(dbm::is_result($r)){
$record = $r[0];
} else {
logger('FKOAuth1::loginUser failure: ' . print_r($_SERVER,true), LOGGER_DEBUG);
@ -162,7 +162,7 @@ class FKOAuth1 extends OAuthServer {
$r = q("SELECT * FROM `contact` WHERE `uid` = %s AND `self` = 1 LIMIT 1",
intval($_SESSION['uid']));
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$a->contact = $r[0];
$a->cid = $r[0]['id'];
$_SESSION['cid'] = $a->cid;
@ -219,7 +219,7 @@ class FKOAuth2 extends OAuth2 {
$r = q("SELECT client_id, expires, scope FROM tokens WHERE id = '%s'",
dbesc($oauth_token));
if (dba::is_result($r))
if (dbm::is_result($r))
return $r[0];
return null;
}
@ -247,7 +247,7 @@ class FKOAuth2 extends OAuth2 {
$r = q("SELECT id, client_id, redirect_uri, expires, scope FROM auth_codes WHERE id = '%s'",
dbesc($code));
if (dba::is_result($r))
if (dbm::is_result($r))
return $r[0];
return null;
}

View file

@ -75,8 +75,11 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){
else { //save in cache
$j = json_decode($txt);
if ($j->type != "error")
q("INSERT INTO `oembed` (`url`, `content`, `created`) VALUES ('%s', '%s', '%s')",
dbesc(normalise_link($embedurl)), dbesc($txt), dbesc(datetime_convert()));
q("INSERT INTO `oembed` (`url`, `content`, `created`) VALUES ('%s', '%s', '%s')
ON DUPLICATE KEY UPDATE `content` = '%s', `created` = '%s'",
dbesc(normalise_link($embedurl)),
dbesc($txt), dbesc(datetime_convert()),
dbesc($txt), dbesc(datetime_convert()));
Cache::set($a->videowidth.$embedurl,$txt, CACHE_DAY);
}

View file

@ -24,7 +24,6 @@ function onepoll_run(&$argv, &$argc){
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once('include/session.php');
require_once('include/datetime.php');
require_once('include/items.php');
@ -94,7 +93,7 @@ function onepoll_run(&$argv, &$argc){
where `cid` = %d and updated > UTC_TIMESTAMP() - INTERVAL 1 DAY",
intval($contact['id'])
);
if (dba::is_result($r))
if (dbm::is_result($r))
if (!$r[0]['total'])
poco_load($contact['id'],$importer_uid,0,$contact['poco']);
}
@ -394,7 +393,7 @@ function onepoll_run(&$argv, &$argc){
dbesc($datarray['uri'])
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
logger("Mail: Seen before ".$msg_uid." for ".$mailconf[0]['user']." UID: ".$importer_uid." URI: ".$datarray['uri'],LOGGER_DEBUG);
// Only delete when mails aren't automatically moved or deleted
@ -447,7 +446,7 @@ function onepoll_run(&$argv, &$argc){
$r = q("SELECT `uri` , `parent-uri` FROM `item` WHERE `uri` IN ( $qstr ) AND `uid` = %d LIMIT 1",
intval($importer_uid)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$datarray['parent-uri'] = $r[0]['parent-uri']; // Set the parent as the top-level item
// $datarray['parent-uri'] = $r[0]['uri'];
}
@ -479,7 +478,7 @@ function onepoll_run(&$argv, &$argc){
$r = q("SELECT `uri` , `parent-uri` FROM `item` WHERE `title` = \"%s\" AND `uid` = %d ORDER BY `created` DESC LIMIT 1",
dbesc(protect_sprintf($datarray['title'])),
intval($importer_uid));
if(dba::is_result($r))
if(dbm::is_result($r))
$datarray['parent-uri'] = $r[0]['parent-uri'];
}

View file

@ -161,6 +161,7 @@ class ostatus {
}
$contact["generation"] = 2;
$contact["hide"] = false; // OStatus contacts are never hidden
$contact["photo"] = $author["author-avatar"];
update_gcontact($contact);
}
@ -492,6 +493,7 @@ class ostatus {
$orig_body = $xpath->query('atom:content/text()', $activityobjects)->item(0)->nodeValue;
$orig_created = $xpath->query('atom:published/text()', $activityobjects)->item(0)->nodeValue;
$orig_edited = $xpath->query('atom:updated/text()', $activityobjects)->item(0)->nodeValue;
$orig_contact = $contact;
$orig_author = self::fetchauthor($xpath, $activityobjects, $importer, $orig_contact, false);
@ -501,6 +503,7 @@ class ostatus {
$item["author-avatar"] = $orig_author["author-avatar"];
$item["body"] = add_page_info_to_body(html2bbcode($orig_body));
$item["created"] = $orig_created;
$item["edited"] = $orig_edited;
$item["uri"] = $orig_uri;
$item["plink"] = $orig_link;
@ -691,6 +694,7 @@ class ostatus {
}
}
$contact["hide"] = false; // OStatus contacts are never hidden
update_gcontact($contact);
}
@ -1967,7 +1971,7 @@ class ostatus {
OR (`item`.`network` = '%s' AND ((`thread`.`network` IN ('%s', '%s')) OR (`thritem`.`network` IN ('%s', '%s')))) AND `thread`.`mention`)
AND ((`item`.`owner-link` IN ('%s', '%s') AND (`item`.`parent` = `item`.`id`))
OR (`item`.`author-link` IN ('%s', '%s')))
ORDER BY `item`.`received` DESC
ORDER BY `item`.`id` DESC
LIMIT 0, 300",
intval($owner["uid"]), dbesc($check_date), dbesc(NETWORK_DFRN),
//dbesc(NETWORK_OSTATUS), dbesc(NETWORK_OSTATUS),

View file

@ -82,7 +82,7 @@ function get_attachment_data($body) {
$data = array();
if (!preg_match("/(.*)\[attachment(.*)\](.*?)\[\/attachment\](.*)/ism", $body, $match))
if (!preg_match("/(.*)\[attachment(.*?)\](.*?)\[\/attachment\](.*)/ism", $body, $match))
return get_old_attachment_data($body);
$attributes = $match[2];
@ -117,7 +117,7 @@ function get_attachment_data($body) {
$url = $matches[1];
if ($url != "")
$data["url"] = $url;
$data["url"] = html_entity_decode($url, ENT_QUOTES, 'UTF-8');
$title = "";
preg_match("/title='(.*?)'/ism", $attributes, $matches);
@ -128,12 +128,12 @@ function get_attachment_data($body) {
if ($matches[1] != "")
$title = $matches[1];
//$title = htmlentities($title, ENT_QUOTES, 'UTF-8', false);
if ($title != "") {
$title = bbcode(html_entity_decode($title, ENT_QUOTES, 'UTF-8'), false, false, true);
$title = html_entity_decode($title, ENT_QUOTES, 'UTF-8');
$title = str_replace(array("[", "]"), array("&#91;", "&#93;"), $title);
if ($title != "")
$data["title"] = $title;
}
$image = "";
preg_match("/image='(.*?)'/ism", $attributes, $matches);
@ -145,7 +145,7 @@ function get_attachment_data($body) {
$image = $matches[1];
if ($image != "")
$data["image"] = $image;
$data["image"] = html_entity_decode($image, ENT_QUOTES, 'UTF-8');
$preview = "";
preg_match("/preview='(.*?)'/ism", $attributes, $matches);
@ -157,7 +157,7 @@ function get_attachment_data($body) {
$preview = $matches[1];
if ($preview != "")
$data["preview"] = $preview;
$data["preview"] = html_entity_decode($preview, ENT_QUOTES, 'UTF-8');
$data["description"] = trim($match[3]);
@ -189,6 +189,13 @@ function get_attached_data($body) {
if (count($pictures) == 1) {
// Checking, if the link goes to a picture
$data = parseurl_getsiteinfo_cached($pictures[0][1], true);
// Workaround:
// Sometimes photo posts to the own album are not detected at the start.
// So we seem to cannot use the cache for these cases. That's strange.
if (($data["type"] != "photo") AND strstr($pictures[0][1], "/photos/"))
$data = parseurl_getsiteinfo($pictures[0][1], true);
if ($data["type"] == "photo") {
$post["type"] = "photo";
if (isset($data["images"][0])) {
@ -343,7 +350,7 @@ function plaintext($a, $b, $limit = 0, $includedlinks = false, $htmlmode = 2, $t
}
}
$html = bbcode($post["text"], false, false, $htmlmode);
$html = bbcode($post["text"].$post["after"], false, false, $htmlmode);
$msg = html2plain($html, 0, true);
$msg = trim(html_entity_decode($msg,ENT_QUOTES,'UTF-8'));

View file

@ -79,7 +79,7 @@ function reload_plugins() {
if(strlen($plugins)) {
$r = q("SELECT * FROM `addon` WHERE `installed` = 1");
if(dba::is_result($r))
if(dbm::is_result($r))
$installed = $r;
else
$installed = array();
@ -150,7 +150,7 @@ function register_hook($hook,$file,$function,$priority=0) {
dbesc($file),
dbesc($function)
);
if(dba::is_result($r))
if(dbm::is_result($r))
return true;
$r = q("INSERT INTO `hook` (`hook`, `file`, `function`, `priority`) VALUES ( '%s', '%s', '%s', '%s' ) ",
@ -187,7 +187,7 @@ function load_hooks() {
$a = get_app();
$a->hooks = array();
$r = q("SELECT * FROM `hook` WHERE 1 ORDER BY `priority` DESC, `file`");
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $rr) {
if(! array_key_exists($rr['hook'],$a->hooks))
$a->hooks[$rr['hook']] = array();
@ -205,27 +205,33 @@ function load_hooks() {
* @param string $name of the hook to call
* @param string|array &$data to transmit to the callback handler
*/
if(! function_exists('call_hooks')) {
function call_hooks($name, &$data = null) {
$stamp1 = microtime(true);
$a = get_app();
#logger($name, LOGGER_ALL);
if (is_array($a->hooks) && array_key_exists($name, $a->hooks))
foreach ($a->hooks[$name] as $hook)
call_single_hook($a, $name, $hook, $data);
}
if((is_array($a->hooks)) && (array_key_exists($name,$a->hooks))) {
foreach($a->hooks[$name] as $hook) {
/**
* @brief Calls a single hook.
*
* @param string $name of the hook to call
* @param array $hook Hook data
* @param string|array &$data to transmit to the callback handler
*/
function call_single_hook($a, $name, $hook, &$data = null) {
// Don't run a theme's hook if the user isn't using the theme
if (strpos($hook[0], 'view/theme/') !== false && strpos($hook[0], 'view/theme/'.current_theme()) === false)
continue;
return;
@include_once($hook[0]);
if (function_exists($hook[1])) {
$func = $hook[1];
//logger($name." => ".$hook[0].":".$func."()", LOGGER_DEBUG);
$func($a, $data);
}
else {
} else {
// remove orphan hooks
q("DELETE FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `function` = '%s'",
dbesc($name),
@ -234,8 +240,6 @@ function call_hooks($name, &$data = null) {
);
}
}
}
}}
//check if an app_menu hook exist for plugin $name.
//Return true if the plugin is an app
@ -534,3 +538,41 @@ function upgrade_bool_message($bbcode = false) {
$x = upgrade_link($bbcode);
return t('This action is not available under your subscription plan.') . (($x) ? ' ' . $x : '') ;
}
/**
* @brief Get the full path to relevant theme files by filename
*
* This function search in the theme directory (and if not present in global theme directory)
* if there is a directory with the file extension and for a file with the given
* filename.
*
* @param string $file Filename
* @param string $root Full root path
* @return string Path to the file or empty string if the file isn't found
*/
function theme_include($file, $root = '') {
// Make sure $root ends with a slash / if it's not blank
if($root !== '' && $root[strlen($root)-1] !== '/')
$root = $root . '/';
$theme_info = $a->theme_info;
if(is_array($theme_info) AND array_key_exists('extends',$theme_info))
$parent = $theme_info['extends'];
else
$parent = 'NOPATH';
$theme = current_theme();
$thname = $theme;
$ext = substr($file,strrpos($file,'.')+1);
$paths = array(
"{$root}view/theme/$thname/$ext/$file",
"{$root}view/theme/$parent/$ext/$file",
"{$root}view/$ext/$file",
);
foreach($paths as $p) {
// strpos() is faster than strstr when checking if one string is in another (http://php.net/manual/en/function.strstr.php)
if(strpos($p,'NOPATH') !== false)
continue;
if(file_exists($p))
return $p;
}
return '';
}

View file

@ -10,6 +10,9 @@ if (!file_exists("boot.php") AND (sizeof($_SERVER["argv"]) != 0)) {
chdir($directory);
}
use \Friendica\Core\Config;
use \Friendica\Core\PConfig;
require_once("boot.php");
function poller_run(&$argv, &$argc){
@ -26,6 +29,13 @@ function poller_run(&$argv, &$argc){
unset($db_host, $db_user, $db_pass, $db_data);
};
$a->start_process();
$mypid = getmypid();
if ($a->max_processes_reached())
return;
if (poller_max_connections_reached())
return;
@ -33,17 +43,17 @@ function poller_run(&$argv, &$argc){
return;
// Checking the number of workers
if (poller_too_much_workers(1)) {
if (poller_too_much_workers()) {
poller_kill_stale_workers();
return;
}
if(($argc <= 1) OR ($argv[1] != "no_cron")) {
// Run the cron job that calls all other jobs
proc_run("php","include/cron.php");
proc_run(PRIORITY_MEDIUM, "include/cron.php");
// Run the cronhooks job separately from cron for being able to use a different timing
proc_run("php","include/cronhooks.php");
proc_run(PRIORITY_MEDIUM, "include/cronhooks.php");
// Cleaning dead processes
poller_kill_stale_workers();
@ -52,32 +62,42 @@ function poller_run(&$argv, &$argc){
sleep(4);
// Checking number of workers
if (poller_too_much_workers(2))
if (poller_too_much_workers())
return;
$cooldown = Config::get("system", "worker_cooldown", 0);
$starttime = time();
while ($r = q("SELECT * FROM `workerqueue` WHERE `executed` = '0000-00-00 00:00:00' ORDER BY `created` LIMIT 1")) {
while ($r = q("SELECT * FROM `workerqueue` WHERE `executed` = '0000-00-00 00:00:00' ORDER BY `priority`, `created` LIMIT 1")) {
// Constantly check the number of parallel database processes
if ($a->max_processes_reached())
return;
// Constantly check the number of available database connections to let the frontend be accessible at any time
if (poller_max_connections_reached())
return;
// Count active workers and compare them with a maximum value that depends on the load
if (poller_too_much_workers(3))
if (poller_too_much_workers())
return;
q("UPDATE `workerqueue` SET `executed` = '%s', `pid` = %d WHERE `id` = %d AND `executed` = '0000-00-00 00:00:00'",
dbesc(datetime_convert()),
intval(getmypid()),
intval($mypid),
intval($r[0]["id"]));
// Assure that there are no tasks executed twice
$id = q("SELECT `id` FROM `workerqueue` WHERE `id` = %d AND `pid` = %d",
intval($r[0]["id"]),
intval(getmypid()));
$id = q("SELECT `pid`, `executed` FROM `workerqueue` WHERE `id` = %d", intval($r[0]["id"]));
if (!$id) {
logger("Queue item ".$r[0]["id"]." was executed multiple times - skip this execution", LOGGER_DEBUG);
logger("Queue item ".$r[0]["id"]." vanished - skip this execution", LOGGER_DEBUG);
continue;
} elseif ((strtotime($id[0]["executed"]) <= 0) OR ($id[0]["pid"] == 0)) {
logger("Entry for queue item ".$r[0]["id"]." wasn't stored - we better stop here", LOGGER_DEBUG);
return;
} elseif ($id[0]["pid"] != $mypid) {
logger("Queue item ".$r[0]["id"]." is to be executed by process ".$id[0]["pid"]." and not by me (".$mypid.") - skip this execution", LOGGER_DEBUG);
continue;
}
@ -99,10 +119,15 @@ function poller_run(&$argv, &$argc){
$funcname = str_replace(".php", "", basename($argv[0]))."_run";
if (function_exists($funcname)) {
logger("Process ".getmypid()." - ID ".$r[0]["id"].": ".$funcname." ".$r[0]["parameter"]);
logger("Process ".$mypid." - Prio ".$r[0]["priority"]." - ID ".$r[0]["id"].": ".$funcname." ".$r[0]["parameter"]);
$funcname($argv, $argc);
logger("Process ".getmypid()." - ID ".$r[0]["id"].": ".$funcname." - done");
if ($cooldown > 0) {
logger("Process ".$mypid." - Prio ".$r[0]["priority"]." - ID ".$r[0]["id"].": ".$funcname." - in cooldown for ".$cooldown." seconds");
sleep($cooldown);
}
logger("Process ".$mypid." - Prio ".$r[0]["priority"]." - ID ".$r[0]["id"].": ".$funcname." - done");
q("DELETE FROM `workerqueue` WHERE `id` = %d", intval($r[0]["id"]));
} else
@ -200,9 +225,9 @@ function poller_max_connections_reached() {
*
*/
function poller_kill_stale_workers() {
$r = q("SELECT `pid`, `executed` FROM `workerqueue` WHERE `executed` != '0000-00-00 00:00:00'");
$r = q("SELECT `pid`, `executed`, `priority`, `parameter` FROM `workerqueue` WHERE `executed` != '0000-00-00 00:00:00'");
if (!dba::is_result($r)) {
if (!dbm::is_result($r)) {
// No processing here needed
return;
}
@ -213,27 +238,47 @@ function poller_kill_stale_workers() {
intval($pid["pid"]));
else {
// Kill long running processes
// Check if the priority is in a valid range
if (!in_array($pid["priority"], array(PRIORITY_CRITICAL, PRIORITY_HIGH, PRIORITY_MEDIUM, PRIORITY_LOW, PRIORITY_NEGLIGIBLE)))
$pid["priority"] = PRIORITY_MEDIUM;
// Define the maximum durations
$max_duration_defaults = array(PRIORITY_CRITICAL => 360, PRIORITY_HIGH => 10, PRIORITY_MEDIUM => 60, PRIORITY_LOW => 180, PRIORITY_NEGLIGIBLE => 360);
$max_duration = $max_duration_defaults[$pid["priority"]];
$argv = json_decode($pid["parameter"]);
$argv[0] = basename($argv[0]);
// How long is the process already running?
$duration = (time() - strtotime($pid["executed"])) / 60;
if ($duration > 180) {
logger("Worker process ".$pid["pid"]." took more than 3 hours. It will be killed now.");
if ($duration > $max_duration) {
logger("Worker process ".$pid["pid"]." (".implode(" ", $argv).") took more than ".$max_duration." minutes. It will be killed now.");
posix_kill($pid["pid"], SIGTERM);
// Question: If a process is stale: Should we remove it or should we reschedule it?
// By now we rescheduling it. It's maybe not the wisest decision?
q("UPDATE `workerqueue` SET `executed` = '0000-00-00 00:00:00', `pid` = 0 WHERE `pid` = %d",
// 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',
`priority` = %d, `pid` = 0 WHERE `pid` = %d",
dbesc(datetime_convert()),
intval(PRIORITY_NEGLIGIBLE),
intval($pid["pid"]));
} else
logger("Worker process ".$pid["pid"]." now runs for ".round($duration)." minutes. That's okay.", LOGGER_DEBUG);
logger("Worker process ".$pid["pid"]." (".implode(" ", $argv).") now runs for ".round($duration)." of ".$max_duration." allowed minutes. That's okay.", LOGGER_DEBUG);
}
}
function poller_too_much_workers($stage) {
function poller_too_much_workers() {
$queues = get_config("system", "worker_queues");
if ($queues == 0)
$queues = 4;
$maxqueues = $queues;
$active = poller_active_workers();
// Decrease the number of workers at higher load
@ -250,21 +295,48 @@ function poller_too_much_workers($stage) {
$slope = $maxworkers / pow($maxsysload, $exponent);
$queues = ceil($slope * pow(max(0, $maxsysload - $load), $exponent));
logger("Current load stage ".$stage.": ".$load." - maximum: ".$maxsysload." - current queues: ".$active." - maximum: ".$queues, LOGGER_DEBUG);
$s = q("SELECT COUNT(*) AS `total` FROM `workerqueue` WHERE `executed` = '0000-00-00 00:00:00'");
$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");
$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));
$high_running = dbm::is_result($s);
if (!$high_running AND ($top_priority > PRIORITY_UNDEFINED) AND ($top_priority < PRIORITY_NEGLIGIBLE)) {
logger("There are jobs with priority ".$top_priority." waiting but none is executed. Open a fastlane.", LOGGER_DEBUG);
$queues = $active + 1;
}
}
logger("Current load: ".$load." - maximum: ".$maxsysload." - current queues: ".$active."/".$entries." - maximum: ".$queues."/".$maxqueues, LOGGER_DEBUG);
// Are there fewer workers running as possible? Then fork a new one.
if (!get_config("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");
$a = get_app();
$a->proc_run($args);
}
}
return($active >= $queues);
}
function poller_active_workers() {
$workers = q("SELECT COUNT(*) AS `workers` FROM `workerqueue` WHERE `executed` != '0000-00-00 00:00:00'");
$workers = q("SELECT COUNT(*) AS `processes` FROM `process` WHERE `command` = 'poller.php'");
return($workers[0]["workers"]);
return($workers[0]["processes"]);
}
if (array_search(__file__,get_included_files())===0){
poller_run($_SERVER["argv"],$_SERVER["argc"]);
get_app()->end_process();
killme();
}
?>

View file

@ -13,6 +13,9 @@ function post_update() {
if (!post_update_1194())
return;
if (!post_update_1198())
return;
}
/**
@ -138,4 +141,78 @@ function post_update_1194() {
logger("Done", LOGGER_DEBUG);
}
/**
* @brief set the author-id and owner-id in all item entries
*
* This job has to be started multiple times until all entries are set.
* It isn't started in the update function since it would consume too much time and can be done in the background.
*
* @return bool "true" when the job is done
*/
function post_update_1198() {
// Was the script completed?
if (get_config("system", "post_update_version") >= 1198)
return true;
logger("Start", LOGGER_DEBUG);
// Check if the first step is done (Setting "author-id" and "owner-id" in the item table)
$r = q("SELECT `author-link`, `owner-link`, `uid` FROM `item` WHERE `author-id` = 0 AND `owner-id` = 0 LIMIT 100");
if (!$r) {
// Are there unfinished entries in the thread table?
$r = q("SELECT COUNT(*) AS `total` FROM `thread`
INNER JOIN `item` ON `item`.`id` =`thread`.`iid`
WHERE `thread`.`author-id` = 0 AND `thread`.`owner-id` = 0 AND
(`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)");
if ($r AND ($r[0]["total"] == 0)) {
set_config("system", "post_update_version", 1198);
logger("Done", LOGGER_DEBUG);
return true;
}
// Update the thread table from the item table
q("UPDATE `thread` INNER JOIN `item` ON `item`.`id`=`thread`.`iid`
SET `thread`.`author-id` = `item`.`author-id`,
`thread`.`owner-id` = `item`.`owner-id`
WHERE `thread`.`author-id` = 0 AND `thread`.`owner-id` = 0 AND
(`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)");
logger("Updated threads", LOGGER_DEBUG);
return false;
}
logger("Query done", LOGGER_DEBUG);
$item_arr = array();
foreach ($r AS $item) {
$index = $item["author-link"]."-".$item["owner-link"]."-".$item["uid"];
$item_arr[$index] = array("author-link" => $item["author-link"],
"owner-link" => $item["owner-link"],
"uid" => $item["uid"]);
}
// Set the "gcontact-id" in the item table and add a new gcontact entry if needed
foreach($item_arr AS $item) {
$author_id = get_contact($item["author-link"], 0);
$owner_id = get_contact($item["owner-link"], 0);
if ($author_id == 0)
$author_id = -1;
if ($owner_id == 0)
$owner_id = -1;
q("UPDATE `item` SET `author-id` = %d, `owner-id` = %d
WHERE `uid` = %d AND `author-link` = '%s' AND `owner-link` = '%s'
AND `author-id` = 0 AND `owner-id` = 0",
intval($author_id), intval($owner_id), intval($item["uid"]),
dbesc($item["author-link"]), dbesc($item["owner-link"]));
}
logger("Updated items", LOGGER_DEBUG);
return false;
}
?>

View file

@ -2,19 +2,19 @@
require_once("boot.php");
require_once("include/ostatus.php");
function handle_pubsubhubbub() {
use \Friendica\Core\Config;
use \Friendica\Core\PConfig;
function handle_pubsubhubbub($id) {
global $a, $db;
logger('start');
$r = q("SELECT * FROM `push_subscriber` WHERE `id` = %d", intval($id));
if (!$r)
return;
else
$rr = $r[0];
// We'll push to each subscriber that has push > 0,
// i.e. there has been an update (set in notifier.php).
$r = q("SELECT * FROM `push_subscriber` WHERE `push` > 0");
foreach($r as $rr) {
logger("Generate feed for user ".$rr['nickname']." - last updated ".$rr['last_update'], LOGGER_DEBUG);
logger("Generate feed of user ".$rr['nickname']." to ".$rr['callback_url']." - last updated ".$rr['last_update'], LOGGER_DEBUG);
$params = ostatus::feed($a, $rr['nickname'], $rr['last_update']);
$hmac_sig = hash_hmac("sha1", $params, $rr['secret']);
@ -55,9 +55,6 @@ function handle_pubsubhubbub() {
}
}
logger('done');
}
function pubsubpublish_run(&$argv, &$argc){
global $a, $db;
@ -89,10 +86,28 @@ function pubsubpublish_run(&$argv, &$argc){
if($argc > 1)
$pubsubpublish_id = intval($argv[1]);
else
$pubsubpublish_id = 0;
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");
handle_pubsubhubbub();
// 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;

View file

@ -17,7 +17,6 @@ function queue_run(&$argv, &$argc){
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once("include/session.php");
require_once("include/datetime.php");
require_once('include/items.php');
@ -45,10 +44,12 @@ function queue_run(&$argv, &$argc){
$deadservers = array();
$serverlist = array();
if (!$queue_id) {
logger('queue: start');
// Handling the pubsubhubbub requests
proc_run('php','include/pubsubpublish.php');
proc_run(PRIORITY_HIGH,'include/pubsubpublish.php');
$interval = ((get_config('system','delivery_interval') === false) ? 2 : intval(get_config('system','delivery_interval')));
@ -60,7 +61,7 @@ function queue_run(&$argv, &$argc){
if($r) {
foreach($r as $rr) {
logger('queue: deliverq');
proc_run('php','include/delivery.php',$rr['cmd'],$rr['item'],$rr['contact']);
proc_run(PRIORITY_HIGH,'include/delivery.php',$rr['cmd'],$rr['item'],$rr['contact']);
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
@ -77,18 +78,18 @@ function queue_run(&$argv, &$argc){
q("DELETE FROM `queue` WHERE `created` < UTC_TIMESTAMP() - INTERVAL 3 DAY");
}
if($queue_id) {
$r = q("SELECT `id` FROM `queue` WHERE `id` = %d LIMIT 1",
intval($queue_id)
);
}
else {
// For the first 12 hours we'll try to deliver every 15 minutes
// 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)
);
}
if (!$r){
return;
}
@ -107,16 +108,17 @@ function queue_run(&$argv, &$argc){
// queue_predeliver hooks may have changed the queue db details,
// so check again if this entry still needs processing
if($queue_id) {
if($queue_id)
$qi = q("SELECT * FROM `queue` WHERE `id` = %d LIMIT 1",
intval($queue_id)
);
}
else {
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'])
);
}
intval($q_item['id']));
if(! count($qi))
continue;

View file

@ -21,14 +21,14 @@ function was_recently_delayed($cid) {
and last > UTC_TIMESTAMP() - interval 15 minute limit 1",
intval($cid)
);
if(dba::is_result($r))
if(dbm::is_result($r))
return true;
$r = q("select `term-date` from contact where id = %d and `term-date` != '' and `term-date` != '0000-00-00 00:00:00' limit 1",
intval($cid)
);
return (dba::is_result($r));
return (dbm::is_result($r));
}

View file

@ -1,15 +1,14 @@
<?php
require_once('include/crypto.php');
require_once('include/Probe.php');
function get_salmon_key($uri,$keyhash) {
$ret = array();
logger('Fetching salmon key for '.$uri);
$arr = lrdd($uri);
$arr = Probe::lrdd($uri);
if(is_array($arr)) {
foreach($arr as $a) {

View file

@ -42,7 +42,7 @@ function authenticate_success($user_record, $login_initial = false, $interactive
$r = q("select * from user where uid = %d limit 1",
intval($_SESSION['submanage'])
);
if(dba::is_result($r))
if(dbm::is_result($r))
$master_record = $r[0];
}
@ -70,7 +70,7 @@ function authenticate_success($user_record, $login_initial = false, $interactive
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1",
intval($_SESSION['uid']));
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$a->contact = $r[0];
$a->cid = $r[0]['id'];
$_SESSION['cid'] = $a->cid;
@ -158,7 +158,7 @@ function can_write_wall(&$a,$owner) {
intval(PAGE_COMMUNITY)
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$verified = 2;
return true;
}
@ -212,7 +212,7 @@ function permissions_sql($owner_id,$remote_verified = false,$groups = null) {
intval($remote_user),
intval($owner_id)
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$remote_verified = true;
$groups = init_groups_visitor($remote_user);
}
@ -294,7 +294,7 @@ function item_permissions_sql($owner_id,$remote_verified = false,$groups = null)
intval($remote_user),
intval($owner_id)
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$remote_verified = true;
$groups = init_groups_visitor($remote_user);
}
@ -405,7 +405,7 @@ function init_groups_visitor($contact_id) {
WHERE `contact-id` = %d ",
intval($contact_id)
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $rr)
$groups[] = $rr['gid'];
}

View file

@ -17,7 +17,7 @@ function ref_session_read ($id) {
if(x($id))
$r = q("SELECT `data` FROM `session` WHERE `sid`= '%s'", dbesc($id));
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$session_exists = true;
return $r[0]['data'];
} else {

View file

@ -9,6 +9,7 @@
require_once('include/datetime.php');
require_once("include/Scrape.php");
require_once("include/network.php");
require_once("include/html2bbcode.php");
require_once("include/Contact.php");
require_once("include/Photo.php");
@ -39,7 +40,7 @@ function poco_load($cid,$uid = 0,$zcid = 0,$url = null) {
$r = q("select `poco`, `uid` from `contact` where `id` = %d limit 1",
intval($cid)
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$url = $r[0]['poco'];
$uid = $r[0]['uid'];
}
@ -205,14 +206,14 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
$r = q("SELECT `network` FROM `contact` WHERE `nurl` = '%s' AND `network` != '' AND `network` != '%s' LIMIT 1",
dbesc(normalise_link($profile_url)), dbesc(NETWORK_STATUSNET)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$network = $r[0]["network"];
if (($network == "") OR ($network == NETWORK_OSTATUS)) {
$r = q("SELECT `network`, `url` FROM `contact` WHERE `alias` IN ('%s', '%s') AND `network` != '' AND `network` != '%s' LIMIT 1",
dbesc($profile_url), dbesc(normalise_link($profile_url)), dbesc(NETWORK_STATUSNET)
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$network = $r[0]["network"];
//$profile_url = $r[0]["url"];
}
@ -453,7 +454,10 @@ function poco_last_updated($profile, $force = false) {
"network" => $server[0]["network"],
"generation" => $gcontacts[0]["generation"]);
if (isset($noscrape["fn"]))
$contact["name"] = $noscrape["fn"];
if (isset($noscrape["comm"]))
$contact["community"] = $noscrape["comm"];
if (isset($noscrape["tags"])) {
@ -466,6 +470,7 @@ function poco_last_updated($profile, $force = false) {
if ($location)
$contact["location"] = $location;
if (isset($noscrape["dfrn-notify"]))
$contact["notify"] = $noscrape["dfrn-notify"];
// Remove all fields that are not present in the gcontact table
@ -948,7 +953,7 @@ function count_common_friends($uid,$cid) {
);
// logger("count_common_friends: $uid $cid {$r[0]['total']}");
if(dba::is_result($r))
if(dbm::is_result($r))
return $r[0]['total'];
return 0;
@ -994,7 +999,7 @@ function count_common_friends_zcid($uid,$zcid) {
intval($uid)
);
if(dba::is_result($r))
if(dbm::is_result($r))
return $r[0]['total'];
return 0;
@ -1033,7 +1038,7 @@ function count_all_friends($uid,$cid) {
intval($uid)
);
if(dba::is_result($r))
if(dbm::is_result($r))
return $r[0]['total'];
return 0;
@ -1162,7 +1167,7 @@ function update_suggestions() {
dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA)
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
foreach($r as $rr) {
$base = substr($rr['poco'],0,strrpos($rr['poco'],'/'));
if(! in_array($base,$done))
@ -1447,6 +1452,10 @@ function get_gcontact_id($contact) {
if ($contact["network"] == NETWORK_STATUSNET)
$contact["network"] = NETWORK_OSTATUS;
// All new contacts are hidden by default
if (!isset($contact["hide"]))
$contact["hide"] = true;
// Replace alternate OStatus user format with the primary one
fix_alternate_contact_address($contact);
@ -1469,8 +1478,8 @@ function get_gcontact_id($contact) {
$doprobing = (((time() - $last_contact) > (90 * 86400)) AND ((time() - $last_failure) > (90 * 86400)));
}
} else {
q("INSERT INTO `gcontact` (`name`, `nick`, `addr` , `network`, `url`, `nurl`, `photo`, `created`, `updated`, `location`, `about`, `generation`)
VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)",
q("INSERT INTO `gcontact` (`name`, `nick`, `addr` , `network`, `url`, `nurl`, `photo`, `created`, `updated`, `location`, `about`, `hide`, `generation`)
VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d)",
dbesc($contact["name"]),
dbesc($contact["nick"]),
dbesc($contact["addr"]),
@ -1482,6 +1491,7 @@ function get_gcontact_id($contact) {
dbesc(datetime_convert()),
dbesc($contact["location"]),
dbesc($contact["about"]),
intval($contact["hide"]),
intval($contact["generation"])
);
@ -1497,7 +1507,7 @@ function get_gcontact_id($contact) {
if ($doprobing) {
logger("Last Contact: ". $last_contact_str." - Last Failure: ".$last_failure_str." - Checking: ".$contact["url"], LOGGER_DEBUG);
proc_run('php', 'include/gprobe.php', bin2hex($contact["url"]));
proc_run(PRIORITY_LOW, 'include/gprobe.php', bin2hex($contact["url"]));
}
if ((count($r) > 1) AND ($gcontact_id > 0) AND ($contact["url"] != ""))
@ -1535,6 +1545,7 @@ function update_gcontact($contact) {
unset($fields["url"]);
unset($fields["updated"]);
unset($fields["hide"]);
// Bugfix: We had an error in the storing of keywords which lead to the "0"
// This value is still transmitted via poco.
@ -1549,6 +1560,11 @@ function update_gcontact($contact) {
if (!isset($contact[$field]) OR ($contact[$field] == ""))
$contact[$field] = $r[0][$field];
if (!isset($contact["hide"]))
$contact["hide"] = $r[0]["hide"];
$fields["hide"] = $r[0]["hide"];
if ($contact["network"] == NETWORK_STATUSNET)
$contact["network"] = NETWORK_OSTATUS;
@ -1657,6 +1673,44 @@ function update_gcontact_from_probe($url) {
update_gcontact($data);
}
/**
* @brief Update the gcontact entry for a given user id
*
* @param int $uid User ID
*/
function update_gcontact_for_user($uid) {
$r = q("SELECT `profile`.`locality`, `profile`.`region`, `profile`.`country-name`,
`profile`.`name`, `profile`.`about`, `profile`.`gender`,
`profile`.`pub_keywords`, `profile`.`dob`, `profile`.`photo`,
`profile`.`net-publish`, `user`.`nickname`, `user`.`hidewall`,
`contact`.`notify`, `contact`.`url`, `contact`.`addr`
FROM `profile`
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
INNER JOIN `contact` ON `contact`.`uid` = `profile`.`uid`
WHERE `profile`.`uid` = %d AND `profile`.`is-default` AND `contact`.`self`",
intval($uid));
$location = formatted_location(array("locality" => $r[0]["locality"], "region" => $r[0]["region"],
"country-name" => $r[0]["country-name"]));
// The "addr" field was added in 3.4.3 so it can be empty for older users
if ($r[0]["addr"] != "")
$addr = $r[0]["nickname"].'@'.str_replace(array("http://", "https://"), "", App::get_baseurl());
else
$addr = $r[0]["addr"];
$gcontact = array("name" => $r[0]["name"], "location" => $location, "about" => $r[0]["about"],
"gender" => $r[0]["gender"], "keywords" => $r[0]["pub_keywords"],
"birthday" => $r[0]["dob"], "photo" => $r[0]["photo"],
"notify" => $r[0]["notify"], "url" => $r[0]["url"],
"hide" => ($r[0]["hidewall"] OR !$r[0]["net-publish"]),
"nick" => $r[0]["nickname"], "addr" => $addr,
"connect" => $addr, "server_url" => App::get_baseurl(),
"generation" => 1, "network" => NETWORK_DFRN);
update_gcontact($gcontact);
}
/**
* @brief Fetches users of given GNU Social server
*

View file

@ -491,7 +491,7 @@ function item_new_uri($hostname,$uid, $guid = "") {
$r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' LIMIT 1",
dbesc($uri));
if(dba::is_result($r))
if(dbm::is_result($r))
$dups = true;
} while($dups == true);
return $uri;
@ -515,7 +515,7 @@ function photo_new_resource() {
$r = q("SELECT `id` FROM `photo` WHERE `resource-id` = '%s' LIMIT 1",
dbesc($resource)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$found = true;
} while($found == true);
return $resource;
@ -717,10 +717,15 @@ function logger($msg,$level = 0) {
if((! $debugging) || (! $logfile) || ($level > $loglevel))
return;
$process_id = session_id();
if ($process_id == "")
$process_id = get_app()->process_id;
$callers = debug_backtrace();
$logline = sprintf("%s@%s\t[%s]:%s:%s:%s\t%s\n",
datetime_convert(),
session_id(),
$process_id,
$LOGGER_LEVELS[$level],
basename($callers[0]['file']),
$callers[0]['line'],
@ -859,7 +864,7 @@ function contact_block() {
dbesc(NETWORK_OSTATUS),
dbesc(NETWORK_DIASPORA)
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$total = intval($r[0]['total']);
}
if(! $total) {
@ -867,7 +872,8 @@ function contact_block() {
$micropro = Null;
} else {
$r = q("SELECT `id`, `uid`, `addr`, `url`, `name`, `micro`, `network` FROM `contact`
// Splitting the query in two parts makes it much faster
$r = q("SELECT `id` FROM `contact`
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending`
AND NOT `hidden` AND NOT `archive`
AND `network` IN ('%s', '%s', '%s') ORDER BY RAND() LIMIT %d",
@ -877,7 +883,15 @@ function contact_block() {
dbesc(NETWORK_DIASPORA),
intval($shown)
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
$contacts = "";
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)));
if(dbm::is_result($r)) {
$contacts = sprintf( tt('%d Contact','%d Contacts', $total),$total);
$micropro = Array();
foreach($r as $rr) {
@ -885,6 +899,7 @@ function contact_block() {
}
}
}
}
$tpl = get_markup_template('contact_block.tpl');
$o = replace_macros($tpl, array(
@ -901,20 +916,28 @@ function contact_block() {
}}
if(! function_exists('micropro')) {
/**
* @brief Format contacts as picture links or as texxt links
*
* @param array $contact
* @param boolean $redirect
* @param string $class
* @param boolean $textmode
* @return string #FIXME: remove html
* @param array $contact Array with contacts which contains an array with
* int 'id' => The ID of the contact
* int 'uid' => The user ID of the user who owns this data
* string 'name' => The name of the contact
* string 'url' => The url to the profile page of the contact
* string 'addr' => The webbie of the contact (e.g.) username@friendica.com
* string 'network' => The network to which the contact belongs to
* string 'thumb' => The contact picture
* string 'click' => js code which is performed when clicking on the contact
* @param boolean $redirect If true try to use the redir url if it's possible
* @param string $class CSS class for the
* @param boolean $textmode If true display the contacts as text links
* if false display the contacts as picture links
* @return string Formatted html
*/
function micropro($contact, $redirect = false, $class = '', $textmode = false) {
if($class)
$class = ' ' . $class;
// Use the contact URL if no address is available
if ($contact["addr"] == "")
$contact["addr"] = $contact["url"];
@ -933,26 +956,23 @@ function micropro($contact, $redirect = false, $class = '', $textmode = false) {
else
$url = zrl($url);
}
$click = ((x($contact,'click')) ? ' onclick="' . $contact['click'] . '" ' : '');
if($click)
// If there is some js available we don't need the url
if(x($contact,'click'))
$url = '';
if($textmode) {
return '<div class="contact-block-textdiv' . $class . '"><a class="contact-block-link' . $class . $sparkle
. (($click) ? ' fakelink' : '') . '" '
. (($redir) ? ' target="redir" ' : '')
. (($url) ? ' href="' . $url . '"' : '') . $click
. '" title="' . $contact['name'] . ' [' . $contact['addr'] . ']" alt="' . $contact['name']
. '" >'. $contact['name'] . '</a></div>' . "\r\n";
return replace_macros(get_markup_template(($textmode)?'micropro_txt.tpl':'micropro_img.tpl'),array(
'$click' => (($contact['click']) ? $contact['click'] : ''),
'$class' => $class,
'$url' => $url,
'$photo' => proxy_url($contact['thumb'], false, PROXY_SIZE_THUMB),
'$name' => $contact['name'],
'title' => $contact['name'] . ' [' . $contact['addr'] . ']',
'$parkle' => $sparkle,
'$redir' => $redir,
));
}
else {
return '<div class="contact-block-div' . $class . '"><a class="contact-block-link' . $class . $sparkle
. (($click) ? ' fakelink' : '') . '" '
. (($redir) ? ' target="redir" ' : '')
. (($url) ? ' href="' . $url . '"' : '') . $click . ' ><img class="contact-block-img' . $class . $sparkle . '" src="'
. proxy_url($contact['micro'], false, PROXY_SIZE_THUMB) . '" title="' . $contact['name'] . ' [' . $contact['addr'] . ']" alt="' . $contact['name']
. '" /></a></div>' . "\r\n";
}
}}
@ -975,6 +995,7 @@ function search($s,$id='search-box',$url='search',$save = false, $aside = true)
'$search_label' => t('Search'),
'$save_label' => t('Save'),
'$savedsearch' => feature_enabled(local_user(),'savedsearch'),
'$search_hint' => t('@name, !forum, #tags, content'),
);
if (!$aside) {
@ -1080,159 +1101,6 @@ function get_mood_verbs() {
return $arr;
}
if(! function_exists('smilies')) {
/**
* Replaces text emoticons with graphical images
*
* It is expected that this function will be called using HTML text.
* We will escape text between HTML pre and code blocks from being
* processed.
*
* At a higher level, the bbcode [nosmile] tag can be used to prevent this
* function from being executed by the prepare_text() routine when preparing
* bbcode source for HTML display
*
* @param string $s
* @param boolean $sample
* @return string
* @hook smilie ('texts' => smilies texts array, 'icons' => smilies html array, 'string' => $s)
*/
function smilies($s, $sample = false) {
$a = get_app();
if(intval(get_config('system','no_smilies'))
|| (local_user() && intval(get_pconfig(local_user(),'system','no_smilies'))))
return $s;
$s = preg_replace_callback('/<pre>(.*?)<\/pre>/ism','smile_encode',$s);
$s = preg_replace_callback('/<code>(.*?)<\/code>/ism','smile_encode',$s);
$texts = array(
'&lt;3',
'&lt;/3',
'&lt;\\3',
':-)',
';-)',
':-(',
':-P',
':-p',
':-"',
':-&quot;',
':-x',
':-X',
':-D',
'8-|',
'8-O',
':-O',
'\\o/',
'o.O',
'O.o',
'o_O',
'O_o',
":'(",
":-!",
":-/",
":-[",
"8-)",
':beer',
':homebrew',
':coffee',
':facepalm',
':like',
':dislike',
'~friendica',
'red#',
'red#matrix'
);
$icons = array(
'<img class="smiley" src="' . z_root() . '/images/smiley-heart.gif" alt="&lt;3" title="&lt;3" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-brokenheart.gif" alt="&lt;/3" title="&lt;/3" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-brokenheart.gif" alt="&lt;\\3" title="&lt;\\3" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-smile.gif" alt=":-)" title=":-)" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-wink.gif" alt=";-)" title=";-)" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-frown.gif" alt=":-(" title=":-(" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-tongue-out.gif" alt=":-P" title=":-P" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-tongue-out.gif" alt=":-p" title=":-P" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-\" title=":-\" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-\" title=":-\" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-x" title=":-x" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-X" title=":-X" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-laughing.gif" alt=":-D" title=":-D" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt="8-|" title="8-|" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt="8-O" title="8-O" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt=":-O" title="8-O" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-thumbsup.gif" alt="\\o/" title="\\o/" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="o.O" title="o.O" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="O.o" title="O.o" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="o_O" title="o_O" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="O_o" title="O_o" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-cry.gif" alt=":\'(" title=":\'("/>',
'<img class="smiley" src="' . z_root() . '/images/smiley-foot-in-mouth.gif" alt=":-!" title=":-!" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-undecided.gif" alt=":-/" title=":-/" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-embarassed.gif" alt=":-[" title=":-[" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-cool.gif" alt="8-)" title="8-)" />',
'<img class="smiley" src="' . z_root() . '/images/beer_mug.gif" alt=":beer" title=":beer" />',
'<img class="smiley" src="' . z_root() . '/images/beer_mug.gif" alt=":homebrew" title=":homebrew" />',
'<img class="smiley" src="' . z_root() . '/images/coffee.gif" alt=":coffee" title=":coffee" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-facepalm.gif" alt=":facepalm" title=":facepalm" />',
'<img class="smiley" src="' . z_root() . '/images/like.gif" alt=":like" title=":like" />',
'<img class="smiley" src="' . z_root() . '/images/dislike.gif" alt=":dislike" title=":dislike" />',
'<a href="http://friendica.com">~friendica <img class="smiley" src="' . z_root() . '/images/friendica-16.png" alt="~friendica" title="~friendica" /></a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . z_root() . '/images/rm-16.png" alt="red#" title="red#" />matrix</a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . z_root() . '/images/rm-16.png" alt="red#matrix" title="red#matrix" />matrix</a>'
);
$params = array('texts' => $texts, 'icons' => $icons, 'string' => $s);
call_hooks('smilie', $params);
if($sample) {
$s = '<div class="smiley-sample">';
for($x = 0; $x < count($params['texts']); $x ++) {
$s .= '<dl><dt>' . $params['texts'][$x] . '</dt><dd>' . $params['icons'][$x] . '</dd></dl>';
}
}
else {
$params['string'] = preg_replace_callback('/&lt;(3+)/','preg_heart',$params['string']);
$s = str_replace($params['texts'],$params['icons'],$params['string']);
}
$s = preg_replace_callback('/<pre>(.*?)<\/pre>/ism','smile_decode',$s);
$s = preg_replace_callback('/<code>(.*?)<\/code>/ism','smile_decode',$s);
return $s;
}}
function smile_encode($m) {
return(str_replace($m[1],base64url_encode($m[1]),$m[0]));
}
function smile_decode($m) {
return(str_replace($m[1],base64url_decode($m[1]),$m[0]));
}
/**
* expand <3333 to the correct number of hearts
*
* @param string $x
* @return string
*/
function preg_heart($x) {
$a = get_app();
if(strlen($x[1]) == 1)
return $x[0];
$t = '';
for($cnt = 0; $cnt < strlen($x[1]); $cnt ++)
$t .= '<img class="smiley" src="' . z_root() . '/images/smiley-heart.gif" alt="&lt;3" />';
$r = str_replace($x[0],$t,$x[0]);
return $r;
}
if(! function_exists('day_translate')) {
/**
* Translate days and months names
@ -2050,7 +1918,7 @@ function file_tag_update_pconfig($uid,$file_old,$file_new,$type = 'file') {
// intval($uid)
//);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
unset($deleted_tags[$key]);
}
else {
@ -2080,7 +1948,7 @@ function file_tag_save_file($uid,$item,$file) {
intval($item),
intval($uid)
);
if(dba::is_result($r)) {
if(dbm::is_result($r)) {
if(! stristr($r[0]['file'],'[' . file_tag_encode($file) . ']'))
q("UPDATE `item` SET `file` = '%s' WHERE `id` = %d AND `uid` = %d",
dbesc($r[0]['file'] . '[' . file_tag_encode($file) . ']'),
@ -2239,3 +2107,54 @@ function format_network_name($network, $url = 0) {
}
}
/**
* @brief Syntax based code highlighting for popular languages.
* @param string $s Code block
* @param string $lang Programming language
* @return string Formated html
*/
function text_highlight($s,$lang) {
if($lang === 'js')
$lang = 'javascript';
if(! strpos('Text_Highlighter',get_include_path())) {
set_include_path(get_include_path() . PATH_SEPARATOR . 'library/Text_Highlighter');
}
require_once('library/Text_Highlighter/Text/Highlighter.php');
require_once('library/Text_Highlighter/Text/Highlighter/Renderer/Html.php');
$options = array(
'numbers' => HL_NUMBERS_LI,
'tabsize' => 4,
);
$tag_added = false;
$s = trim(html_entity_decode($s,ENT_COMPAT));
$s = str_replace(" ","\t",$s);
// The highlighter library insists on an opening php tag for php code blocks. If
// it isn't present, nothing is highlighted. So we're going to see if it's present.
// If not, we'll add it, and then quietly remove it after we get the processed output back.
if($lang === 'php') {
if(strpos('<?php',$s) !== 0) {
$s = '<?php' . "\n" . $s;
$tag_added = true;
}
}
$renderer = new Text_Highlighter_Renderer_HTML($options);
$hl = Text_Highlighter::factory($lang);
$hl->setRenderer($renderer);
$o = $hl->highlight($s);
$o = str_replace([" ","\n"],["&nbsp;&nbsp;&nbsp;&nbsp;",''],$o);
if($tag_added) {
$b = substr($o,0,strpos($o,'<li>'));
$e = substr($o,strpos($o,'</li>'));
$o = $b . $e;
}
return('<code>' . $o . '</code>');
}

View file

@ -1,7 +1,9 @@
<?php
function add_thread($itemid, $onlyshadow = false) {
$items = q("SELECT `uid`, `created`, `edited`, `commented`, `received`, `changed`, `wall`, `private`, `pubmail`, `moderated`, `visible`, `spam`, `starred`, `bookmark`, `contact-id`, `gcontact-id`,
`deleted`, `origin`, `forum_mode`, `mention`, `network` FROM `item` WHERE `id` = %d AND (`parent` = %d OR `parent` = 0) LIMIT 1", intval($itemid), intval($itemid));
$items = q("SELECT `uid`, `created`, `edited`, `commented`, `received`, `changed`, `wall`, `private`, `pubmail`,
`moderated`, `visible`, `spam`, `starred`, `bookmark`, `contact-id`, `gcontact-id`,
`deleted`, `origin`, `forum_mode`, `mention`, `network`, `author-id`, `owner-id`
FROM `item` WHERE `id` = %d AND (`parent` = %d OR `parent` = 0) LIMIT 1", intval($itemid), intval($itemid));
if (!$items)
return;
@ -83,12 +85,12 @@ function add_shadow_entry($item) {
// Is there a shadow parent?
$r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = 0 LIMIT 1", dbesc($item['parent-uri']));
if (!count($r))
if (!dbm::is_result($r))
return;
// Is there already a shadow entry?
$r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = 0 LIMIT 1", dbesc($item['uri']));
if (dba::is_result($r))
if (dbm::is_result($r))
return;
// Preparing public shadow (removing user specific data)
@ -106,7 +108,7 @@ function add_shadow_entry($item) {
function update_thread_uri($itemuri, $uid) {
$messages = q("SELECT `id` FROM `item` WHERE uri ='%s' AND uid=%d", dbesc($itemuri), intval($uid));
if(count($messages))
if(dbm::is_result($messages))
foreach ($messages as $message)
update_thread($message["id"]);
}
@ -115,7 +117,7 @@ function update_thread($itemid, $setmention = false) {
$items = q("SELECT `uid`, `guid`, `title`, `body`, `created`, `edited`, `commented`, `received`, `changed`, `wall`, `private`, `pubmail`, `moderated`, `visible`, `spam`, `starred`, `bookmark`, `contact-id`, `gcontact-id`,
`deleted`, `origin`, `forum_mode`, `network`, `rendered-html`, `rendered-hash` FROM `item` WHERE `id` = %d AND (`parent` = %d OR `parent` = 0) LIMIT 1", intval($itemid), intval($itemid));
if (!$items)
if (!dbm::is_result($items))
return;
$item = $items[0];
@ -174,7 +176,7 @@ function delete_thread($itemid, $itemuri = "") {
intval($item["uid"])
);
if (!count($r)) {
$r = q("DELETE FROM `item` WHERE `uri` = '%s' AND `uid` = 0)",
$r = q("DELETE FROM `item` WHERE `uri` = '%s' AND `uid` = 0",
dbesc($itemuri)
);
logger("delete_thread: Deleted shadow for item ".$itemuri." - ".print_r($result, true), LOGGER_DEBUG);

View file

@ -287,7 +287,7 @@ function import_account(&$a, $file) {
}
// send relocate messages
proc_run('php', 'include/notifier.php', 'relocate', $newuid);
proc_run(PRIORITY_HIGH, 'include/notifier.php', 'relocate', $newuid);
info(t("Done. You can now login with your username and password"));
goaway($a->get_baseurl() . "/login");

View file

@ -130,7 +130,7 @@ function create_user($arr) {
$r = q("SELECT * FROM `user` WHERE `email` = '%s' LIMIT 1",
dbesc($email)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$result['message'] .= t('Cannot use that email.') . EOL;
}
@ -143,7 +143,7 @@ function create_user($arr) {
WHERE `nickname` = '%s' LIMIT 1",
dbesc($nickname)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
// Check deleted accounts that had this nickname. Doesn't matter to us,
@ -153,7 +153,7 @@ function create_user($arr) {
WHERE `username` = '%s' LIMIT 1",
dbesc($nickname)
);
if(dba::is_result($r))
if(dbm::is_result($r))
$result['message'] .= t('Nickname was once registered here and may not be re-used. Please choose another.') . EOL;
if(strlen($result['message'])) {

View file

@ -27,8 +27,11 @@ class xml {
foreach ($namespaces AS $nskey => $nsvalue)
$key .= " xmlns".($nskey == "" ? "":":").$nskey.'="'.$nsvalue.'"';
if (is_array($value)) {
$root = new SimpleXMLElement("<".$key."/>");
self::from_array($value, $root, $remove_header, $namespaces, false);
} else
$root = new SimpleXMLElement("<".$key.">".xmlify($value)."</".$key.">");
$dom = dom_import_simplexml($root)->ownerDocument;
$dom->formatOutput = true;
@ -44,7 +47,33 @@ class xml {
}
foreach($array as $key => $value) {
if ($key == "@attributes") {
if (!isset($element) AND isset($xml))
$element = $xml;
if (is_integer($key)) {
if (isset($element)) {
if (is_scalar($value)) {
$element[0] = $value;
} else {
/// @todo: handle nested array values
}
}
continue;
}
$element_parts = explode(":", $key);
if ((count($element_parts) > 1) AND isset($namespaces[$element_parts[0]]))
$namespace = $namespaces[$element_parts[0]];
elseif (isset($namespaces[""])) {
$namespace = $namespaces[""];
} else
$namespace = NULL;
// Remove undefined namespaces from the key
if ((count($element_parts) > 1) AND is_null($namespace))
$key = $element_parts[1];
if (substr($key, 0, 11) == "@attributes") {
if (!isset($element) OR !is_array($value))
continue;
@ -61,12 +90,6 @@ class xml {
continue;
}
$element_parts = explode(":", $key);
if ((count($element_parts) > 1) AND isset($namespaces[$element_parts[0]]))
$namespace = $namespaces[$element_parts[0]];
else
$namespace = NULL;
if (!is_array($value))
$element = $xml->addChild($key, xmlify($value), $namespace);
elseif (is_array($value)) {

117
index.php
View file

@ -19,6 +19,10 @@ require_once('object/BaseObject.php');
$a = new App;
BaseObject::set_app($a);
// We assume that the index.php is called by a frontend process
// The value is set to "true" by default in boot.php
$a->backend = false;
/**
*
* Load the configuration file which contains our DB credentials.
@ -53,20 +57,12 @@ if(!$install) {
load_config('config');
load_config('system');
$maxsysload_frontend = intval(get_config('system','maxloadavg_frontend'));
if($maxsysload_frontend < 1)
$maxsysload_frontend = 50;
$load = current_load();
if($load) {
if($load > $maxsysload_frontend) {
logger('system: load ' . $load . ' too high. Service Temporarily Unavailable.');
if ($a->max_processes_reached() OR $a->maxload_reached()) {
header($_SERVER["SERVER_PROTOCOL"].' 503 Service Temporarily Unavailable');
header('Retry-After: 300');
header('Retry-After: 120');
header('Refresh: 120; url='.$a->get_baseurl()."/".$a->query_string);
die("System is currently unavailable. Please try again later");
}
}
if (get_config('system','force_ssl') AND ($a->get_scheme() == "http") AND
(intval(get_config('system','ssl_policy')) == SSL_POLICY_FULL) AND
@ -98,7 +94,12 @@ load_translation_table($lang);
*
*/
// Exclude the backend processes from the session management
if (!$a->is_backend()) {
$stamp1 = microtime(true);
session_start();
$a->save_timestamp($stamp1, "parser");
}
/**
* Language was set earlier, but we can over-ride it in the session.
@ -108,7 +109,7 @@ if (x($_SESSION,'authenticated') && !x($_SESSION,'language')) {
// we didn't loaded user data yet, but we need user language
$r = q("SELECT language FROM user WHERE uid=%d", intval($_SESSION['uid']));
$_SESSION['language'] = $lang;
if (dba::is_result($r)) $_SESSION['language'] = $r[0]['language'];
if (dbm::is_result($r)) $_SESSION['language'] = $r[0]['language'];
}
if((x($_SESSION,'language')) && ($_SESSION['language'] !== $lang)) {
@ -488,73 +489,10 @@ if (isset($_GET["mode"]) AND ($_GET["mode"] == "raw")) {
echo substr($target->saveHTML(), 6, -8);
if (!$a->is_backend())
session_write_close();
exit;
} elseif (get_pconfig(local_user(),'system','infinite_scroll')
AND ($a->module == "network") AND ($_GET["mode"] != "minimal")) {
if (is_string($_GET["page"]))
$pageno = $_GET["page"];
else
$pageno = 1;
$reload_uri = "";
foreach ($_GET AS $param => $value)
if (($param != "page") AND ($param != "q"))
$reload_uri .= "&".$param."=".urlencode($value);
if (($a->page_offset != "") AND !strstr($reload_uri, "&offset="))
$reload_uri .= "&offset=".urlencode($a->page_offset);
$a->page['htmlhead'] .= <<< EOT
<script type="text/javascript">
$(document).ready(function() {
num = $pageno;
});
function loadcontent() {
if (lockLoadContent) return;
lockLoadContent = true;
$("#scroll-loader").fadeIn('normal');
num+=1;
console.log('Loading page ' + num);
$.get('/network?mode=raw$reload_uri&page=' + num, function(data) {
$("#scroll-loader").hide();
if ($(data).length > 0) {
$(data).insertBefore('#conversation-end');
lockLoadContent = false;
} else {
$("#scroll-end").fadeIn('normal');
}
});
}
var num = $pageno;
var lockLoadContent = false;
$(window).scroll(function(e){
if ($(document).height() != $(window).height()) {
// First method that is expected to work - but has problems with Chrome
if ($(window).scrollTop() > ($(document).height() - $(window).height() * 1.5))
loadcontent();
} else {
// This method works with Chrome - but seems to be much slower in Firefox
if ($(window).scrollTop() > (($("section").height() + $("header").height() + $("footer").height()) - $(window).height() * 1.5))
loadcontent();
}
});
</script>
EOT;
}
$page = $a->page;
@ -563,21 +501,20 @@ $profile = $a->profile;
header("X-Friendica-Version: ".FRIENDICA_VERSION);
header("Content-type: text/html; charset=utf-8");
if (isset($_GET["mode"]) AND ($_GET["mode"] == "minimal")) {
//$page['content'] = substr($target->saveHTML(), 6, -8)."\n\n".
// '<div id="conversation-end"></div>'."\n\n";
require "view/minimal.php";
} else {
$template = 'view/theme/' . current_theme() . '/'
. ((x($a->page,'template')) ? $a->page['template'] : 'default' ) . '.php';
if(file_exists($template))
require_once($template);
else
require_once(str_replace('theme/' . current_theme() . '/', '', $template));
// We use $_GET["mode"] for special page templates. So we will check if we have
// to load another page template than the default one
// The page templates are located in /view/php/ or in the theme directory
if (isset($_GET["mode"])) {
$template = theme_include($_GET["mode"].'.php');
}
// If there is no page template use the default page template
if(!$template) {
$template = theme_include("default.php");
}
require_once($template);
if (!$a->is_backend())
session_write_close();
exit;

View file

@ -41,7 +41,7 @@ function contact_search(term, callback, backend_url, type, mode) {
postdata['conversation'] = conv_id[0];
if(mode !== null)
postdata['mode'] = mode;
postdata['smode'] = mode;
$.ajax({
@ -104,6 +104,13 @@ function basic_replace(item) {
return '$1'+item.name+' ';
}
function webbie_replace(item) {
if(typeof item.replace !== 'undefined')
return '$1'+item.replace;
return '$1'+item.nick+' ';
}
function trim_replace(item) {
if(typeof item.replace !== 'undefined')
return '$1'+item.replace;
@ -216,7 +223,7 @@ function string2bb(element) {
match: /(^@)([^\n]{2,})$/,
index: 2,
search: function(term, callback) { contact_search(term, callback, backend_url, 'x', 'contact'); },
replace: basic_replace,
replace: webbie_replace,
template: contact_format,
};
@ -225,7 +232,7 @@ function string2bb(element) {
match: /(^!)([^\n]{2,})$/,
index: 2,
search: function(term, callback) { contact_search(term, callback, backend_url, 'x', 'community'); },
replace: basic_replace,
replace: webbie_replace,
template: contact_format,
};
this.attr('autocomplete', 'off');

View file

@ -51,6 +51,7 @@
var commentBusy = false;
var last_popup_menu = null;
var last_popup_button = null;
var lockLoadContent = false;
$(function() {
$.ajaxSetup({cache: false});
@ -349,6 +350,21 @@
}
});
// Set an event listener for infinite scroll
if(typeof infinite_scroll !== 'undefined') {
$(window).scroll(function(e){
if ($(document).height() != $(window).height()) {
// First method that is expected to work - but has problems with Chrome
if ($(window).scrollTop() > ($(document).height() - $(window).height() * 1.5))
loadScrollContent();
} else {
// This method works with Chrome - but seems to be much slower in Firefox
if ($(window).scrollTop() > (($("section").height() + $("header").height() + $("footer").height()) - $(window).height() * 1.5))
loadScrollContent();
}
});
}
});
@ -496,7 +512,7 @@
/* autocomplete @nicknames */
$(".comment-edit-form textarea").editor_autocomplete(baseurl+"/acl");
/* autocomplete bbcode */
+ $(".comment-edit-form textarea").bbco_autocomplete('bbcode');
$(".comment-edit-form textarea").bbco_autocomplete('bbcode');
// setup videos, since VideoJS won't take care of any loaded via AJAX
if(typeof videojs != 'undefined') videojs.autoSetup();
@ -709,6 +725,31 @@
$('#pause').html('');
}
// load more network content (used for infinite scroll)
function loadScrollContent() {
if (lockLoadContent) return;
lockLoadContent = true;
$("#scroll-loader").fadeIn('normal');
// the page number to load is one higher than the actual
// page number
infinite_scroll.pageno+=1;
console.log('Loading page ' + infinite_scroll.pageno);
// get the raw content from the next page and insert this content
// right before "#conversation-end"
$.get('network?mode=raw' + infinite_scroll.reload_uri + '&page=' + infinite_scroll.pageno, function(data) {
$("#scroll-loader").hide();
if ($(data).length > 0) {
$(data).insertBefore('#conversation-end');
lockLoadContent = false;
} else {
$("#scroll-end").fadeIn('normal');
}
});
}
function bin2hex(s){
// Converts the binary representation of data to hex

View file

@ -0,0 +1,455 @@
# $Id$
Introduction
============
Text_Highlighter is a class for syntax highlighting. The main idea is to
simplify creation of subclasses implementing syntax highlighting for
particular language. Subclasses do not implement any new functioanality, they
just provide syntax highlighting rules. The rules sources are in XML format.
To create a highlighter for a language, there is no need to code a new class
manually. Simply describe the rules in XML file and use Text_Highlighter_Generator
to create a new class.
This document does not contain a formal description of API - it is very
simple, and I believe providing some examples of code is sufficient.
Highlighter XML source
======================
Basics
------
Creating a new syntax highlighter begins with describing the highlighting
rules. There are two basic elements: block and region. A block is just a
portion of text matching a regular expression and highlighted with a single
color. Keyword is an example of a block. A region is defined by two regular
expressions: one for start of region, and another for the end. The main
difference from a block is that a region can contain blocks and regions
(including same-named regions). An example of a region is a group of
statements enclosed in curly brackets (this is used in many languages, for
example PHP and C). Also, characters matching start and end of a region may be
highlighted with their own color, and region contents with another.
Blocks and regions may be declared as contained. Contained blocks and regions
can only appear inside regions. If a region or a block is not declared as
contained, it can appear both on top level and inside regions. Block or region
declared as not-contained can only appear on top level.
For any region, a list of blocks and regions that can appear inside this
region can be specified.
In this document, the term "color group" is used. Chunks of text assigned to
same color group will be highlighted with same color. Note that in versions
prior 0.5.0 color goups were refered as CSS classes, but since 0.5.0 not only
HTML output is supported, so "color group" is more appropriate term.
Elements
--------
The toplevel element is <highlight>. Attribute lang is required and denotes
the name of the language. Its value is used as a part of generated class name,
and must only contain letters, digits and underscores. Optional attribute
case, when given value yes, makes the language case sensitive (default is case
insensitive). Allowed subelements are:
* <authors>: Information about the authors of the file.
<author>: Information about a single author of the file. (May be used
multiple times, one per author.)
- name="...": Author's name. Required.
- email="...": Author's email address. Optional.
* <default>: Default color group.
- innerGroup="...": color group name. Required.
* <region>: Region definition
- name="...": Region name. Required.
- innerGroup="...": Default color group of region contents. Required.
- delimGroup="...": color group of start and end of region. Optional,
defaults to value of innerGroup attribute.
- start="...", end="...": Regular expression matching start and end
of region. Required. Regular expression delimiters are optional, but
if you need to specify delimiter, use /. The only case when the
delimiters are needed, is specifying regular expression modifiers,
such as m or U. Examples: \/\* or /$/m.
- contained="yes": Marks region as contained.
- never-contained="yes": Marks region as not-contained.
- <contains>: Elements allowed inside this region.
- all="yes" Region can contain any other region or block
(except not-contained). May be used multiple times.
- <but> Do not allow certain regions or blocks.
- region="..." Name of region not allowed within
current region.
- block="..." Name of block not allowed within
current region.
- region="..." Name of region allowed within current region.
- block="..." Name of block allowed within current region.
- <onlyin> Only allow this region within certain regions. May be
used multiple times.
- block="..." Name of parent region
* <block>: Block definition
- name="...": Block name. Required.
- innerGroup="...": color group of block contents. Optional. If not
specified, color group of parent region or default color group will be
used. One would only want to omit this attribute if there are
keyword groups (see below) inherited from this block, and no special
highlighting should apply when the block does not match the keyword.
- match="..." Regular expression matching the block. Required.
Regular expression delimiters are optional, but if you need to
specify delimiter, use /. The only case when the delimiters are
needed, is specifying regular expression modifiers, such as m or U.
Examples: #|\/\/ or /$/m.
- contained="yes": Marks block as contained.
- never-contained="yes": Marks block as not-contained.
- <onlyin> Only allow this block within certain regions. May be used
multiple times.
- block="..." Name of parent region
- multiline="yes": Marks block as multi-line. By default, whole
blocks are assumed to reside in a single line. This make the things
faster. If you need to declare a multi-line block, use this
attribute.
- <partgroup>: Assigns another color group to a part of the block that
matched a subpattern.
- index="n": Subpattern index. Required.
- innerGroup="...": color group name. Required.
This is an example from CSS highlighter: the measure is matched as
a whole, but the measurement units are highlighted with different
color.
<block name="measure" match="\d*\.?\d+(\%|em|ex|pc|pt|px|in|mm|cm)"
innerGroup="number" contained="yes">
<onlyin region="property"/>
<partGroup index="1" innerGroup="string" />
</block>
* <keywords>: Keyword group definition. Keyword groups are useful when you
want to highlight some words that match a condition for a block with a
different color. Keywords are defined with literal match, not regular
expressions. For example, you have a block named identifier matching a
general identifier, and want to highlight reserved words (which match
this block as well) with different color. You inherit a keyword group
"reserved" from "identifier" block.
- name="...": Keyword group. Required.
- ifdef="...", ifndef="..." : Conditional declaration. See
"Conditions" below.
- inherits="...": Inherited block name. Required.
- innerGroup="...": color group of keyword group. Required.
- case="yes|no": Overrides case-sensitivity of the language.
Optional, defaults to global value.
- <keyword>: Single keyword definition.
- match="..." The keyword. Note: this is not a regular
expression, but literal match (possibly case insensitive).
Note that for BC reasons element partClass is alias for partGroup, and
attributes innerClass and delimClass are aliases of innerGroup and
delimGroup, respectively.
Conditions
----------
Conditional declarations allow enabling or disabling certain highlighting
rules at runtime. For example, Java highlighter has a very big list of
keywords matching Java standard classes. Finding a match in this list can take
much time. For that reason, corresponding keyword group is declared with
"ifdef" attribute :
<keywords name="builtin" inherits="identifier" innerClass="builtin"
case="yes" ifdef="java.builtins">
<keyword match="AbstractAction" />
<keyword match="AbstractBorder" />
<keyword match="AbstractButton" />
...
...
<keyword match="_Remote_Stub" />
<keyword match="_ServantActivatorStub" />
<keyword match="_ServantLocatorStub" />
</keywords>
This keyword group will be only enabled when "java.builtins" is passed as an
element of "defines" option:
$options = array(
'defines' => array(
'java.builtins',
),
'numbers' => HL_NUMBERS_TABLE,
);
$highlighter = Text_Highlighter::factory('java', $options);
"ifndef" attribute has reverse meaning.
Currently, "ifdef" and "ifndef" attributes are only supported for <keywords>
tag.
Class generation
================
Creating XML description of highlighting rules is the most complicated part of
the process. To generate the class, you need just few lines of code:
<?php
require_once 'Text/Highlighter/Generator.php';
$generator = new Text_Highlighter_Generator('php.xml');
$generator->generate();
$generator->saveCode('PHP.php');
?>
Command-line class generation tool
==================================
Example from previous section looks pretty simple, but it does not handle any
errors which may occur during parsing of XML source. The package provides a
command-line script to make generation of classes even more simple, and takes
care of possible errors. It is called generate (on Unix/Linux) or generate.bat
(on Windows). This script is able to process multiple files in one run, and
also to process XML from standard input and write generated code to standard
output.
Usage:
generate options
Options:
-x filename, --xml=filename
source XML file. Multiple input files can be specified, in which
case each -x option must be followed by -p unless -d is specified
Defaults to stdin
-p filename, --php=filename
destination PHP file. Defaults to stdout. If specied multiple times,
each -p must follow -x
-d dirname, --dir=dirname
Default destination directory. File names will be taken from XML input
("lang" attribute of <highlight> tag)
-h, --help
This help
Examples
Read from php.xml, write to PHP.php
generate -x php.xml -p PHP.php
Read from php.xml, write to standard output
generate -x php.xml
Read from php.xml, write to PHP.php, read from xml.xml, write to XML.php
generate -x php.xml -p PHP.php -x xml.xml -p XML.php
Read from php.xml, write to /some/dir/PHP.php, read from xml.xml, write to
/some/dir/XML.php (assuming that xml.xml contains <highlight lang="xml">, and
php.xml contains <highlight lang="php">)
generate -x php.xml -x xml.xml -d /some/dir/
Renderers
=========
Introduction
------------
Text_Highlighter supports renderes. Using renderers, you can get output in
different formats. Two renderers are included in the package:
- HTML renderer. Generates HTML output. A style sheet should be linked to
the document to display colored text
- Console renderer. Can be used to output highlighted text to
color-capable terminals, either directly or trough less -r
Renderers API
-------------
Renderers are subclasses of Text_Highlighter_Renderer. Renderer should
override at least two methods - acceptToken and getOutput. Overriding other
methods is optional, depending on the nature of renderer's output and details
of implementation.
string reset()
resets renderer state. This method is called every time before a new
source file is highlighted.
string preprocess(string $code)
preprocesses code. Can be used, for example, to normalize whitespace
before highlighting. Returns preprocessed string.
void acceptToken(string $group, string $content)
the core method of the renderer. Highlighter passes chunks of text to
this method in $content, and color group in $group
void finalize()
signals the renderer that no more tokens are available.
mixed getOutput()
returns generated output.
Setting renderer options
--------------------------------
Renderers accept an optional argument to their constructor - options array.
Elements of this array are renderer-specific.
HTML renderer
-------------
HTML renderer produces HTML output with optional line numbering. The renderer
itself does not provide information about actual colors of highlighted text.
Instead, <span class="hl-XXX"> is used, where XXX is replaced with color group
name (hl-var, hl-string, etc.). It is up to you to create a CSS stylesheet.
If 'use_language' option with value evaluating to true was passed, class names
will be formatted as "LANG-hl-XXX", where LANG is language name as defined in
highlighter XML source ("lang" attribute of <highlight> tag) in lower case.
There are 3 special CSS classes:
hl-main - this class applies to whole output or right table column,
depending on 'numbers' option
hl-gutter - applies to left column in table
hl-table - applies to whole table
HTML renderer accepts following options (each being optional):
* numbers - line numbering style.
0 - no numbering (default)
HL_NUMBERS_LI - use <ol></ol> for line numbering
HL_NUMBERS_TABLE - create a 2-column table, with line numbers in left
column and highlighted text in right column
* tabsize - tabulation size. Defaults to 4
Example:
require_once 'Text/Highlighter/Renderer/Html.php';
$options = array(
'numbers' => HL_NUMBERS_LI,
'tabsize' => 8,
);
$renderer = new Text_Highlighter_Renderer_HTML($options);
Console renderer
----------------
Console renderer produces output for displaying on a color-capable terminal,
either directly or through less -r, using ANSI escape sequences. By default,
this renderer only highlights most common color groups. Additional colors
can be specified using 'colors' option. This renderer also accepts 'numbers'
option - a boolean value, and 'tabsize' option.
Example :
require_once 'Text/Highlighter/Renderer/Console.php';
$colors = array(
'prepro' => "\033[35m",
'types' => "\033[32m",
);
$options = array(
'numbers' => true,
'tabsize' => 8,
'colors' => $colors,
);
$renderer = new Text_Highlighter_Renderer_Console($options);
ANSI color escape sequences have the following format:
ESC[#;#;....;#m
where ESC is character with ASCII code 27 (033 octal, 0x1B hexadecimal). # is
one of the following:
0 for normal display
1 for bold on
4 underline (mono only)
5 blink on
7 reverse video on
8 nondisplayed (invisible)
30 black foreground
31 red foreground
32 green foreground
33 yellow foreground
34 blue foreground
35 magenta foreground
36 cyan foreground
37 white foreground
40 black background
41 red background
42 green background
43 yellow background
44 blue background
45 magenta background
46 cyan background
47 white background
How to use Text_Highlighter class
=================================
Creating a highlighter object
-----------------------------
To create a highlighter for a certain language, use Text_Highlighter::factory()
static method:
require_once 'Text/Highlighter.php';
$hl = Text_Highlighter::factory('php');
Setting a renderer
------------------
Actual output is produced by a renderer.
require_once 'Text/Highlighter.php';
require_once 'Text/Highlighter/Renderer/Html.php';
$options = array(
'numbers' => HL_NUMBERS_LI,
'tabsize' => 8,
);
$renderer = new Text_Highlighter_Renderer_HTML($options);
$hl = Text_Highlighter::factory('php');
$hl->setRenderer($renderer);
Note that for BC reasons, it is possible to use highlighter without setting a
renderer. If no renderer is set, HTML renderer will be used by default. In
this case, you should pass options as second parameter to factory method. The
following example works exactly as previous one:
require_once 'Text/Highlighter.php';
$options = array(
'numbers' => HL_NUMBERS_LI,
'tabsize' => 8,
);
$hl = Text_Highlighter::factory('php', $options);
Getting output
--------------
And finally, do the highlighting and get the output:
require_once 'Text/Highlighter.php';
require_once 'Text/Highlighter/Renderer/Html.php';
$options = array(
'numbers' => HL_NUMBERS_LI,
'tabsize' => 8,
);
$renderer = new Text_Highlighter_Renderer_HTML($options);
$hl = Text_Highlighter::factory('php');
$hl->setRenderer($renderer);
$html = $hl->highlight(file_get_contents('example.php'));
# vim: set autoindent tabstop=4 shiftwidth=4 softtabstop=4 tw=78: */

View file

@ -0,0 +1,12 @@
# $Id$
Major issues to solve (but I currently have no idea how) :
- speedup highlighting process
- switching between highlighters depending on context, for example :
PHP code -> HTML -> (JavaScript|CSS)
# vim: set autoindent tabstop=4 shiftwidth=4 softtabstop=4 tw=78: */

View file

@ -0,0 +1,398 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Highlighter base class
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Text
* @package Text_Highlighter
* @author Andrey Demenev <demenev@gmail.com>
* @copyright 2004-2006 Andrey Demenev
* @license http://www.php.net/license/3_0.txt PHP License
* @version CVS: $Id$
* @link http://pear.php.net/package/Text_Highlighter
*/
// require_once 'PEAR.php';
// {{{ BC constants
// BC trick : define constants related to default
// renderer if needed
if (!defined('HL_NUMBERS_LI')) {
/**#@+
* Constant for use with $options['numbers']
* @see Text_Highlighter_Renderer_Html::_init()
*/
/**
* use numbered list
*/
define ('HL_NUMBERS_LI' , 1);
/**
* Use 2-column table with line numbers in left column and code in right column.
* Forces $options['tag'] = HL_TAG_PRE
*/
define ('HL_NUMBERS_TABLE' , 2);
/**#@-*/
}
// }}}
// {{{ constants
/**
* for our purpose, it is infinity
*/
define ('HL_INFINITY', 1000000000);
// }}}
/**
* Text highlighter base class
*
* @author Andrey Demenev <demenev@gmail.com>
* @copyright 2004-2006 Andrey Demenev
* @license http://www.php.net/license/3_0.txt PHP License
* @version Release: @package_version@
* @link http://pear.php.net/package/Text_Highlighter
*/
// {{{ Text_Highlighter
/**
* Text highlighter base class
*
* This class implements all functions necessary for highlighting,
* but it does not contain highlighting rules. Actual highlighting is
* done using a descendent of this class.
*
* One is not supposed to manually create descendent classes.
* Instead, describe highlighting rules in XML format and
* use {@link Text_Highlighter_Generator} to create descendent class.
* Alternatively, an instance of a descendent class can be created
* directly.
*
* Use {@link Text_Highlighter::factory()} to create an
* object for particular language highlighter
*
* Usage example
* <code>
*require_once 'Text/Highlighter.php';
*$hlSQL = Text_Highlighter::factory('SQL',array('numbers'=>true));
*echo $hlSQL->highlight('SELECT * FROM table a WHERE id = 12');
* </code>
*
* @author Andrey Demenev <demenev@gmail.com>
* @package Text_Highlighter
* @access public
*/
class Text_Highlighter
{
// {{{ members
/**
* Syntax highlighting rules.
* Auto-generated classes set this var
*
* @access protected
* @see _init
* @var array
*/
var $_syntax;
/**
* Renderer object.
*
* @access private
* @var array
*/
var $_renderer;
/**
* Options. Keeped for BC
*
* @access protected
* @var array
*/
var $_options = array();
/**
* Conditionds
*
* @access protected
* @var array
*/
var $_conditions = array();
/**
* Disabled keywords
*
* @access protected
* @var array
*/
var $_disabled = array();
/**
* Language
*
* @access protected
* @var string
*/
var $_language = '';
// }}}
// {{{ _checkDefines
/**
* Called by subclssses' constructors to enable/disable
* optional highlighter rules
*
* @param array $defines Conditional defines
*
* @access protected
*/
function _checkDefines()
{
if (isset($this->_options['defines'])) {
$defines = $this->_options['defines'];
} else {
$defines = array();
}
foreach ($this->_conditions as $name => $actions) {
foreach($actions as $action) {
$present = in_array($name, $defines);
if (!$action[1]) {
$present = !$present;
}
if ($present) {
unset($this->_disabled[$action[0]]);
} else {
$this->_disabled[$action[0]] = true;
}
}
}
}
// }}}
// {{{ factory
/**
* Create a new Highlighter object for specified language
*
* @param string $lang language, for example "SQL"
* @param array $options Rendering options. This
* parameter is only keeped for BC reasons, use
* {@link Text_Highlighter::setRenderer()} instead
*
* @return mixed a newly created Highlighter object, or
* a PEAR error object on error
*
* @static
* @access public
*/
function &factory($lang, $options = array())
{
$lang = strtoupper($lang);
@include_once 'Text/Highlighter/' . $lang . '.php';
$classname = 'Text_Highlighter_' . $lang;
if (!class_exists($classname)) {
return PEAR::raiseError('Highlighter for ' . $lang . ' not found');
}
$obj = new $classname($options);
return $obj;
}
// }}}
// {{{ setRenderer
/**
* Set renderer object
*
* @param object $renderer Text_Highlighter_Renderer
*
* @access public
*/
function setRenderer(&$renderer)
{
$this->_renderer = $renderer;
}
// }}}
/**
* Helper function to find matching brackets
*
* @access private
*/
function _matchingBrackets($str)
{
return strtr($str, '()<>[]{}', ')(><][}{');
}
function _getToken()
{
if (!empty($this->_tokenStack)) {
return array_pop($this->_tokenStack);
}
if ($this->_pos >= $this->_len) {
return NULL;
}
if ($this->_state != -1 && preg_match($this->_endpattern, $this->_str, $m, PREG_OFFSET_CAPTURE, $this->_pos)) {
$endpos = $m[0][1];
$endmatch = $m[0][0];
} else {
$endpos = -1;
}
preg_match ($this->_regs[$this->_state], $this->_str, $m, PREG_OFFSET_CAPTURE, $this->_pos);
$n = 1;
foreach ($this->_counts[$this->_state] as $i=>$count) {
if (!isset($m[$n])) {
break;
}
if ($m[$n][1]>-1 && ($endpos == -1 || $m[$n][1] < $endpos)) {
if ($this->_states[$this->_state][$i] != -1) {
$this->_tokenStack[] = array($this->_delim[$this->_state][$i], $m[$n][0]);
} else {
$inner = $this->_inner[$this->_state][$i];
if (isset($this->_parts[$this->_state][$i])) {
$parts = array();
$partpos = $m[$n][1];
for ($j=1; $j<=$count; $j++) {
if ($m[$j+$n][1] < 0) {
continue;
}
if (isset($this->_parts[$this->_state][$i][$j])) {
if ($m[$j+$n][1] > $partpos) {
array_unshift($parts, array($inner, substr($this->_str, $partpos, $m[$j+$n][1]-$partpos)));
}
array_unshift($parts, array($this->_parts[$this->_state][$i][$j], $m[$j+$n][0]));
}
$partpos = $m[$j+$n][1] + strlen($m[$j+$n][0]);
}
if ($partpos < $m[$n][1] + strlen($m[$n][0])) {
array_unshift($parts, array($inner, substr($this->_str, $partpos, $m[$n][1] - $partpos + strlen($m[$n][0]))));
}
$this->_tokenStack = array_merge($this->_tokenStack, $parts);
} else {
foreach ($this->_keywords[$this->_state][$i] as $g => $re) {
if (isset($this->_disabled[$g])) {
continue;
}
if (preg_match($re, $m[$n][0])) {
$inner = $this->_kwmap[$g];
break;
}
}
$this->_tokenStack[] = array($inner, $m[$n][0]);
}
}
if ($m[$n][1] > $this->_pos) {
$this->_tokenStack[] = array($this->_lastinner, substr($this->_str, $this->_pos, $m[$n][1]-$this->_pos));
}
$this->_pos = $m[$n][1] + strlen($m[$n][0]);
if ($this->_states[$this->_state][$i] != -1) {
$this->_stack[] = array($this->_state, $this->_lastdelim, $this->_lastinner, $this->_endpattern);
$this->_lastinner = $this->_inner[$this->_state][$i];
$this->_lastdelim = $this->_delim[$this->_state][$i];
$l = $this->_state;
$this->_state = $this->_states[$this->_state][$i];
$this->_endpattern = $this->_end[$this->_state];
if ($this->_subst[$l][$i]) {
for ($k=0; $k<=$this->_counts[$l][$i]; $k++) {
if (!isset($m[$i+$k])) {
break;
}
$quoted = preg_quote($m[$n+$k][0], '/');
$this->_endpattern = str_replace('%'.$k.'%', $quoted, $this->_endpattern);
$this->_endpattern = str_replace('%b'.$k.'%', $this->_matchingBrackets($quoted), $this->_endpattern);
}
}
}
return array_pop($this->_tokenStack);
}
$n += $count + 1;
}
if ($endpos > -1) {
$this->_tokenStack[] = array($this->_lastdelim, $endmatch);
if ($endpos > $this->_pos) {
$this->_tokenStack[] = array($this->_lastinner, substr($this->_str, $this->_pos, $endpos-$this->_pos));
}
list($this->_state, $this->_lastdelim, $this->_lastinner, $this->_endpattern) = array_pop($this->_stack);
$this->_pos = $endpos + strlen($endmatch);
return array_pop($this->_tokenStack);
}
$p = $this->_pos;
$this->_pos = HL_INFINITY;
return array($this->_lastinner, substr($this->_str, $p));
}
// {{{ highlight
/**
* Highlights code
*
* @param string $str Code to highlight
* @access public
* @return string Highlighted text
*
*/
function highlight($str)
{
if (!($this->_renderer)) {
include_once('Text/Highlighter/Renderer/Html.php');
$this->_renderer = new Text_Highlighter_Renderer_Html($this->_options);
}
$this->_state = -1;
$this->_pos = 0;
$this->_stack = array();
$this->_tokenStack = array();
$this->_lastinner = $this->_defClass;
$this->_lastdelim = $this->_defClass;
$this->_endpattern = '';
$this->_renderer->reset();
$this->_renderer->setCurrentLanguage($this->_language);
$this->_str = $this->_renderer->preprocess($str);
$this->_len = strlen($this->_str);
while ($token = $this->_getToken()) {
$this->_renderer->acceptToken($token[0], $token[1]);
}
$this->_renderer->finalize();
return $this->_renderer->getOutput();
}
// }}}
}
// }}}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>

View file

@ -0,0 +1,519 @@
<?php
/**
* Auto-generated class. ABAP syntax highlighting
*
* PHP version 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @copyright 2004-2006 Andrey Demenev
* @license http://www.php.net/license/3_0.txt PHP License
* @link http://pear.php.net/package/Text_Highlighter
* @category Text
* @package Text_Highlighter
* @version generated from: : abap.xml,v 1.1 2007/06/03 02:35:28 ssttoo Exp
* @author Stoyan Stefanov <ssttoo@gmail.com>
*
*/
/**
* @ignore
*/
require_once 'Text/Highlighter.php';
/**
* Auto-generated class. ABAP syntax highlighting
*
* @author Stoyan Stefanov <ssttoo@gmail.com>
* @category Text
* @package Text_Highlighter
* @copyright 2004-2006 Andrey Demenev
* @license http://www.php.net/license/3_0.txt PHP License
* @version Release: @package_version@
* @link http://pear.php.net/package/Text_Highlighter
*/
class Text_Highlighter_ABAP extends Text_Highlighter
{
var $_language = 'abap';
/**
* PHP4 Compatible Constructor
*
* @param array $options
* @access public
*/
function Text_Highlighter_ABAP($options=array())
{
$this->__construct($options);
}
/**
* Constructor
*
* @param array $options
* @access public
*/
function __construct($options=array())
{
$this->_options = $options;
$this->_regs = array (
-1 => '/((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)^\\*|")|((?i)\')|((?i)[a-z_\\-]\\w*)/',
0 => '/((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)^\\*|")|((?i)\')|((?i)0[xX][\\da-f]+)|((?i)\\d\\d*|\\b0\\b)|((?i)0[0-7]+)|((?i)(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?i)[a-z_\\-]\\w*)/',
1 => '/((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)^\\*|")|((?i)\')|((?i)0[xX][\\da-f]+)|((?i)\\d\\d*|\\b0\\b)|((?i)0[0-7]+)|((?i)(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?i)[a-z_\\-]\\w*)/',
2 => '/((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)^\\*|")|((?i)\')|((?i)0[xX][\\da-f]+)|((?i)\\d\\d*|\\b0\\b)|((?i)0[0-7]+)|((?i)(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?i)[a-z_\\-]\\w*)/',
3 => '//',
4 => '//',
);
$this->_counts = array (
-1 =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
),
0 =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 2,
9 => 0,
),
1 =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 2,
9 => 0,
),
2 =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 2,
9 => 0,
),
3 =>
array (
),
4 =>
array (
),
);
$this->_delim = array (
-1 =>
array (
0 => 'brackets',
1 => 'brackets',
2 => 'brackets',
3 => 'comment',
4 => 'quotes',
5 => '',
),
0 =>
array (
0 => 'brackets',
1 => 'brackets',
2 => 'brackets',
3 => 'comment',
4 => 'quotes',
5 => '',
6 => '',
7 => '',
8 => '',
9 => '',
),
1 =>
array (
0 => 'brackets',
1 => 'brackets',
2 => 'brackets',
3 => 'comment',
4 => 'quotes',
5 => '',
6 => '',
7 => '',
8 => '',
9 => '',
),
2 =>
array (
0 => 'brackets',
1 => 'brackets',
2 => 'brackets',
3 => 'comment',
4 => 'quotes',
5 => '',
6 => '',
7 => '',
8 => '',
9 => '',
),
3 =>
array (
),
4 =>
array (
),
);
$this->_inner = array (
-1 =>
array (
0 => 'code',
1 => 'code',
2 => 'code',
3 => 'comment',
4 => 'string',
5 => 'identifier',
),
0 =>
array (
0 => 'code',
1 => 'code',
2 => 'code',
3 => 'comment',
4 => 'string',
5 => 'number',
6 => 'number',
7 => 'number',
8 => 'number',
9 => 'identifier',
),
1 =>
array (
0 => 'code',
1 => 'code',
2 => 'code',
3 => 'comment',
4 => 'string',
5 => 'number',
6 => 'number',
7 => 'number',
8 => 'number',
9 => 'identifier',
),
2 =>
array (
0 => 'code',
1 => 'code',
2 => 'code',
3 => 'comment',
4 => 'string',
5 => 'number',
6 => 'number',
7 => 'number',
8 => 'number',
9 => 'identifier',
),
3 =>
array (
),
4 =>
array (
),
);
$this->_end = array (
0 => '/(?i)\\}/',
1 => '/(?i)\\)/',
2 => '/(?i)\\]/',
3 => '/(?mi)$/',
4 => '/(?i)\'/',
);
$this->_states = array (
-1 =>
array (
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => -1,
),
0 =>
array (
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => -1,
6 => -1,
7 => -1,
8 => -1,
9 => -1,
),
1 =>
array (
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => -1,
6 => -1,
7 => -1,
8 => -1,
9 => -1,
),
2 =>
array (
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => -1,
6 => -1,
7 => -1,
8 => -1,
9 => -1,
),
3 =>
array (
),
4 =>
array (
),
);
$this->_keywords = array (
-1 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 => -1,
4 => -1,
5 =>
array (
'sy' => '/^((?i)screen-name|screen-group1|screen-group2|screen-group3|screen-group4|screen-required|screen-input|screen-output|screen-intensified|screen-invisible|screen-length|screen-active|sy-index|sy-pagno|sy-tabix|sy-tfill|sy-tlopc|sy-tmaxl|sy-toccu|sy-ttabc|sy-tstis|sy-ttabi|sy-dbcnt|sy-fdpos|sy-colno|sy-linct|sy-linno|sy-linsz|sy-pagct|sy-macol|sy-marow|sy-tleng|sy-sfoff|sy-willi|sy-lilli|sy-subrc|sy-fleng|sy-cucol|sy-curow|sy-lsind|sy-listi|sy-stepl|sy-tpagi|sy-winx1|sy-winy1|sy-winx2|sy-winy2|sy-winco|sy-winro|sy-windi|sy-srows|sy-scols|sy-loopc|sy-folen|sy-fodec|sy-tzone|sy-dayst|sy-ftype|sy-appli|sy-fdayw|sy-ccurs|sy-ccurt|sy-debug|sy-ctype|sy-input|sy-langu|sy-modno|sy-batch|sy-binpt|sy-calld|sy-dynnr|sy-dyngr|sy-newpa|sy-pri40|sy-rstrt|sy-wtitl|sy-cpage|sy-dbnam|sy-mandt|sy-prefx|sy-fmkey|sy-pexpi|sy-prini|sy-primm|sy-prrel|sy-playo|sy-prbig|sy-playp|sy-prnew|sy-prlog|sy-pdest|sy-plist|sy-pauth|sy-prdsn|sy-pnwpa|sy-callr|sy-repi2|sy-rtitl|sy-prrec|sy-prtxt|sy-prabt|sy-lpass|sy-nrpag|sy-paart|sy-prcop|sy-batzs|sy-bspld|sy-brep4|sy-batzo|sy-batzd|sy-batzw|sy-batzm|sy-ctabl|sy-dbsys|sy-dcsys|sy-macdb|sy-sysid|sy-opsys|sy-pfkey|sy-saprl|sy-tcode|sy-ucomm|sy-cfwae|sy-chwae|sy-spono|sy-sponr|sy-waers|sy-cdate|sy-datum|sy-slset|sy-subty|sy-subcs|sy-group|sy-ffile|sy-uzeit|sy-dsnam|sy-repid|sy-tabid|sy-tfdsn|sy-uname|sy-lstat|sy-abcde|sy-marky|sy-sfnam|sy-tname|sy-msgli|sy-title|sy-entry|sy-lisel|sy-uline|sy-xcode|sy-cprog|sy-xprog|sy-xform|sy-ldbpg|sy-tvar0|sy-tvar1|sy-tvar2|sy-tvar3|sy-tvar4|sy-tvar5|sy-tvar6|sy-tvar7|sy-tvar8|sy-tvar9|sy-msgid|sy-msgty|sy-msgno|sy-msgv1|sy-msgv2|sy-msgv3|sy-msgv4|sy-oncom|sy-vline|sy-winsl|sy-staco|sy-staro|sy-datar|sy-host|sy-locdb|sy-locop|sy-datlo|sy-timlo|sy-zonlo|syst-index|syst-pagno|syst-tabix|syst-tfill|syst-tlopc|syst-tmaxl|syst-toccu|syst-ttabc|syst-tstis|syst-ttabi|syst-dbcnt|syst-fdpos|syst-colno|syst-linct|syst-linno|syst-linsz|syst-pagct|syst-macol|syst-marow|syst-tleng|syst-sfoff|syst-willi|syst-lilli|syst-subrc|syst-fleng|syst-cucol|syst-curow|syst-lsind|syst-listi|syst-stepl|syst-tpagi|syst-winx1|syst-winy1|syst-winx2|syst-winy2|syst-winco|syst-winro|syst-windi|syst-srows|syst-scols|syst-loopc|syst-folen|syst-fodec|syst-tzone|syst-dayst|syst-ftype|syst-appli|syst-fdayw|syst-ccurs|syst-ccurt|syst-debug|syst-ctype|syst-input|syst-langu|syst-modno|syst-batch|syst-binpt|syst-calld|syst-dynnr|syst-dyngr|syst-newpa|syst-pri40|syst-rstrt|syst-wtitl|syst-cpage|syst-dbnam|syst-mandt|syst-prefx|syst-fmkey|syst-pexpi|syst-prini|syst-primm|syst-prrel|syst-playo|syst-prbig|syst-playp|syst-prnew|syst-prlog|syst-pdest|syst-plist|syst-pauth|syst-prdsn|syst-pnwpa|syst-callr|syst-repi2|syst-rtitl|syst-prrec|syst-prtxt|syst-prabt|syst-lpass|syst-nrpag|syst-paart|syst-prcop|syst-batzs|syst-bspld|syst-brep4|syst-batzo|syst-batzd|syst-batzw|syst-batzm|syst-ctabl|syst-dbsys|syst-dcsys|syst-macdb|syst-sysid|syst-opsys|syst-pfkey|syst-saprl|syst-tcode|syst-ucomm|syst-cfwae|syst-chwae|syst-spono|syst-sponr|syst-waers|syst-cdate|syst-datum|syst-slset|syst-subty|syst-subcs|syst-group|syst-ffile|syst-uzeit|syst-dsnam|syst-repid|syst-tabid|syst-tfdsn|syst-uname|syst-lstat|syst-abcde|syst-marky|syst-sfnam|syst-tname|syst-msgli|syst-title|syst-entry|syst-lisel|syst-uline|syst-xcode|syst-cprog|syst-xprog|syst-xform|syst-ldbpg|syst-tvar0|syst-tvar1|syst-tvar2|syst-tvar3|syst-tvar4|syst-tvar5|syst-tvar6|syst-tvar7|syst-tvar8|syst-tvar9|syst-msgid|syst-msgty|syst-msgno|syst-msgv1|syst-msgv2|syst-msgv3|syst-msgv4|syst-oncom|syst-vline|syst-winsl|syst-staco|syst-staro|syst-datar|syst-host|syst-locdb|syst-locop|syst-datlo|syst-timlo|syst-zonlo)$/',
'reserved' => '/^((?i)abs|acos|add|add-corresponding|adjacent|after|aliases|all|analyzer|and|any|append|as|ascending|asin|assign|assigned|assigning|at|atan|authority-check|avg|back|before|begin|binary|bit|bit-and|bit-not|bit-or|bit-xor|blank|block|break-point|buffer|by|c|call|case|catch|ceil|centered|chain|change|changing|check|checkbox|class|class-data|class-events|class-methods|class-pool|clear|client|close|cnt|code|collect|color|comment|commit|communication|compute|concatenate|condense|constants|context|contexts|continue|control|controls|convert|copy|corresponding|cos|cosh|count|country|create|currency|cursor|customer-function|data|database|dataset|delete|decimals|default|define|demand|descending|describe|dialog|distinct|div|divide|divide-corresponding|do|duplicates|dynpro|edit|editor-call|else|elseif|end|end-of-definition|end-of-page|end-of-selection|endat|endcase|endcatch|endchain|endclass|enddo|endexec|endform|endfunction|endif|endinterface|endloop|endmethod|endmodule|endon|endprovide|endselect|endwhile|entries|events|exec|exit|exit-command|exp|exponent|export|exporting|exceptions|extended|extract|fetch|field|field-groups|field-symbols|fields|floor|for|form|format|frac|frame|free|from|function|function-pool|generate|get|group|hashed|header|help-id|help-request|hide|hotspot|icon|id|if|import|importing|include|index|infotypes|initialization|inner|input|insert|intensified|interface|interface-pool|interfaces|into|inverse|join|key|language|last|leave|left|left-justified|like|line|line-count|line-selection|line-size|lines|list-processing|load|load-of-program|local|locale|log|log10|loop|m|margin|mask|matchcode|max|memory|message|message-id|messages|method|methods|min|mod|mode|modif|modify|module|move|move-corresponding|multiply|multiply-corresponding|new|new-line|new-page|next|no|no-gap|no-gaps|no-heading|no-scrolling|no-sign|no-title|no-zero|nodes|non-unique|o|object|obligatory|occurs|of|off|on|open|or|order|others|outer|output|overlay|pack|page|parameter|parameters|perform|pf-status|position|print|print-control|private|process|program|property|protected|provide|public|put|radiobutton|raise|raising|range|ranges|read|receive|refresh|reject|replace|report|requested|reserve|reset|right-justified|rollback|round|rows|rtti|run|scan|screen|search|separated|scroll|scroll-boundary|select|select-options|selection-screen|selection-table|set|shared|shift|sign|sin|single|sinh|size|skip|sort|sorted|split|sql|sqrt|stamp|standard|start-of-selection|statics|stop|string|strlen|structure|submit|subtract|subtract-corresponding|sum|supply|suppress|symbol|syntax-check|syntax-trace|system-call|system-exceptions|table|table_line|tables|tan|tanh|text|textpool|time|times|title|titlebar|to|top-of-page|transaction|transfer|translate|transporting|trunc|type|type-pool|type-pools|types|uline|under|unique|unit|unpack|up|update|user-command|using|value|value-request|values|vary|when|where|while|window|with|with-title|work|write|x|xstring|z|zone)$/',
'constants' => '/^((?i)initial|null|space|col_background|col_heading|col_normal|col_total|col_key|col_positive|col_negative|col_group)$/',
),
),
0 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 => -1,
4 => -1,
5 =>
array (
),
6 =>
array (
),
7 =>
array (
),
8 =>
array (
),
9 =>
array (
'sy' => '/^((?i)screen-name|screen-group1|screen-group2|screen-group3|screen-group4|screen-required|screen-input|screen-output|screen-intensified|screen-invisible|screen-length|screen-active|sy-index|sy-pagno|sy-tabix|sy-tfill|sy-tlopc|sy-tmaxl|sy-toccu|sy-ttabc|sy-tstis|sy-ttabi|sy-dbcnt|sy-fdpos|sy-colno|sy-linct|sy-linno|sy-linsz|sy-pagct|sy-macol|sy-marow|sy-tleng|sy-sfoff|sy-willi|sy-lilli|sy-subrc|sy-fleng|sy-cucol|sy-curow|sy-lsind|sy-listi|sy-stepl|sy-tpagi|sy-winx1|sy-winy1|sy-winx2|sy-winy2|sy-winco|sy-winro|sy-windi|sy-srows|sy-scols|sy-loopc|sy-folen|sy-fodec|sy-tzone|sy-dayst|sy-ftype|sy-appli|sy-fdayw|sy-ccurs|sy-ccurt|sy-debug|sy-ctype|sy-input|sy-langu|sy-modno|sy-batch|sy-binpt|sy-calld|sy-dynnr|sy-dyngr|sy-newpa|sy-pri40|sy-rstrt|sy-wtitl|sy-cpage|sy-dbnam|sy-mandt|sy-prefx|sy-fmkey|sy-pexpi|sy-prini|sy-primm|sy-prrel|sy-playo|sy-prbig|sy-playp|sy-prnew|sy-prlog|sy-pdest|sy-plist|sy-pauth|sy-prdsn|sy-pnwpa|sy-callr|sy-repi2|sy-rtitl|sy-prrec|sy-prtxt|sy-prabt|sy-lpass|sy-nrpag|sy-paart|sy-prcop|sy-batzs|sy-bspld|sy-brep4|sy-batzo|sy-batzd|sy-batzw|sy-batzm|sy-ctabl|sy-dbsys|sy-dcsys|sy-macdb|sy-sysid|sy-opsys|sy-pfkey|sy-saprl|sy-tcode|sy-ucomm|sy-cfwae|sy-chwae|sy-spono|sy-sponr|sy-waers|sy-cdate|sy-datum|sy-slset|sy-subty|sy-subcs|sy-group|sy-ffile|sy-uzeit|sy-dsnam|sy-repid|sy-tabid|sy-tfdsn|sy-uname|sy-lstat|sy-abcde|sy-marky|sy-sfnam|sy-tname|sy-msgli|sy-title|sy-entry|sy-lisel|sy-uline|sy-xcode|sy-cprog|sy-xprog|sy-xform|sy-ldbpg|sy-tvar0|sy-tvar1|sy-tvar2|sy-tvar3|sy-tvar4|sy-tvar5|sy-tvar6|sy-tvar7|sy-tvar8|sy-tvar9|sy-msgid|sy-msgty|sy-msgno|sy-msgv1|sy-msgv2|sy-msgv3|sy-msgv4|sy-oncom|sy-vline|sy-winsl|sy-staco|sy-staro|sy-datar|sy-host|sy-locdb|sy-locop|sy-datlo|sy-timlo|sy-zonlo|syst-index|syst-pagno|syst-tabix|syst-tfill|syst-tlopc|syst-tmaxl|syst-toccu|syst-ttabc|syst-tstis|syst-ttabi|syst-dbcnt|syst-fdpos|syst-colno|syst-linct|syst-linno|syst-linsz|syst-pagct|syst-macol|syst-marow|syst-tleng|syst-sfoff|syst-willi|syst-lilli|syst-subrc|syst-fleng|syst-cucol|syst-curow|syst-lsind|syst-listi|syst-stepl|syst-tpagi|syst-winx1|syst-winy1|syst-winx2|syst-winy2|syst-winco|syst-winro|syst-windi|syst-srows|syst-scols|syst-loopc|syst-folen|syst-fodec|syst-tzone|syst-dayst|syst-ftype|syst-appli|syst-fdayw|syst-ccurs|syst-ccurt|syst-debug|syst-ctype|syst-input|syst-langu|syst-modno|syst-batch|syst-binpt|syst-calld|syst-dynnr|syst-dyngr|syst-newpa|syst-pri40|syst-rstrt|syst-wtitl|syst-cpage|syst-dbnam|syst-mandt|syst-prefx|syst-fmkey|syst-pexpi|syst-prini|syst-primm|syst-prrel|syst-playo|syst-prbig|syst-playp|syst-prnew|syst-prlog|syst-pdest|syst-plist|syst-pauth|syst-prdsn|syst-pnwpa|syst-callr|syst-repi2|syst-rtitl|syst-prrec|syst-prtxt|syst-prabt|syst-lpass|syst-nrpag|syst-paart|syst-prcop|syst-batzs|syst-bspld|syst-brep4|syst-batzo|syst-batzd|syst-batzw|syst-batzm|syst-ctabl|syst-dbsys|syst-dcsys|syst-macdb|syst-sysid|syst-opsys|syst-pfkey|syst-saprl|syst-tcode|syst-ucomm|syst-cfwae|syst-chwae|syst-spono|syst-sponr|syst-waers|syst-cdate|syst-datum|syst-slset|syst-subty|syst-subcs|syst-group|syst-ffile|syst-uzeit|syst-dsnam|syst-repid|syst-tabid|syst-tfdsn|syst-uname|syst-lstat|syst-abcde|syst-marky|syst-sfnam|syst-tname|syst-msgli|syst-title|syst-entry|syst-lisel|syst-uline|syst-xcode|syst-cprog|syst-xprog|syst-xform|syst-ldbpg|syst-tvar0|syst-tvar1|syst-tvar2|syst-tvar3|syst-tvar4|syst-tvar5|syst-tvar6|syst-tvar7|syst-tvar8|syst-tvar9|syst-msgid|syst-msgty|syst-msgno|syst-msgv1|syst-msgv2|syst-msgv3|syst-msgv4|syst-oncom|syst-vline|syst-winsl|syst-staco|syst-staro|syst-datar|syst-host|syst-locdb|syst-locop|syst-datlo|syst-timlo|syst-zonlo)$/',
'reserved' => '/^((?i)abs|acos|add|add-corresponding|adjacent|after|aliases|all|analyzer|and|any|append|as|ascending|asin|assign|assigned|assigning|at|atan|authority-check|avg|back|before|begin|binary|bit|bit-and|bit-not|bit-or|bit-xor|blank|block|break-point|buffer|by|c|call|case|catch|ceil|centered|chain|change|changing|check|checkbox|class|class-data|class-events|class-methods|class-pool|clear|client|close|cnt|code|collect|color|comment|commit|communication|compute|concatenate|condense|constants|context|contexts|continue|control|controls|convert|copy|corresponding|cos|cosh|count|country|create|currency|cursor|customer-function|data|database|dataset|delete|decimals|default|define|demand|descending|describe|dialog|distinct|div|divide|divide-corresponding|do|duplicates|dynpro|edit|editor-call|else|elseif|end|end-of-definition|end-of-page|end-of-selection|endat|endcase|endcatch|endchain|endclass|enddo|endexec|endform|endfunction|endif|endinterface|endloop|endmethod|endmodule|endon|endprovide|endselect|endwhile|entries|events|exec|exit|exit-command|exp|exponent|export|exporting|exceptions|extended|extract|fetch|field|field-groups|field-symbols|fields|floor|for|form|format|frac|frame|free|from|function|function-pool|generate|get|group|hashed|header|help-id|help-request|hide|hotspot|icon|id|if|import|importing|include|index|infotypes|initialization|inner|input|insert|intensified|interface|interface-pool|interfaces|into|inverse|join|key|language|last|leave|left|left-justified|like|line|line-count|line-selection|line-size|lines|list-processing|load|load-of-program|local|locale|log|log10|loop|m|margin|mask|matchcode|max|memory|message|message-id|messages|method|methods|min|mod|mode|modif|modify|module|move|move-corresponding|multiply|multiply-corresponding|new|new-line|new-page|next|no|no-gap|no-gaps|no-heading|no-scrolling|no-sign|no-title|no-zero|nodes|non-unique|o|object|obligatory|occurs|of|off|on|open|or|order|others|outer|output|overlay|pack|page|parameter|parameters|perform|pf-status|position|print|print-control|private|process|program|property|protected|provide|public|put|radiobutton|raise|raising|range|ranges|read|receive|refresh|reject|replace|report|requested|reserve|reset|right-justified|rollback|round|rows|rtti|run|scan|screen|search|separated|scroll|scroll-boundary|select|select-options|selection-screen|selection-table|set|shared|shift|sign|sin|single|sinh|size|skip|sort|sorted|split|sql|sqrt|stamp|standard|start-of-selection|statics|stop|string|strlen|structure|submit|subtract|subtract-corresponding|sum|supply|suppress|symbol|syntax-check|syntax-trace|system-call|system-exceptions|table|table_line|tables|tan|tanh|text|textpool|time|times|title|titlebar|to|top-of-page|transaction|transfer|translate|transporting|trunc|type|type-pool|type-pools|types|uline|under|unique|unit|unpack|up|update|user-command|using|value|value-request|values|vary|when|where|while|window|with|with-title|work|write|x|xstring|z|zone)$/',
'constants' => '/^((?i)initial|null|space|col_background|col_heading|col_normal|col_total|col_key|col_positive|col_negative|col_group)$/',
),
),
1 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 => -1,
4 => -1,
5 =>
array (
),
6 =>
array (
),
7 =>
array (
),
8 =>
array (
),
9 =>
array (
'sy' => '/^((?i)screen-name|screen-group1|screen-group2|screen-group3|screen-group4|screen-required|screen-input|screen-output|screen-intensified|screen-invisible|screen-length|screen-active|sy-index|sy-pagno|sy-tabix|sy-tfill|sy-tlopc|sy-tmaxl|sy-toccu|sy-ttabc|sy-tstis|sy-ttabi|sy-dbcnt|sy-fdpos|sy-colno|sy-linct|sy-linno|sy-linsz|sy-pagct|sy-macol|sy-marow|sy-tleng|sy-sfoff|sy-willi|sy-lilli|sy-subrc|sy-fleng|sy-cucol|sy-curow|sy-lsind|sy-listi|sy-stepl|sy-tpagi|sy-winx1|sy-winy1|sy-winx2|sy-winy2|sy-winco|sy-winro|sy-windi|sy-srows|sy-scols|sy-loopc|sy-folen|sy-fodec|sy-tzone|sy-dayst|sy-ftype|sy-appli|sy-fdayw|sy-ccurs|sy-ccurt|sy-debug|sy-ctype|sy-input|sy-langu|sy-modno|sy-batch|sy-binpt|sy-calld|sy-dynnr|sy-dyngr|sy-newpa|sy-pri40|sy-rstrt|sy-wtitl|sy-cpage|sy-dbnam|sy-mandt|sy-prefx|sy-fmkey|sy-pexpi|sy-prini|sy-primm|sy-prrel|sy-playo|sy-prbig|sy-playp|sy-prnew|sy-prlog|sy-pdest|sy-plist|sy-pauth|sy-prdsn|sy-pnwpa|sy-callr|sy-repi2|sy-rtitl|sy-prrec|sy-prtxt|sy-prabt|sy-lpass|sy-nrpag|sy-paart|sy-prcop|sy-batzs|sy-bspld|sy-brep4|sy-batzo|sy-batzd|sy-batzw|sy-batzm|sy-ctabl|sy-dbsys|sy-dcsys|sy-macdb|sy-sysid|sy-opsys|sy-pfkey|sy-saprl|sy-tcode|sy-ucomm|sy-cfwae|sy-chwae|sy-spono|sy-sponr|sy-waers|sy-cdate|sy-datum|sy-slset|sy-subty|sy-subcs|sy-group|sy-ffile|sy-uzeit|sy-dsnam|sy-repid|sy-tabid|sy-tfdsn|sy-uname|sy-lstat|sy-abcde|sy-marky|sy-sfnam|sy-tname|sy-msgli|sy-title|sy-entry|sy-lisel|sy-uline|sy-xcode|sy-cprog|sy-xprog|sy-xform|sy-ldbpg|sy-tvar0|sy-tvar1|sy-tvar2|sy-tvar3|sy-tvar4|sy-tvar5|sy-tvar6|sy-tvar7|sy-tvar8|sy-tvar9|sy-msgid|sy-msgty|sy-msgno|sy-msgv1|sy-msgv2|sy-msgv3|sy-msgv4|sy-oncom|sy-vline|sy-winsl|sy-staco|sy-staro|sy-datar|sy-host|sy-locdb|sy-locop|sy-datlo|sy-timlo|sy-zonlo|syst-index|syst-pagno|syst-tabix|syst-tfill|syst-tlopc|syst-tmaxl|syst-toccu|syst-ttabc|syst-tstis|syst-ttabi|syst-dbcnt|syst-fdpos|syst-colno|syst-linct|syst-linno|syst-linsz|syst-pagct|syst-macol|syst-marow|syst-tleng|syst-sfoff|syst-willi|syst-lilli|syst-subrc|syst-fleng|syst-cucol|syst-curow|syst-lsind|syst-listi|syst-stepl|syst-tpagi|syst-winx1|syst-winy1|syst-winx2|syst-winy2|syst-winco|syst-winro|syst-windi|syst-srows|syst-scols|syst-loopc|syst-folen|syst-fodec|syst-tzone|syst-dayst|syst-ftype|syst-appli|syst-fdayw|syst-ccurs|syst-ccurt|syst-debug|syst-ctype|syst-input|syst-langu|syst-modno|syst-batch|syst-binpt|syst-calld|syst-dynnr|syst-dyngr|syst-newpa|syst-pri40|syst-rstrt|syst-wtitl|syst-cpage|syst-dbnam|syst-mandt|syst-prefx|syst-fmkey|syst-pexpi|syst-prini|syst-primm|syst-prrel|syst-playo|syst-prbig|syst-playp|syst-prnew|syst-prlog|syst-pdest|syst-plist|syst-pauth|syst-prdsn|syst-pnwpa|syst-callr|syst-repi2|syst-rtitl|syst-prrec|syst-prtxt|syst-prabt|syst-lpass|syst-nrpag|syst-paart|syst-prcop|syst-batzs|syst-bspld|syst-brep4|syst-batzo|syst-batzd|syst-batzw|syst-batzm|syst-ctabl|syst-dbsys|syst-dcsys|syst-macdb|syst-sysid|syst-opsys|syst-pfkey|syst-saprl|syst-tcode|syst-ucomm|syst-cfwae|syst-chwae|syst-spono|syst-sponr|syst-waers|syst-cdate|syst-datum|syst-slset|syst-subty|syst-subcs|syst-group|syst-ffile|syst-uzeit|syst-dsnam|syst-repid|syst-tabid|syst-tfdsn|syst-uname|syst-lstat|syst-abcde|syst-marky|syst-sfnam|syst-tname|syst-msgli|syst-title|syst-entry|syst-lisel|syst-uline|syst-xcode|syst-cprog|syst-xprog|syst-xform|syst-ldbpg|syst-tvar0|syst-tvar1|syst-tvar2|syst-tvar3|syst-tvar4|syst-tvar5|syst-tvar6|syst-tvar7|syst-tvar8|syst-tvar9|syst-msgid|syst-msgty|syst-msgno|syst-msgv1|syst-msgv2|syst-msgv3|syst-msgv4|syst-oncom|syst-vline|syst-winsl|syst-staco|syst-staro|syst-datar|syst-host|syst-locdb|syst-locop|syst-datlo|syst-timlo|syst-zonlo)$/',
'reserved' => '/^((?i)abs|acos|add|add-corresponding|adjacent|after|aliases|all|analyzer|and|any|append|as|ascending|asin|assign|assigned|assigning|at|atan|authority-check|avg|back|before|begin|binary|bit|bit-and|bit-not|bit-or|bit-xor|blank|block|break-point|buffer|by|c|call|case|catch|ceil|centered|chain|change|changing|check|checkbox|class|class-data|class-events|class-methods|class-pool|clear|client|close|cnt|code|collect|color|comment|commit|communication|compute|concatenate|condense|constants|context|contexts|continue|control|controls|convert|copy|corresponding|cos|cosh|count|country|create|currency|cursor|customer-function|data|database|dataset|delete|decimals|default|define|demand|descending|describe|dialog|distinct|div|divide|divide-corresponding|do|duplicates|dynpro|edit|editor-call|else|elseif|end|end-of-definition|end-of-page|end-of-selection|endat|endcase|endcatch|endchain|endclass|enddo|endexec|endform|endfunction|endif|endinterface|endloop|endmethod|endmodule|endon|endprovide|endselect|endwhile|entries|events|exec|exit|exit-command|exp|exponent|export|exporting|exceptions|extended|extract|fetch|field|field-groups|field-symbols|fields|floor|for|form|format|frac|frame|free|from|function|function-pool|generate|get|group|hashed|header|help-id|help-request|hide|hotspot|icon|id|if|import|importing|include|index|infotypes|initialization|inner|input|insert|intensified|interface|interface-pool|interfaces|into|inverse|join|key|language|last|leave|left|left-justified|like|line|line-count|line-selection|line-size|lines|list-processing|load|load-of-program|local|locale|log|log10|loop|m|margin|mask|matchcode|max|memory|message|message-id|messages|method|methods|min|mod|mode|modif|modify|module|move|move-corresponding|multiply|multiply-corresponding|new|new-line|new-page|next|no|no-gap|no-gaps|no-heading|no-scrolling|no-sign|no-title|no-zero|nodes|non-unique|o|object|obligatory|occurs|of|off|on|open|or|order|others|outer|output|overlay|pack|page|parameter|parameters|perform|pf-status|position|print|print-control|private|process|program|property|protected|provide|public|put|radiobutton|raise|raising|range|ranges|read|receive|refresh|reject|replace|report|requested|reserve|reset|right-justified|rollback|round|rows|rtti|run|scan|screen|search|separated|scroll|scroll-boundary|select|select-options|selection-screen|selection-table|set|shared|shift|sign|sin|single|sinh|size|skip|sort|sorted|split|sql|sqrt|stamp|standard|start-of-selection|statics|stop|string|strlen|structure|submit|subtract|subtract-corresponding|sum|supply|suppress|symbol|syntax-check|syntax-trace|system-call|system-exceptions|table|table_line|tables|tan|tanh|text|textpool|time|times|title|titlebar|to|top-of-page|transaction|transfer|translate|transporting|trunc|type|type-pool|type-pools|types|uline|under|unique|unit|unpack|up|update|user-command|using|value|value-request|values|vary|when|where|while|window|with|with-title|work|write|x|xstring|z|zone)$/',
'constants' => '/^((?i)initial|null|space|col_background|col_heading|col_normal|col_total|col_key|col_positive|col_negative|col_group)$/',
),
),
2 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 => -1,
4 => -1,
5 =>
array (
),
6 =>
array (
),
7 =>
array (
),
8 =>
array (
),
9 =>
array (
'sy' => '/^((?i)screen-name|screen-group1|screen-group2|screen-group3|screen-group4|screen-required|screen-input|screen-output|screen-intensified|screen-invisible|screen-length|screen-active|sy-index|sy-pagno|sy-tabix|sy-tfill|sy-tlopc|sy-tmaxl|sy-toccu|sy-ttabc|sy-tstis|sy-ttabi|sy-dbcnt|sy-fdpos|sy-colno|sy-linct|sy-linno|sy-linsz|sy-pagct|sy-macol|sy-marow|sy-tleng|sy-sfoff|sy-willi|sy-lilli|sy-subrc|sy-fleng|sy-cucol|sy-curow|sy-lsind|sy-listi|sy-stepl|sy-tpagi|sy-winx1|sy-winy1|sy-winx2|sy-winy2|sy-winco|sy-winro|sy-windi|sy-srows|sy-scols|sy-loopc|sy-folen|sy-fodec|sy-tzone|sy-dayst|sy-ftype|sy-appli|sy-fdayw|sy-ccurs|sy-ccurt|sy-debug|sy-ctype|sy-input|sy-langu|sy-modno|sy-batch|sy-binpt|sy-calld|sy-dynnr|sy-dyngr|sy-newpa|sy-pri40|sy-rstrt|sy-wtitl|sy-cpage|sy-dbnam|sy-mandt|sy-prefx|sy-fmkey|sy-pexpi|sy-prini|sy-primm|sy-prrel|sy-playo|sy-prbig|sy-playp|sy-prnew|sy-prlog|sy-pdest|sy-plist|sy-pauth|sy-prdsn|sy-pnwpa|sy-callr|sy-repi2|sy-rtitl|sy-prrec|sy-prtxt|sy-prabt|sy-lpass|sy-nrpag|sy-paart|sy-prcop|sy-batzs|sy-bspld|sy-brep4|sy-batzo|sy-batzd|sy-batzw|sy-batzm|sy-ctabl|sy-dbsys|sy-dcsys|sy-macdb|sy-sysid|sy-opsys|sy-pfkey|sy-saprl|sy-tcode|sy-ucomm|sy-cfwae|sy-chwae|sy-spono|sy-sponr|sy-waers|sy-cdate|sy-datum|sy-slset|sy-subty|sy-subcs|sy-group|sy-ffile|sy-uzeit|sy-dsnam|sy-repid|sy-tabid|sy-tfdsn|sy-uname|sy-lstat|sy-abcde|sy-marky|sy-sfnam|sy-tname|sy-msgli|sy-title|sy-entry|sy-lisel|sy-uline|sy-xcode|sy-cprog|sy-xprog|sy-xform|sy-ldbpg|sy-tvar0|sy-tvar1|sy-tvar2|sy-tvar3|sy-tvar4|sy-tvar5|sy-tvar6|sy-tvar7|sy-tvar8|sy-tvar9|sy-msgid|sy-msgty|sy-msgno|sy-msgv1|sy-msgv2|sy-msgv3|sy-msgv4|sy-oncom|sy-vline|sy-winsl|sy-staco|sy-staro|sy-datar|sy-host|sy-locdb|sy-locop|sy-datlo|sy-timlo|sy-zonlo|syst-index|syst-pagno|syst-tabix|syst-tfill|syst-tlopc|syst-tmaxl|syst-toccu|syst-ttabc|syst-tstis|syst-ttabi|syst-dbcnt|syst-fdpos|syst-colno|syst-linct|syst-linno|syst-linsz|syst-pagct|syst-macol|syst-marow|syst-tleng|syst-sfoff|syst-willi|syst-lilli|syst-subrc|syst-fleng|syst-cucol|syst-curow|syst-lsind|syst-listi|syst-stepl|syst-tpagi|syst-winx1|syst-winy1|syst-winx2|syst-winy2|syst-winco|syst-winro|syst-windi|syst-srows|syst-scols|syst-loopc|syst-folen|syst-fodec|syst-tzone|syst-dayst|syst-ftype|syst-appli|syst-fdayw|syst-ccurs|syst-ccurt|syst-debug|syst-ctype|syst-input|syst-langu|syst-modno|syst-batch|syst-binpt|syst-calld|syst-dynnr|syst-dyngr|syst-newpa|syst-pri40|syst-rstrt|syst-wtitl|syst-cpage|syst-dbnam|syst-mandt|syst-prefx|syst-fmkey|syst-pexpi|syst-prini|syst-primm|syst-prrel|syst-playo|syst-prbig|syst-playp|syst-prnew|syst-prlog|syst-pdest|syst-plist|syst-pauth|syst-prdsn|syst-pnwpa|syst-callr|syst-repi2|syst-rtitl|syst-prrec|syst-prtxt|syst-prabt|syst-lpass|syst-nrpag|syst-paart|syst-prcop|syst-batzs|syst-bspld|syst-brep4|syst-batzo|syst-batzd|syst-batzw|syst-batzm|syst-ctabl|syst-dbsys|syst-dcsys|syst-macdb|syst-sysid|syst-opsys|syst-pfkey|syst-saprl|syst-tcode|syst-ucomm|syst-cfwae|syst-chwae|syst-spono|syst-sponr|syst-waers|syst-cdate|syst-datum|syst-slset|syst-subty|syst-subcs|syst-group|syst-ffile|syst-uzeit|syst-dsnam|syst-repid|syst-tabid|syst-tfdsn|syst-uname|syst-lstat|syst-abcde|syst-marky|syst-sfnam|syst-tname|syst-msgli|syst-title|syst-entry|syst-lisel|syst-uline|syst-xcode|syst-cprog|syst-xprog|syst-xform|syst-ldbpg|syst-tvar0|syst-tvar1|syst-tvar2|syst-tvar3|syst-tvar4|syst-tvar5|syst-tvar6|syst-tvar7|syst-tvar8|syst-tvar9|syst-msgid|syst-msgty|syst-msgno|syst-msgv1|syst-msgv2|syst-msgv3|syst-msgv4|syst-oncom|syst-vline|syst-winsl|syst-staco|syst-staro|syst-datar|syst-host|syst-locdb|syst-locop|syst-datlo|syst-timlo|syst-zonlo)$/',
'reserved' => '/^((?i)abs|acos|add|add-corresponding|adjacent|after|aliases|all|analyzer|and|any|append|as|ascending|asin|assign|assigned|assigning|at|atan|authority-check|avg|back|before|begin|binary|bit|bit-and|bit-not|bit-or|bit-xor|blank|block|break-point|buffer|by|c|call|case|catch|ceil|centered|chain|change|changing|check|checkbox|class|class-data|class-events|class-methods|class-pool|clear|client|close|cnt|code|collect|color|comment|commit|communication|compute|concatenate|condense|constants|context|contexts|continue|control|controls|convert|copy|corresponding|cos|cosh|count|country|create|currency|cursor|customer-function|data|database|dataset|delete|decimals|default|define|demand|descending|describe|dialog|distinct|div|divide|divide-corresponding|do|duplicates|dynpro|edit|editor-call|else|elseif|end|end-of-definition|end-of-page|end-of-selection|endat|endcase|endcatch|endchain|endclass|enddo|endexec|endform|endfunction|endif|endinterface|endloop|endmethod|endmodule|endon|endprovide|endselect|endwhile|entries|events|exec|exit|exit-command|exp|exponent|export|exporting|exceptions|extended|extract|fetch|field|field-groups|field-symbols|fields|floor|for|form|format|frac|frame|free|from|function|function-pool|generate|get|group|hashed|header|help-id|help-request|hide|hotspot|icon|id|if|import|importing|include|index|infotypes|initialization|inner|input|insert|intensified|interface|interface-pool|interfaces|into|inverse|join|key|language|last|leave|left|left-justified|like|line|line-count|line-selection|line-size|lines|list-processing|load|load-of-program|local|locale|log|log10|loop|m|margin|mask|matchcode|max|memory|message|message-id|messages|method|methods|min|mod|mode|modif|modify|module|move|move-corresponding|multiply|multiply-corresponding|new|new-line|new-page|next|no|no-gap|no-gaps|no-heading|no-scrolling|no-sign|no-title|no-zero|nodes|non-unique|o|object|obligatory|occurs|of|off|on|open|or|order|others|outer|output|overlay|pack|page|parameter|parameters|perform|pf-status|position|print|print-control|private|process|program|property|protected|provide|public|put|radiobutton|raise|raising|range|ranges|read|receive|refresh|reject|replace|report|requested|reserve|reset|right-justified|rollback|round|rows|rtti|run|scan|screen|search|separated|scroll|scroll-boundary|select|select-options|selection-screen|selection-table|set|shared|shift|sign|sin|single|sinh|size|skip|sort|sorted|split|sql|sqrt|stamp|standard|start-of-selection|statics|stop|string|strlen|structure|submit|subtract|subtract-corresponding|sum|supply|suppress|symbol|syntax-check|syntax-trace|system-call|system-exceptions|table|table_line|tables|tan|tanh|text|textpool|time|times|title|titlebar|to|top-of-page|transaction|transfer|translate|transporting|trunc|type|type-pool|type-pools|types|uline|under|unique|unit|unpack|up|update|user-command|using|value|value-request|values|vary|when|where|while|window|with|with-title|work|write|x|xstring|z|zone)$/',
'constants' => '/^((?i)initial|null|space|col_background|col_heading|col_normal|col_total|col_key|col_positive|col_negative|col_group)$/',
),
),
3 =>
array (
),
4 =>
array (
),
);
$this->_parts = array (
0 =>
array (
0 => NULL,
1 => NULL,
2 => NULL,
3 => NULL,
4 => NULL,
5 => NULL,
6 => NULL,
7 => NULL,
8 => NULL,
9 => NULL,
),
1 =>
array (
0 => NULL,
1 => NULL,
2 => NULL,
3 => NULL,
4 => NULL,
5 => NULL,
6 => NULL,
7 => NULL,
8 => NULL,
9 => NULL,
),
2 =>
array (
0 => NULL,
1 => NULL,
2 => NULL,
3 => NULL,
4 => NULL,
5 => NULL,
6 => NULL,
7 => NULL,
8 => NULL,
9 => NULL,
),
3 =>
array (
),
4 =>
array (
),
);
$this->_subst = array (
-1 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
),
0 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
9 => false,
),
1 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
9 => false,
),
2 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
9 => false,
),
3 =>
array (
),
4 =>
array (
),
);
$this->_conditions = array (
);
$this->_kwmap = array (
'sy' => 'reserved',
'reserved' => 'reserved',
'constants' => 'reserved',
);
$this->_defClass = 'code';
$this->_checkDefines();
}
}

View file

@ -0,0 +1,894 @@
<?php
/**
* Auto-generated class. AVRC syntax highlighting
*
*
* C/C++ highlighter specific to Atmel AVR microcontrollers
*
*
* PHP version 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @copyright 2004-2006 Andrey Demenev
* @license http://www.php.net/license/3_0.txt PHP License
* @link http://pear.php.net/package/Text_Highlighter
* @category Text
* @package Text_Highlighter
* @version generated from: avrc.xml
* @author Andrey Demenev <demenev@gmail.com>
*
*/
/**
* @ignore
*/
require_once 'Text/Highlighter.php';
/**
* Auto-generated class. AVRC syntax highlighting
*
* @author Andrey Demenev <demenev@gmail.com>
* @category Text
* @package Text_Highlighter
* @copyright 2004-2006 Andrey Demenev
* @license http://www.php.net/license/3_0.txt PHP License
* @version Release: 0.7.0
* @link http://pear.php.net/package/Text_Highlighter
*/
class Text_Highlighter_AVRC extends Text_Highlighter
{
var $_language = 'avrc';
/**
* PHP4 Compatible Constructor
*
* @param array $options
* @access public
*/
function Text_Highlighter_AVRC($options=array())
{
$this->__construct($options);
}
/**
* Constructor
*
* @param array $options
* @access public
*/
function __construct($options=array())
{
$this->_options = $options;
$this->_regs = array (
-1 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
0 => '/((?i)\\\\)/',
1 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
2 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
3 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
4 => '//',
5 => '/((?i)")|((?i)<)/',
6 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?i)\\/\\*)|((?i)\\/\\/.+)/',
7 => '/((?i)\\$\\w+\\s*:.+\\$)/',
8 => '/((?i)\\$\\w+\\s*:.+\\$)/',
);
$this->_counts = array (
-1 =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 2,
9 => 0,
10 => 0,
11 => 0,
12 => 0,
13 => 0,
),
0 =>
array (
0 => 0,
),
1 =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 2,
9 => 0,
10 => 0,
11 => 0,
12 => 0,
13 => 0,
),
2 =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 2,
9 => 0,
10 => 0,
11 => 0,
12 => 0,
13 => 0,
),
3 =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 2,
9 => 0,
10 => 0,
11 => 0,
12 => 0,
13 => 0,
),
4 =>
array (
),
5 =>
array (
0 => 0,
1 => 0,
),
6 =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 2,
8 => 0,
9 => 0,
),
7 =>
array (
0 => 0,
),
8 =>
array (
0 => 0,
),
);
$this->_delim = array (
-1 =>
array (
0 => 'quotes',
1 => 'brackets',
2 => 'brackets',
3 => 'brackets',
4 => '',
5 => '',
6 => '',
7 => '',
8 => '',
9 => 'prepro',
10 => 'prepro',
11 => '',
12 => 'mlcomment',
13 => 'comment',
),
0 =>
array (
0 => '',
),
1 =>
array (
0 => 'quotes',
1 => 'brackets',
2 => 'brackets',
3 => 'brackets',
4 => '',
5 => '',
6 => '',
7 => '',
8 => '',
9 => 'prepro',
10 => 'prepro',
11 => '',
12 => 'mlcomment',
13 => 'comment',
),
2 =>
array (
0 => 'quotes',
1 => 'brackets',
2 => 'brackets',
3 => 'brackets',
4 => '',
5 => '',
6 => '',
7 => '',
8 => '',
9 => 'prepro',
10 => 'prepro',
11 => '',
12 => 'mlcomment',
13 => 'comment',
),
3 =>
array (
0 => 'quotes',
1 => 'brackets',
2 => 'brackets',
3 => 'brackets',
4 => '',
5 => '',
6 => '',
7 => '',
8 => '',
9 => 'prepro',
10 => 'prepro',
11 => '',
12 => 'mlcomment',
13 => 'comment',
),
4 =>
array (
),
5 =>
array (
0 => 'quotes',
1 => 'quotes',
),
6 =>
array (
0 => 'quotes',
1 => 'brackets',
2 => 'brackets',
3 => '',
4 => '',
5 => '',
6 => '',
7 => '',
8 => 'mlcomment',
9 => 'comment',
),
7 =>
array (
0 => '',
),
8 =>
array (
0 => '',
),
);
$this->_inner = array (
-1 =>
array (
0 => 'string',
1 => 'code',
2 => 'code',
3 => 'code',
4 => 'identifier',
5 => 'number',
6 => 'number',
7 => 'number',
8 => 'number',
9 => 'prepro',
10 => 'code',
11 => 'number',
12 => 'mlcomment',
13 => 'comment',
),
0 =>
array (
0 => 'special',
),
1 =>
array (
0 => 'string',
1 => 'code',
2 => 'code',
3 => 'code',
4 => 'identifier',
5 => 'number',
6 => 'number',
7 => 'number',
8 => 'number',
9 => 'prepro',
10 => 'code',
11 => 'number',
12 => 'mlcomment',
13 => 'comment',
),
2 =>
array (
0 => 'string',
1 => 'code',
2 => 'code',
3 => 'code',
4 => 'identifier',
5 => 'number',
6 => 'number',
7 => 'number',
8 => 'number',
9 => 'prepro',
10 => 'code',
11 => 'number',
12 => 'mlcomment',
13 => 'comment',
),
3 =>
array (
0 => 'string',
1 => 'code',
2 => 'code',
3 => 'code',
4 => 'identifier',
5 => 'number',
6 => 'number',
7 => 'number',
8 => 'number',
9 => 'prepro',
10 => 'code',
11 => 'number',
12 => 'mlcomment',
13 => 'comment',
),
4 =>
array (
),
5 =>
array (
0 => 'string',
1 => 'string',
),
6 =>
array (
0 => 'string',
1 => 'code',
2 => 'code',
3 => 'identifier',
4 => 'number',
5 => 'number',
6 => 'number',
7 => 'number',
8 => 'mlcomment',
9 => 'comment',
),
7 =>
array (
0 => 'inlinedoc',
),
8 =>
array (
0 => 'inlinedoc',
),
);
$this->_end = array (
0 => '/(?i)"/',
1 => '/(?i)\\}/',
2 => '/(?i)\\)/',
3 => '/(?i)\\]/',
4 => '/(?i)>/',
5 => '/(?mi)(?<!\\\\)$/',
6 => '/(?mi)(?<!\\\\)$/',
7 => '/(?i)\\*\\//',
8 => '/(?mi)$/',
);
$this->_states = array (
-1 =>
array (
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => -1,
5 => -1,
6 => -1,
7 => -1,
8 => -1,
9 => 5,
10 => 6,
11 => -1,
12 => 7,
13 => 8,
),
0 =>
array (
0 => -1,
),
1 =>
array (
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => -1,
5 => -1,
6 => -1,
7 => -1,
8 => -1,
9 => 5,
10 => 6,
11 => -1,
12 => 7,
13 => 8,
),
2 =>
array (
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => -1,
5 => -1,
6 => -1,
7 => -1,
8 => -1,
9 => 5,
10 => 6,
11 => -1,
12 => 7,
13 => 8,
),
3 =>
array (
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => -1,
5 => -1,
6 => -1,
7 => -1,
8 => -1,
9 => 5,
10 => 6,
11 => -1,
12 => 7,
13 => 8,
),
4 =>
array (
),
5 =>
array (
0 => 0,
1 => 4,
),
6 =>
array (
0 => 0,
1 => 1,
2 => 2,
3 => -1,
4 => -1,
5 => -1,
6 => -1,
7 => -1,
8 => 7,
9 => 8,
),
7 =>
array (
0 => -1,
),
8 =>
array (
0 => -1,
),
);
$this->_keywords = array (
-1 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 => -1,
4 =>
array (
'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
'registers' => '/^(ACSR|ADCH|ADCL|ADCSRA|ADMUX|ASSR|DDRA|DDRB|DDRC|DDRD|DDRE|DDRF|DDRG|EEARH|EEARL|EECR|EEDR|EICRA|EICRB|EIFR|EIMSK|ETIFR|ETIMSK|GICR|GIFR|ICR1H|ICR1L|ICR3H|ICR3L|MCUCR|MCUCSR|OCDR|OCR0|OCR1AH|OCR1AL|OCR1BH|OCR1BL|OCR1CH|OCR1CL|OCR2|OCR3AH|OCR3AL|OCR3BH|OCR3BL|OCR3CH|OCR3CL|OSCCAL|PINA|PINB|PINC|PIND|PINE|PINF|PING|PORTA|PORTB|PORTC|PORTD|PORTE|PORTF|PORTG|RAMPZ|SFIOR|SPCR|SPDR|SPH|SPL|SPMCR|SPMCSR|SPSR|SREG|TCCR0|TCCR1A|TCCR1B|TCCR1C|TCCR2|TCCR3A|TCCR3B|TCCR3C|TCNT0|TCNT1H|TCNT1L|TCNT2|TCNT3H|TCNT3L|TIFR|TIMSK|TWAR|TWBR|TWCR|TWDR|TWSR|UBRR0H|UBRR0L|UBRR1H|UBRR1L|UBRRH|UBRRL|UCSR0A|UCSR0B|UCSR0C|UCSR1A|UCSR1B|UCSR1C|UCSRA|UCSRB|UCSRC|UDR|UDR0|UDR1|WDTCR|XDIV|XMCRA|XMCRB)$/',
'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
),
5 =>
array (
),
6 =>
array (
),
7 =>
array (
),
8 =>
array (
),
9 => -1,
10 => -1,
11 =>
array (
),
12 => -1,
13 => -1,
),
0 =>
array (
0 =>
array (
),
),
1 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 => -1,
4 =>
array (
'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
'registers' => '/^(ACSR|ADCH|ADCL|ADCSRA|ADMUX|ASSR|DDRA|DDRB|DDRC|DDRD|DDRE|DDRF|DDRG|EEARH|EEARL|EECR|EEDR|EICRA|EICRB|EIFR|EIMSK|ETIFR|ETIMSK|GICR|GIFR|ICR1H|ICR1L|ICR3H|ICR3L|MCUCR|MCUCSR|OCDR|OCR0|OCR1AH|OCR1AL|OCR1BH|OCR1BL|OCR1CH|OCR1CL|OCR2|OCR3AH|OCR3AL|OCR3BH|OCR3BL|OCR3CH|OCR3CL|OSCCAL|PINA|PINB|PINC|PIND|PINE|PINF|PING|PORTA|PORTB|PORTC|PORTD|PORTE|PORTF|PORTG|RAMPZ|SFIOR|SPCR|SPDR|SPH|SPL|SPMCR|SPMCSR|SPSR|SREG|TCCR0|TCCR1A|TCCR1B|TCCR1C|TCCR2|TCCR3A|TCCR3B|TCCR3C|TCNT0|TCNT1H|TCNT1L|TCNT2|TCNT3H|TCNT3L|TIFR|TIMSK|TWAR|TWBR|TWCR|TWDR|TWSR|UBRR0H|UBRR0L|UBRR1H|UBRR1L|UBRRH|UBRRL|UCSR0A|UCSR0B|UCSR0C|UCSR1A|UCSR1B|UCSR1C|UCSRA|UCSRB|UCSRC|UDR|UDR0|UDR1|WDTCR|XDIV|XMCRA|XMCRB)$/',
'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
),
5 =>
array (
),
6 =>
array (
),
7 =>
array (
),
8 =>
array (
),
9 => -1,
10 => -1,
11 =>
array (
),
12 => -1,
13 => -1,
),
2 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 => -1,
4 =>
array (
'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
'registers' => '/^(ACSR|ADCH|ADCL|ADCSRA|ADMUX|ASSR|DDRA|DDRB|DDRC|DDRD|DDRE|DDRF|DDRG|EEARH|EEARL|EECR|EEDR|EICRA|EICRB|EIFR|EIMSK|ETIFR|ETIMSK|GICR|GIFR|ICR1H|ICR1L|ICR3H|ICR3L|MCUCR|MCUCSR|OCDR|OCR0|OCR1AH|OCR1AL|OCR1BH|OCR1BL|OCR1CH|OCR1CL|OCR2|OCR3AH|OCR3AL|OCR3BH|OCR3BL|OCR3CH|OCR3CL|OSCCAL|PINA|PINB|PINC|PIND|PINE|PINF|PING|PORTA|PORTB|PORTC|PORTD|PORTE|PORTF|PORTG|RAMPZ|SFIOR|SPCR|SPDR|SPH|SPL|SPMCR|SPMCSR|SPSR|SREG|TCCR0|TCCR1A|TCCR1B|TCCR1C|TCCR2|TCCR3A|TCCR3B|TCCR3C|TCNT0|TCNT1H|TCNT1L|TCNT2|TCNT3H|TCNT3L|TIFR|TIMSK|TWAR|TWBR|TWCR|TWDR|TWSR|UBRR0H|UBRR0L|UBRR1H|UBRR1L|UBRRH|UBRRL|UCSR0A|UCSR0B|UCSR0C|UCSR1A|UCSR1B|UCSR1C|UCSRA|UCSRB|UCSRC|UDR|UDR0|UDR1|WDTCR|XDIV|XMCRA|XMCRB)$/',
'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
),
5 =>
array (
),
6 =>
array (
),
7 =>
array (
),
8 =>
array (
),
9 => -1,
10 => -1,
11 =>
array (
),
12 => -1,
13 => -1,
),
3 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 => -1,
4 =>
array (
'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
'registers' => '/^(ACSR|ADCH|ADCL|ADCSRA|ADMUX|ASSR|DDRA|DDRB|DDRC|DDRD|DDRE|DDRF|DDRG|EEARH|EEARL|EECR|EEDR|EICRA|EICRB|EIFR|EIMSK|ETIFR|ETIMSK|GICR|GIFR|ICR1H|ICR1L|ICR3H|ICR3L|MCUCR|MCUCSR|OCDR|OCR0|OCR1AH|OCR1AL|OCR1BH|OCR1BL|OCR1CH|OCR1CL|OCR2|OCR3AH|OCR3AL|OCR3BH|OCR3BL|OCR3CH|OCR3CL|OSCCAL|PINA|PINB|PINC|PIND|PINE|PINF|PING|PORTA|PORTB|PORTC|PORTD|PORTE|PORTF|PORTG|RAMPZ|SFIOR|SPCR|SPDR|SPH|SPL|SPMCR|SPMCSR|SPSR|SREG|TCCR0|TCCR1A|TCCR1B|TCCR1C|TCCR2|TCCR3A|TCCR3B|TCCR3C|TCNT0|TCNT1H|TCNT1L|TCNT2|TCNT3H|TCNT3L|TIFR|TIMSK|TWAR|TWBR|TWCR|TWDR|TWSR|UBRR0H|UBRR0L|UBRR1H|UBRR1L|UBRRH|UBRRL|UCSR0A|UCSR0B|UCSR0C|UCSR1A|UCSR1B|UCSR1C|UCSRA|UCSRB|UCSRC|UDR|UDR0|UDR1|WDTCR|XDIV|XMCRA|XMCRB)$/',
'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
),
5 =>
array (
),
6 =>
array (
),
7 =>
array (
),
8 =>
array (
),
9 => -1,
10 => -1,
11 =>
array (
),
12 => -1,
13 => -1,
),
4 =>
array (
),
5 =>
array (
0 => -1,
1 => -1,
),
6 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 =>
array (
'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
'registers' => '/^(ACSR|ADCH|ADCL|ADCSRA|ADMUX|ASSR|DDRA|DDRB|DDRC|DDRD|DDRE|DDRF|DDRG|EEARH|EEARL|EECR|EEDR|EICRA|EICRB|EIFR|EIMSK|ETIFR|ETIMSK|GICR|GIFR|ICR1H|ICR1L|ICR3H|ICR3L|MCUCR|MCUCSR|OCDR|OCR0|OCR1AH|OCR1AL|OCR1BH|OCR1BL|OCR1CH|OCR1CL|OCR2|OCR3AH|OCR3AL|OCR3BH|OCR3BL|OCR3CH|OCR3CL|OSCCAL|PINA|PINB|PINC|PIND|PINE|PINF|PING|PORTA|PORTB|PORTC|PORTD|PORTE|PORTF|PORTG|RAMPZ|SFIOR|SPCR|SPDR|SPH|SPL|SPMCR|SPMCSR|SPSR|SREG|TCCR0|TCCR1A|TCCR1B|TCCR1C|TCCR2|TCCR3A|TCCR3B|TCCR3C|TCNT0|TCNT1H|TCNT1L|TCNT2|TCNT3H|TCNT3L|TIFR|TIMSK|TWAR|TWBR|TWCR|TWDR|TWSR|UBRR0H|UBRR0L|UBRR1H|UBRR1L|UBRRH|UBRRL|UCSR0A|UCSR0B|UCSR0C|UCSR1A|UCSR1B|UCSR1C|UCSRA|UCSRB|UCSRC|UDR|UDR0|UDR1|WDTCR|XDIV|XMCRA|XMCRB)$/',
'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
),
4 =>
array (
),
5 =>
array (
),
6 =>
array (
),
7 =>
array (
),
8 => -1,
9 => -1,
),
7 =>
array (
0 =>
array (
),
),
8 =>
array (
0 =>
array (
),
),
);
$this->_parts = array (
0 =>
array (
0 => NULL,
),
1 =>
array (
0 => NULL,
1 => NULL,
2 => NULL,
3 => NULL,
4 => NULL,
5 => NULL,
6 => NULL,
7 => NULL,
8 => NULL,
9 => NULL,
10 => NULL,
11 => NULL,
12 => NULL,
13 => NULL,
),
2 =>
array (
0 => NULL,
1 => NULL,
2 => NULL,
3 => NULL,
4 => NULL,
5 => NULL,
6 => NULL,
7 => NULL,
8 => NULL,
9 => NULL,
10 => NULL,
11 => NULL,
12 => NULL,
13 => NULL,
),
3 =>
array (
0 => NULL,
1 => NULL,
2 => NULL,
3 => NULL,
4 => NULL,
5 => NULL,
6 => NULL,
7 => NULL,
8 => NULL,
9 => NULL,
10 => NULL,
11 => NULL,
12 => NULL,
13 => NULL,
),
4 =>
array (
),
5 =>
array (
0 => NULL,
1 => NULL,
),
6 =>
array (
0 => NULL,
1 => NULL,
2 => NULL,
3 => NULL,
4 => NULL,
5 => NULL,
6 => NULL,
7 => NULL,
8 => NULL,
9 => NULL,
),
7 =>
array (
0 => NULL,
),
8 =>
array (
0 => NULL,
),
);
$this->_subst = array (
-1 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
9 => false,
10 => false,
11 => false,
12 => false,
13 => false,
),
0 =>
array (
0 => false,
),
1 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
9 => false,
10 => false,
11 => false,
12 => false,
13 => false,
),
2 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
9 => false,
10 => false,
11 => false,
12 => false,
13 => false,
),
3 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
9 => false,
10 => false,
11 => false,
12 => false,
13 => false,
),
4 =>
array (
),
5 =>
array (
0 => false,
1 => false,
),
6 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
9 => false,
),
7 =>
array (
0 => false,
),
8 =>
array (
0 => false,
),
);
$this->_conditions = array (
);
$this->_kwmap = array (
'reserved' => 'reserved',
'registers' => 'reserved',
'types' => 'types',
'Common Macros' => 'prepro',
);
$this->_defClass = 'code';
$this->_checkDefines();
}
}

View file

@ -0,0 +1,891 @@
<?php
/**
* Auto-generated class. CPP syntax highlighting
*
*
* Thanks to Aaron Kalin for initial
* implementation of this highlighter
*
*
* PHP version 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @copyright 2004-2006 Andrey Demenev
* @license http://www.php.net/license/3_0.txt PHP License
* @link http://pear.php.net/package/Text_Highlighter
* @category Text
* @package Text_Highlighter
* @version generated from: cpp.xml
* @author Aaron Kalin
* @author Andrey Demenev <demenev@gmail.com>
*
*/
/**
* @ignore
*/
require_once 'Text/Highlighter.php';
/**
* Auto-generated class. CPP syntax highlighting
*
* @author Aaron Kalin
* @author Andrey Demenev <demenev@gmail.com>
* @category Text
* @package Text_Highlighter
* @copyright 2004-2006 Andrey Demenev
* @license http://www.php.net/license/3_0.txt PHP License
* @version Release: 0.7.0
* @link http://pear.php.net/package/Text_Highlighter
*/
class Text_Highlighter_CPP extends Text_Highlighter
{
var $_language = 'cpp';
/**
* PHP4 Compatible Constructor
*
* @param array $options
* @access public
*/
function Text_Highlighter_CPP($options=array())
{
$this->__construct($options);
}
/**
* Constructor
*
* @param array $options
* @access public
*/
function __construct($options=array())
{
$this->_options = $options;
$this->_regs = array (
-1 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
0 => '/((?i)\\\\)/',
1 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
2 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
3 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
4 => '//',
5 => '/((?i)")|((?i)<)/',
6 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?i)\\/\\*)|((?i)\\/\\/.+)/',
7 => '/((?i)\\$\\w+\\s*:.+\\$)/',
8 => '/((?i)\\$\\w+\\s*:.+\\$)/',
);
$this->_counts = array (
-1 =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 2,
9 => 0,
10 => 0,
11 => 0,
12 => 0,
13 => 0,
),
0 =>
array (
0 => 0,
),
1 =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 2,
9 => 0,
10 => 0,
11 => 0,
12 => 0,
13 => 0,
),
2 =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 2,
9 => 0,
10 => 0,
11 => 0,
12 => 0,
13 => 0,
),
3 =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 2,
9 => 0,
10 => 0,
11 => 0,
12 => 0,
13 => 0,
),
4 =>
array (
),
5 =>
array (
0 => 0,
1 => 0,
),
6 =>
array (
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 2,
8 => 0,
9 => 0,
),
7 =>
array (
0 => 0,
),
8 =>
array (
0 => 0,
),
);
$this->_delim = array (
-1 =>
array (
0 => 'quotes',
1 => 'brackets',
2 => 'brackets',
3 => 'brackets',
4 => '',
5 => '',
6 => '',
7 => '',
8 => '',
9 => 'prepro',
10 => 'prepro',
11 => '',
12 => 'mlcomment',
13 => 'comment',
),
0 =>
array (
0 => '',
),
1 =>
array (
0 => 'quotes',
1 => 'brackets',
2 => 'brackets',
3 => 'brackets',
4 => '',
5 => '',
6 => '',
7 => '',
8 => '',
9 => 'prepro',
10 => 'prepro',
11 => '',
12 => 'mlcomment',
13 => 'comment',
),
2 =>
array (
0 => 'quotes',
1 => 'brackets',
2 => 'brackets',
3 => 'brackets',
4 => '',
5 => '',
6 => '',
7 => '',
8 => '',
9 => 'prepro',
10 => 'prepro',
11 => '',
12 => 'mlcomment',
13 => 'comment',
),
3 =>
array (
0 => 'quotes',
1 => 'brackets',
2 => 'brackets',
3 => 'brackets',
4 => '',
5 => '',
6 => '',
7 => '',
8 => '',
9 => 'prepro',
10 => 'prepro',
11 => '',
12 => 'mlcomment',
13 => 'comment',
),
4 =>
array (
),
5 =>
array (
0 => 'quotes',
1 => 'quotes',
),
6 =>
array (
0 => 'quotes',
1 => 'brackets',
2 => 'brackets',
3 => '',
4 => '',
5 => '',
6 => '',
7 => '',
8 => 'mlcomment',
9 => 'comment',
),
7 =>
array (
0 => '',
),
8 =>
array (
0 => '',
),
);
$this->_inner = array (
-1 =>
array (
0 => 'string',
1 => 'code',
2 => 'code',
3 => 'code',
4 => 'identifier',
5 => 'number',
6 => 'number',
7 => 'number',
8 => 'number',
9 => 'prepro',
10 => 'code',
11 => 'number',
12 => 'mlcomment',
13 => 'comment',
),
0 =>
array (
0 => 'special',
),
1 =>
array (
0 => 'string',
1 => 'code',
2 => 'code',
3 => 'code',
4 => 'identifier',
5 => 'number',
6 => 'number',
7 => 'number',
8 => 'number',
9 => 'prepro',
10 => 'code',
11 => 'number',
12 => 'mlcomment',
13 => 'comment',
),
2 =>
array (
0 => 'string',
1 => 'code',
2 => 'code',
3 => 'code',
4 => 'identifier',
5 => 'number',
6 => 'number',
7 => 'number',
8 => 'number',
9 => 'prepro',
10 => 'code',
11 => 'number',
12 => 'mlcomment',
13 => 'comment',
),
3 =>
array (
0 => 'string',
1 => 'code',
2 => 'code',
3 => 'code',
4 => 'identifier',
5 => 'number',
6 => 'number',
7 => 'number',
8 => 'number',
9 => 'prepro',
10 => 'code',
11 => 'number',
12 => 'mlcomment',
13 => 'comment',
),
4 =>
array (
),
5 =>
array (
0 => 'string',
1 => 'string',
),
6 =>
array (
0 => 'string',
1 => 'code',
2 => 'code',
3 => 'identifier',
4 => 'number',
5 => 'number',
6 => 'number',
7 => 'number',
8 => 'mlcomment',
9 => 'comment',
),
7 =>
array (
0 => 'inlinedoc',
),
8 =>
array (
0 => 'inlinedoc',
),
);
$this->_end = array (
0 => '/(?i)"/',
1 => '/(?i)\\}/',
2 => '/(?i)\\)/',
3 => '/(?i)\\]/',
4 => '/(?i)>/',
5 => '/(?mi)(?<!\\\\)$/',
6 => '/(?mi)(?<!\\\\)$/',
7 => '/(?i)\\*\\//',
8 => '/(?mi)$/',
);
$this->_states = array (
-1 =>
array (
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => -1,
5 => -1,
6 => -1,
7 => -1,
8 => -1,
9 => 5,
10 => 6,
11 => -1,
12 => 7,
13 => 8,
),
0 =>
array (
0 => -1,
),
1 =>
array (
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => -1,
5 => -1,
6 => -1,
7 => -1,
8 => -1,
9 => 5,
10 => 6,
11 => -1,
12 => 7,
13 => 8,
),
2 =>
array (
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => -1,
5 => -1,
6 => -1,
7 => -1,
8 => -1,
9 => 5,
10 => 6,
11 => -1,
12 => 7,
13 => 8,
),
3 =>
array (
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => -1,
5 => -1,
6 => -1,
7 => -1,
8 => -1,
9 => 5,
10 => 6,
11 => -1,
12 => 7,
13 => 8,
),
4 =>
array (
),
5 =>
array (
0 => 0,
1 => 4,
),
6 =>
array (
0 => 0,
1 => 1,
2 => 2,
3 => -1,
4 => -1,
5 => -1,
6 => -1,
7 => -1,
8 => 7,
9 => 8,
),
7 =>
array (
0 => -1,
),
8 =>
array (
0 => -1,
),
);
$this->_keywords = array (
-1 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 => -1,
4 =>
array (
'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
),
5 =>
array (
),
6 =>
array (
),
7 =>
array (
),
8 =>
array (
),
9 => -1,
10 => -1,
11 =>
array (
),
12 => -1,
13 => -1,
),
0 =>
array (
0 =>
array (
),
),
1 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 => -1,
4 =>
array (
'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
),
5 =>
array (
),
6 =>
array (
),
7 =>
array (
),
8 =>
array (
),
9 => -1,
10 => -1,
11 =>
array (
),
12 => -1,
13 => -1,
),
2 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 => -1,
4 =>
array (
'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
),
5 =>
array (
),
6 =>
array (
),
7 =>
array (
),
8 =>
array (
),
9 => -1,
10 => -1,
11 =>
array (
),
12 => -1,
13 => -1,
),
3 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 => -1,
4 =>
array (
'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
),
5 =>
array (
),
6 =>
array (
),
7 =>
array (
),
8 =>
array (
),
9 => -1,
10 => -1,
11 =>
array (
),
12 => -1,
13 => -1,
),
4 =>
array (
),
5 =>
array (
0 => -1,
1 => -1,
),
6 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 =>
array (
'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
),
4 =>
array (
),
5 =>
array (
),
6 =>
array (
),
7 =>
array (
),
8 => -1,
9 => -1,
),
7 =>
array (
0 =>
array (
),
),
8 =>
array (
0 =>
array (
),
),
);
$this->_parts = array (
0 =>
array (
0 => NULL,
),
1 =>
array (
0 => NULL,
1 => NULL,
2 => NULL,
3 => NULL,
4 => NULL,
5 => NULL,
6 => NULL,
7 => NULL,
8 => NULL,
9 => NULL,
10 => NULL,
11 => NULL,
12 => NULL,
13 => NULL,
),
2 =>
array (
0 => NULL,
1 => NULL,
2 => NULL,
3 => NULL,
4 => NULL,
5 => NULL,
6 => NULL,
7 => NULL,
8 => NULL,
9 => NULL,
10 => NULL,
11 => NULL,
12 => NULL,
13 => NULL,
),
3 =>
array (
0 => NULL,
1 => NULL,
2 => NULL,
3 => NULL,
4 => NULL,
5 => NULL,
6 => NULL,
7 => NULL,
8 => NULL,
9 => NULL,
10 => NULL,
11 => NULL,
12 => NULL,
13 => NULL,
),
4 =>
array (
),
5 =>
array (
0 => NULL,
1 => NULL,
),
6 =>
array (
0 => NULL,
1 => NULL,
2 => NULL,
3 => NULL,
4 => NULL,
5 => NULL,
6 => NULL,
7 => NULL,
8 => NULL,
9 => NULL,
),
7 =>
array (
0 => NULL,
),
8 =>
array (
0 => NULL,
),
);
$this->_subst = array (
-1 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
9 => false,
10 => false,
11 => false,
12 => false,
13 => false,
),
0 =>
array (
0 => false,
),
1 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
9 => false,
10 => false,
11 => false,
12 => false,
13 => false,
),
2 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
9 => false,
10 => false,
11 => false,
12 => false,
13 => false,
),
3 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
9 => false,
10 => false,
11 => false,
12 => false,
13 => false,
),
4 =>
array (
),
5 =>
array (
0 => false,
1 => false,
),
6 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
9 => false,
),
7 =>
array (
0 => false,
),
8 =>
array (
0 => false,
),
);
$this->_conditions = array (
);
$this->_kwmap = array (
'reserved' => 'reserved',
'types' => 'types',
'Common Macros' => 'prepro',
);
$this->_defClass = 'code';
$this->_checkDefines();
}
}

View file

@ -0,0 +1,437 @@
<?php
/**
* Auto-generated class. CSS syntax highlighting
*
* PHP version 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @copyright 2004-2006 Andrey Demenev
* @license http://www.php.net/license/3_0.txt PHP License
* @link http://pear.php.net/package/Text_Highlighter
* @category Text
* @package Text_Highlighter
* @version generated from: css.xml
* @author Andrey Demenev <demenev@gmail.com>
*
*/
/**
* @ignore
*/
require_once 'Text/Highlighter.php';
/**
* Auto-generated class. CSS syntax highlighting
*
* @author Andrey Demenev <demenev@gmail.com>
* @category Text
* @package Text_Highlighter
* @copyright 2004-2006 Andrey Demenev
* @license http://www.php.net/license/3_0.txt PHP License
* @version Release: 0.7.0
* @link http://pear.php.net/package/Text_Highlighter
*/
class Text_Highlighter_CSS extends Text_Highlighter
{
var $_language = 'css';
/**
* PHP4 Compatible Constructor
*
* @param array $options
* @access public
*/
function Text_Highlighter_CSS($options=array())
{
$this->__construct($options);
}
/**
* Constructor
*
* @param array $options
* @access public
*/
function __construct($options=array())
{
$this->_options = $options;
$this->_regs = array (
-1 => '/((?i)\\/\\*)|((?i)(@[a-z\\d]+))|((?i)(((\\.|#)?[a-z]+[a-z\\d\\-]*(?![a-z\\d\\-]))|(\\*))(?!\\s*:\\s*[\\s\\{]))|((?i):[a-z][a-z\\d\\-]*)|((?i)\\[)|((?i)\\{)/',
0 => '//',
1 => '/((?i)\\d*\\.?\\d+(\\%|em|ex|pc|pt|px|in|mm|cm))|((?i)\\d*\\.?\\d+)|((?i)[a-z][a-z\\d\\-]*)|((?i)#([\\da-f]{6}|[\\da-f]{3})\\b)/',
2 => '/((?i)\')|((?i)")|((?i)[\\w\\-\\:]+)/',
3 => '/((?i)\\/\\*)|((?i)[a-z][a-z\\d\\-]*\\s*:)|((?i)(((\\.|#)?[a-z]+[a-z\\d\\-]*(?![a-z\\d\\-]))|(\\*))(?!\\s*:\\s*[\\s\\{]))|((?i)\\{)/',
4 => '/((?i)\\\\[\\\\(\\\\)\\\\])/',
5 => '/((?i)\\\\\\\\|\\\\"|\\\\\'|\\\\`)/',
6 => '/((?i)\\\\\\\\|\\\\"|\\\\\'|\\\\`|\\\\t|\\\\n|\\\\r)/',
);
$this->_counts = array (
-1 =>
array (
0 => 0,
1 => 1,
2 => 4,
3 => 0,
4 => 0,
5 => 0,
),
0 =>
array (
),
1 =>
array (
0 => 1,
1 => 0,
2 => 0,
3 => 1,
),
2 =>
array (
0 => 0,
1 => 0,
2 => 0,
),
3 =>
array (
0 => 0,
1 => 0,
2 => 4,
3 => 0,
),
4 =>
array (
0 => 0,
),
5 =>
array (
0 => 0,
),
6 =>
array (
0 => 0,
),
);
$this->_delim = array (
-1 =>
array (
0 => 'comment',
1 => '',
2 => '',
3 => '',
4 => 'brackets',
5 => 'brackets',
),
0 =>
array (
),
1 =>
array (
0 => '',
1 => '',
2 => '',
3 => '',
),
2 =>
array (
0 => 'quotes',
1 => 'quotes',
2 => '',
),
3 =>
array (
0 => 'comment',
1 => 'reserved',
2 => '',
3 => 'brackets',
),
4 =>
array (
0 => '',
),
5 =>
array (
0 => '',
),
6 =>
array (
0 => '',
),
);
$this->_inner = array (
-1 =>
array (
0 => 'comment',
1 => 'var',
2 => 'identifier',
3 => 'special',
4 => 'code',
5 => 'code',
),
0 =>
array (
),
1 =>
array (
0 => 'number',
1 => 'number',
2 => 'code',
3 => 'var',
),
2 =>
array (
0 => 'string',
1 => 'string',
2 => 'var',
),
3 =>
array (
0 => 'comment',
1 => 'code',
2 => 'identifier',
3 => 'code',
),
4 =>
array (
0 => 'string',
),
5 =>
array (
0 => 'special',
),
6 =>
array (
0 => 'special',
),
);
$this->_end = array (
0 => '/(?i)\\*\\//',
1 => '/(?i)(?=;|\\})/',
2 => '/(?i)\\]/',
3 => '/(?i)\\}/',
4 => '/(?i)\\)/',
5 => '/(?i)\'/',
6 => '/(?i)"/',
);
$this->_states = array (
-1 =>
array (
0 => 0,
1 => -1,
2 => -1,
3 => -1,
4 => 2,
5 => 3,
),
0 =>
array (
),
1 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 => -1,
),
2 =>
array (
0 => 5,
1 => 6,
2 => -1,
),
3 =>
array (
0 => 0,
1 => 1,
2 => -1,
3 => 3,
),
4 =>
array (
0 => -1,
),
5 =>
array (
0 => -1,
),
6 =>
array (
0 => -1,
),
);
$this->_keywords = array (
-1 =>
array (
0 => -1,
1 =>
array (
),
2 =>
array (
),
3 =>
array (
),
4 => -1,
5 => -1,
),
0 =>
array (
),
1 =>
array (
0 =>
array (
),
1 =>
array (
),
2 =>
array (
'propertyValue' => '/^((?i)far-left|left|center-left|center-right|center|far-right|right-side|right|behind|leftwards|rightwards|inherit|scroll|fixed|transparent|none|repeat-x|repeat-y|repeat|no-repeat|collapse|separate|auto|top|bottom|both|open-quote|close-quote|no-open-quote|no-close-quote|crosshair|default|pointer|move|e-resize|ne-resize|nw-resize|n-resize|se-resize|sw-resize|s-resize|text|wait|help|ltr|rtl|inline|block|list-item|run-in|compact|marker|table|inline-table|table-row-group|table-header-group|table-footer-group|table-row|table-column-group|table-column|table-cell|table-caption|below|level|above|higher|lower|show|hide|caption|icon|menu|message-box|small-caption|status-bar|normal|wider|narrower|ultra-condensed|extra-condensed|condensed|semi-condensed|semi-expanded|expanded|extra-expanded|ultra-expanded|italic|oblique|small-caps|bold|bolder|lighter|inside|outside|disc|circle|square|decimal|decimal-leading-zero|lower-roman|upper-roman|lower-greek|lower-alpha|lower-latin|upper-alpha|upper-latin|hebrew|armenian|georgian|cjk-ideographic|hiragana|katakana|hiragana-iroha|katakana-iroha|crop|cross|invert|visible|hidden|always|avoid|x-low|low|medium|high|x-high|mix?|repeat?|static|relative|absolute|portrait|landscape|spell-out|once|digits|continuous|code|x-slow|slow|fast|x-fast|faster|slower|justify|underline|overline|line-through|blink|capitalize|uppercase|lowercase|embed|bidi-override|baseline|sub|super|text-top|middle|text-bottom|silent|x-soft|soft|loud|x-loud|pre|nowrap|serif|sans-serif|cursive|fantasy|monospace|empty|string|strict|loose|char|true|false|dotted|dashed|solid|double|groove|ridge|inset|outset|larger|smaller|xx-small|x-small|small|large|x-large|xx-large|all|newspaper|distribute|distribute-all-lines|distribute-center-last|inter-word|inter-ideograph|inter-cluster|kashida|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|keep-all|break-all|break-word|lr-tb|tb-rl|thin|thick|inline-block|w-resize|hand|distribute-letter|distribute-space|whitespace|male|female|child)$/',
'namedcolor' => '/^((?i)aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow|activeborder|activecaption|appworkspace|background|buttonface|buttonhighlight|buttonshadow|buttontext|captiontext|graytext|highlight|highlighttext|inactiveborder|inactivecaption|inactivecaptiontext|infobackground|infotext|menu|menutext|scrollbar|threeddarkshadow|threedface|threedhighlight|threedlightshadow|threedshadow|window|windowframe|windowtext)$/',
),
3 =>
array (
),
),
2 =>
array (
0 => -1,
1 => -1,
2 =>
array (
),
),
3 =>
array (
0 => -1,
1 => -1,
2 =>
array (
),
3 => -1,
),
4 =>
array (
0 =>
array (
),
),
5 =>
array (
0 =>
array (
),
),
6 =>
array (
0 =>
array (
),
),
);
$this->_parts = array (
0 =>
array (
),
1 =>
array (
0 =>
array (
1 => 'string',
),
1 => NULL,
2 => NULL,
3 => NULL,
),
2 =>
array (
0 => NULL,
1 => NULL,
2 => NULL,
),
3 =>
array (
0 => NULL,
1 => NULL,
2 => NULL,
3 => NULL,
),
4 =>
array (
0 => NULL,
),
5 =>
array (
0 => NULL,
),
6 =>
array (
0 => NULL,
),
);
$this->_subst = array (
-1 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
),
0 =>
array (
),
1 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
),
2 =>
array (
0 => false,
1 => false,
2 => false,
),
3 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
),
4 =>
array (
0 => false,
),
5 =>
array (
0 => false,
),
6 =>
array (
0 => false,
),
);
$this->_conditions = array (
);
$this->_kwmap = array (
'propertyValue' => 'string',
'namedcolor' => 'var',
);
$this->_defClass = 'code';
$this->_checkDefines();
}
}

View file

@ -0,0 +1,384 @@
<?php
/**
* Auto-generated class. DIFF syntax highlighting
*
* PHP version 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @copyright 2004-2006 Andrey Demenev
* @license http://www.php.net/license/3_0.txt PHP License
* @link http://pear.php.net/package/Text_Highlighter
* @category Text
* @package Text_Highlighter
* @version generated from: : diff.xml,v 1.1 2007/06/03 02:35:28 ssttoo Exp
* @author Andrey Demenev <demenev@gmail.com>
*
*/
/**
* @ignore
*/
require_once 'Text/Highlighter.php';
/**
* Auto-generated class. DIFF syntax highlighting
*
* @author Andrey Demenev <demenev@gmail.com>
* @category Text
* @package Text_Highlighter
* @copyright 2004-2006 Andrey Demenev
* @license http://www.php.net/license/3_0.txt PHP License
* @version Release: @package_version@
* @link http://pear.php.net/package/Text_Highlighter
*/
class Text_Highlighter_DIFF extends Text_Highlighter
{
var $_language = 'diff';
/**
* PHP4 Compatible Constructor
*
* @param array $options
* @access public
*/
function Text_Highlighter_DIFF($options=array())
{
$this->__construct($options);
}
/**
* Constructor
*
* @param array $options
* @access public
*/
function __construct($options=array())
{
$this->_options = $options;
$this->_regs = array (
-1 => '/((?m)^\\\\\\sNo\\snewline.+$)|((?m)^\\-\\-\\-$)|((?m)^(diff\\s+\\-|Only\\s+|Index).*$)|((?m)^(\\-\\-\\-|\\+\\+\\+)\\s.+$)|((?m)^\\*.*$)|((?m)^\\+.*$)|((?m)^!.*$)|((?m)^\\<\\s.*$)|((?m)^\\>\\s.*$)|((?m)^\\d+(\\,\\d+)?[acd]\\d+(,\\d+)?$)|((?m)^\\-.*$)|((?m)^\\+.*$)|((?m)^@@.+@@$)|((?m)^d\\d+\\s\\d+$)|((?m)^a\\d+\\s\\d+$)|((?m)^(\\d+)(,\\d+)?(a)$)|((?m)^(\\d+)(,\\d+)?(c)$)|((?m)^(\\d+)(,\\d+)?(d)$)|((?m)^a(\\d+)(\\s\\d+)?$)|((?m)^c(\\d+)(\\s\\d+)?$)|((?m)^d(\\d+)(\\s\\d+)?$)/',
0 => '//',
1 => '//',
2 => '//',
3 => '//',
4 => '//',
);
$this->_counts = array (
-1 =>
array (
0 => 0,
1 => 0,
2 => 1,
3 => 1,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 0,
9 => 2,
10 => 0,
11 => 0,
12 => 0,
13 => 0,
14 => 0,
15 => 3,
16 => 3,
17 => 3,
18 => 2,
19 => 2,
20 => 2,
),
0 =>
array (
),
1 =>
array (
),
2 =>
array (
),
3 =>
array (
),
4 =>
array (
),
);
$this->_delim = array (
-1 =>
array (
0 => '',
1 => '',
2 => '',
3 => '',
4 => '',
5 => '',
6 => '',
7 => '',
8 => '',
9 => '',
10 => '',
11 => '',
12 => '',
13 => '',
14 => 'code',
15 => 'code',
16 => 'code',
17 => '',
18 => 'code',
19 => 'code',
20 => '',
),
0 =>
array (
),
1 =>
array (
),
2 =>
array (
),
3 =>
array (
),
4 =>
array (
),
);
$this->_inner = array (
-1 =>
array (
0 => 'special',
1 => 'code',
2 => 'var',
3 => 'reserved',
4 => 'quotes',
5 => 'string',
6 => 'inlinedoc',
7 => 'quotes',
8 => 'string',
9 => 'code',
10 => 'quotes',
11 => 'string',
12 => 'code',
13 => 'code',
14 => 'var',
15 => 'string',
16 => 'inlinedoc',
17 => 'code',
18 => 'string',
19 => 'inlinedoc',
20 => 'code',
),
0 =>
array (
),
1 =>
array (
),
2 =>
array (
),
3 =>
array (
),
4 =>
array (
),
);
$this->_end = array (
0 => '/(?m)(?=^[ad]\\d+\\s\\d+)/',
1 => '/(?m)^(\\.)$/',
2 => '/(?m)^(\\.)$/',
3 => '/(?m)^(\\.)$/',
4 => '/(?m)^(\\.)$/',
);
$this->_states = array (
-1 =>
array (
0 => -1,
1 => -1,
2 => -1,
3 => -1,
4 => -1,
5 => -1,
6 => -1,
7 => -1,
8 => -1,
9 => -1,
10 => -1,
11 => -1,
12 => -1,
13 => -1,
14 => 0,
15 => 1,
16 => 2,
17 => -1,
18 => 3,
19 => 4,
20 => -1,
),
0 =>
array (
),
1 =>
array (
),
2 =>
array (
),
3 =>
array (
),
4 =>
array (
),
);
$this->_keywords = array (
-1 =>
array (
0 =>
array (
),
1 =>
array (
),
2 =>
array (
),
3 =>
array (
),
4 =>
array (
),
5 =>
array (
),
6 =>
array (
),
7 =>
array (
),
8 =>
array (
),
9 =>
array (
),
10 =>
array (
),
11 =>
array (
),
12 =>
array (
),
13 =>
array (
),
14 => -1,
15 => -1,
16 => -1,
17 =>
array (
),
18 => -1,
19 => -1,
20 =>
array (
),
),
0 =>
array (
),
1 =>
array (
),
2 =>
array (
),
3 =>
array (
),
4 =>
array (
),
);
$this->_parts = array (
0 =>
array (
),
1 =>
array (
),
2 =>
array (
),
3 =>
array (
),
4 =>
array (
),
);
$this->_subst = array (
-1 =>
array (
0 => false,
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => false,
7 => false,
8 => false,
9 => false,
10 => false,
11 => false,
12 => false,
13 => false,
14 => false,
15 => false,
16 => false,
17 => false,
18 => false,
19 => false,
20 => false,
),
0 =>
array (
),
1 =>
array (
),
2 =>
array (
),
3 =>
array (
),
4 =>
array (
),
);
$this->_conditions = array (
);
$this->_kwmap = array (
);
$this->_defClass = 'default';
$this->_checkDefines();
}
}

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