Merge branch '0.8.x' into design_reset
* 0.8.x: (32 commits) admin indicators in groups show section with admins in sidebar of group update to latest (r76) version of XMPPHP better output for common error handler fix logging error note when going background change name of constructor for xmppdaemon add a lot more logging to xmppdaemon error in get_option_value wasn't returning a value reformat commandline.inc if not in daemon mode, xmppdaemon sends log to stdout extract log-line formatting to its own function got my background/foreground logic backwards twitter status fetcher takes an id argument more efficient fixup of conversations commandline processing handles errors better xmppdaemon.php can stay in foreground command line arg handling a little more flexible Daemon can optionally not go into the background don't canonicalize people's text into URLs ... Conflicts: theme/base/css/display.css
This commit is contained in:
commit
dd1fc46f09
12
README
12
README
|
@ -1278,6 +1278,18 @@ type: type of search. Ignored if PostgreSQL or Sphinx are enabled. Can either
|
|||
systems. We'll probably add another type sometime in the future,
|
||||
with our own indexing system (maybe like MediaWiki's).
|
||||
|
||||
sessions
|
||||
--------
|
||||
|
||||
Session handling.
|
||||
|
||||
handle: boolean. Whether we should register our own PHP session-handling
|
||||
code (using the database and memcache if enabled). Defaults to false.
|
||||
Setting this to true makes some sense on large or multi-server
|
||||
sites, but it probably won't hurt for smaller ones, either.
|
||||
debug: whether to output debugging info for session storage. Can help
|
||||
with weird session bugs, sometimes. Default false.
|
||||
|
||||
Troubleshooting
|
||||
===============
|
||||
|
||||
|
|
|
@ -67,7 +67,9 @@ class ApiAction extends Action
|
|||
$this->process_command();
|
||||
} else {
|
||||
# basic authentication failed
|
||||
common_log(LOG_WARNING, "Failed API auth attempt, nickname: $nickname.");
|
||||
list($proxy, $ip) = common_client_ip();
|
||||
|
||||
common_log(LOG_WARNING, "Failed API auth attempt, nickname = $nickname, proxy = $proxy, ip = $ip.");
|
||||
$this->show_basic_auth_error();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,6 +167,15 @@ class GroupMemberListItem extends ProfileListItem
|
|||
$this->group = $group;
|
||||
}
|
||||
|
||||
function showFullName()
|
||||
{
|
||||
parent::showFullName();
|
||||
if ($this->profile->isAdmin($this->group)) {
|
||||
$this->out->text(' ');
|
||||
$this->out->element('span', 'admin_indicator', _('Admin'));
|
||||
}
|
||||
}
|
||||
|
||||
function showActions()
|
||||
{
|
||||
$this->startActions();
|
||||
|
|
|
@ -331,6 +331,7 @@ class ShowgroupAction extends GroupDesignAction
|
|||
{
|
||||
$this->showMembers();
|
||||
$this->showStatistics();
|
||||
$this->showAdmins();
|
||||
$cloud = new GroupTagCloudSection($this, $this->group);
|
||||
$cloud->show();
|
||||
}
|
||||
|
@ -369,6 +370,18 @@ class ShowgroupAction extends GroupDesignAction
|
|||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show list of admins
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showAdmins()
|
||||
{
|
||||
$adminSection = new GroupAdminSection($this, $this->group);
|
||||
$adminSection->show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show some statistics
|
||||
*
|
||||
|
@ -423,3 +436,34 @@ class ShowgroupAction extends GroupDesignAction
|
|||
$this->elementEnd('div');
|
||||
}
|
||||
}
|
||||
|
||||
class GroupAdminSection extends ProfileSection
|
||||
{
|
||||
var $group;
|
||||
|
||||
function __construct($out, $group)
|
||||
{
|
||||
parent::__construct($out);
|
||||
$this->group = $group;
|
||||
}
|
||||
|
||||
function getProfiles()
|
||||
{
|
||||
return $this->group->getAdmins();
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
return _('Admins');
|
||||
}
|
||||
|
||||
function divId()
|
||||
{
|
||||
return 'group_admins';
|
||||
}
|
||||
|
||||
function moreUrl()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -874,7 +874,6 @@ class Notice extends Memcached_DataObject
|
|||
$qry .= '('.$id.', '.$this->id.', '.$source.', "'.$this->created.'") ';
|
||||
$cnt++;
|
||||
if ($cnt >= MAX_BOXCARS) {
|
||||
common_debug($qry);
|
||||
$inbox = new Notice_inbox();
|
||||
$inbox->query($qry);
|
||||
$qry = $qryhdr;
|
||||
|
@ -883,7 +882,6 @@ class Notice extends Memcached_DataObject
|
|||
}
|
||||
|
||||
if ($cnt > 0) {
|
||||
common_debug($qry);
|
||||
$inbox = new Notice_inbox();
|
||||
$inbox->query($qry);
|
||||
}
|
||||
|
|
129
classes/Session.php
Normal file
129
classes/Session.php
Normal file
|
@ -0,0 +1,129 @@
|
|||
<?php
|
||||
/**
|
||||
* Table Definition for session
|
||||
*
|
||||
* Laconica - a distributed open-source microblogging tool
|
||||
* Copyright (C) 2009, Control Yourself, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) { exit(1); }
|
||||
|
||||
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
|
||||
|
||||
class Session extends Memcached_DataObject
|
||||
{
|
||||
###START_AUTOCODE
|
||||
/* the code below is auto generated do not remove the above tag */
|
||||
|
||||
public $__table = 'session'; // table name
|
||||
public $id; // varchar(32) primary_key not_null
|
||||
public $session_data; // text()
|
||||
public $created; // datetime() not_null
|
||||
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
|
||||
|
||||
/* Static get */
|
||||
function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Session',$k,$v); }
|
||||
|
||||
/* the code above is auto generated do not remove the tag below */
|
||||
###END_AUTOCODE
|
||||
|
||||
static function logdeb($msg)
|
||||
{
|
||||
if (common_config('sessions', 'debug')) {
|
||||
common_debug("Session: " . $msg);
|
||||
}
|
||||
}
|
||||
|
||||
static function open($save_path, $session_name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static function close()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static function read($id)
|
||||
{
|
||||
self::logdeb("Fetching session '$id'");
|
||||
|
||||
$session = Session::staticGet('id', $id);
|
||||
|
||||
if (empty($session)) {
|
||||
return '';
|
||||
} else {
|
||||
return (string)$session->session_data;
|
||||
}
|
||||
}
|
||||
|
||||
static function write($id, $session_data)
|
||||
{
|
||||
self::logdeb("Writing session '$id'");
|
||||
|
||||
$session = Session::staticGet('id', $id);
|
||||
|
||||
if (empty($session)) {
|
||||
$session = new Session();
|
||||
|
||||
$session->id = $id;
|
||||
$session->session_data = $session_data;
|
||||
$session->created = common_sql_now();
|
||||
|
||||
return $session->insert();
|
||||
} else {
|
||||
$session->session_data = $session_data;
|
||||
|
||||
return $session->update();
|
||||
}
|
||||
}
|
||||
|
||||
static function destroy($id)
|
||||
{
|
||||
self::logdeb("Deleting session $id");
|
||||
|
||||
$session = Session::staticGet('id', $id);
|
||||
|
||||
if (!empty($session)) {
|
||||
return $session->delete();
|
||||
}
|
||||
}
|
||||
|
||||
static function gc($maxlifetime)
|
||||
{
|
||||
self::logdeb("garbage collection (maxlifetime = $maxlifetime)");
|
||||
|
||||
$epoch = time() - $maxlifetime;
|
||||
|
||||
$qry = 'DELETE FROM session ' .
|
||||
'WHERE modified < "'.$epoch.'"';
|
||||
|
||||
$session = new Session();
|
||||
|
||||
$result = $session->query($qry);
|
||||
|
||||
self::logdeb("garbage collection result = $result");
|
||||
}
|
||||
|
||||
static function setSaveHandler()
|
||||
{
|
||||
self::logdeb("setting save handlers");
|
||||
$result = session_set_save_handler('Session::open', 'Session::close', 'Session::read',
|
||||
'Session::write', 'Session::destroy', 'Session::gc');
|
||||
self::logdeb("save handlers result = $result");
|
||||
return $result;
|
||||
}
|
||||
}
|
|
@ -132,6 +132,13 @@ class Status_network extends DB_DataObject
|
|||
}
|
||||
} else {
|
||||
$sn = self::memGet('hostname', strtolower($servername));
|
||||
|
||||
if (empty($sn)) {
|
||||
// Try for a no-www address
|
||||
if (0 == strncasecmp($servername, 'www.', 4)) {
|
||||
$sn = self::memGet('hostname', strtolower(substr($servername, 4)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($sn)) {
|
||||
|
|
|
@ -126,6 +126,30 @@ class User_group extends Memcached_DataObject
|
|||
return $members;
|
||||
}
|
||||
|
||||
function getAdmins($offset=0, $limit=null)
|
||||
{
|
||||
$qry =
|
||||
'SELECT profile.* ' .
|
||||
'FROM profile JOIN group_member '.
|
||||
'ON profile.id = group_member.profile_id ' .
|
||||
'WHERE group_member.group_id = %d ' .
|
||||
'AND group_member.is_admin = 1 ' .
|
||||
'ORDER BY group_member.modified ASC ';
|
||||
|
||||
if ($limit != null) {
|
||||
if (common_config('db','type') == 'pgsql') {
|
||||
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
|
||||
} else {
|
||||
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
|
||||
}
|
||||
}
|
||||
|
||||
$admins = new Profile();
|
||||
|
||||
$admins->query(sprintf($qry, $this->id));
|
||||
return $admins;
|
||||
}
|
||||
|
||||
function getBlocked($offset=0, $limit=null)
|
||||
{
|
||||
$qry =
|
||||
|
|
9
classes/laconica.ini
Executable file → Normal file
9
classes/laconica.ini
Executable file → Normal file
|
@ -380,6 +380,15 @@ replied_id = 1
|
|||
notice_id = K
|
||||
profile_id = K
|
||||
|
||||
[session]
|
||||
id = 130
|
||||
session_data = 34
|
||||
created = 142
|
||||
modified = 384
|
||||
|
||||
[session__keys]
|
||||
id = K
|
||||
|
||||
[sms_carrier]
|
||||
id = 129
|
||||
name = 2
|
||||
|
|
|
@ -524,3 +524,14 @@ create table group_alias (
|
|||
index group_alias_group_id_idx (group_id)
|
||||
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table session (
|
||||
|
||||
id varchar(32) primary key comment 'session ID',
|
||||
session_data text comment 'session data',
|
||||
created datetime not null comment 'date this record was created',
|
||||
modified timestamp comment 'date this record was modified',
|
||||
|
||||
index session_modified_idx (modified)
|
||||
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
/** XMPPHP_XMLStream */
|
||||
require_once "XMPP.php";
|
||||
require_once dirname(__FILE__) . "/XMPP.php";
|
||||
|
||||
/**
|
||||
* XMPPHP Main Class
|
||||
|
|
|
@ -27,13 +27,13 @@
|
|||
*/
|
||||
|
||||
/** XMPPHP_Exception */
|
||||
require_once 'Exception.php';
|
||||
require_once dirname(__FILE__) . '/Exception.php';
|
||||
|
||||
/** XMPPHP_XMLObj */
|
||||
require_once 'XMLObj.php';
|
||||
require_once dirname(__FILE__) . '/XMLObj.php';
|
||||
|
||||
/** XMPPHP_Log */
|
||||
require_once 'Log.php';
|
||||
require_once dirname(__FILE__) . '/Log.php';
|
||||
|
||||
/**
|
||||
* XMPPHP XML Stream
|
||||
|
@ -375,7 +375,7 @@ class XMPPHP_XMLStream {
|
|||
* integer -> process for this amount of time
|
||||
*/
|
||||
|
||||
private function __process($maximum=0) {
|
||||
private function __process($maximum=5) {
|
||||
|
||||
$remaining = $maximum;
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
*/
|
||||
|
||||
/** XMPPHP_XMLStream */
|
||||
require_once "XMLStream.php";
|
||||
require_once "Roster.php";
|
||||
require_once dirname(__FILE__) . "/XMLStream.php";
|
||||
require_once dirname(__FILE__) . "/Roster.php";
|
||||
|
||||
/**
|
||||
* XMPPHP Main Class
|
||||
|
@ -208,6 +208,15 @@ class XMPPHP_XMPP extends XMPPHP_XMLStream {
|
|||
|
||||
$this->send($out);
|
||||
}
|
||||
/**
|
||||
* Send Auth request
|
||||
*
|
||||
* @param string $jid
|
||||
*/
|
||||
public function subscribe($jid) {
|
||||
$this->send("<presence type='subscribe' to='{$jid}' from='{$this->fulljid}' />");
|
||||
#$this->send("<presence type='subscribed' to='{$jid}' from='{$this->fulljid}' />");
|
||||
}
|
||||
|
||||
/**
|
||||
* Message handler
|
||||
|
|
48
index.php
48
index.php
|
@ -73,13 +73,45 @@ function handleError($error)
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
function checkMirror($action_obj)
|
||||
{
|
||||
global $config;
|
||||
|
||||
static $alwaysRW = array('session', 'remember_me');
|
||||
|
||||
if (common_config('db', 'mirror') && $action_obj->isReadOnly($args)) {
|
||||
if (is_array(common_config('db', 'mirror'))) {
|
||||
// "load balancing", ha ha
|
||||
$arr = common_config('db', 'mirror');
|
||||
$k = array_rand($arr);
|
||||
$mirror = $arr[$k];
|
||||
} else {
|
||||
$mirror = common_config('db', 'mirror');
|
||||
}
|
||||
|
||||
// We ensure that these tables always are used
|
||||
// on the master DB
|
||||
|
||||
$config['db']['database_rw'] = $config['db']['database'];
|
||||
$config['db']['ini_rw'] = INSTALLDIR.'/classes/laconica.ini';
|
||||
|
||||
foreach ($alwaysRW as $table) {
|
||||
$config['db']['table_'.$table] = 'rw';
|
||||
}
|
||||
|
||||
// everyone else uses the mirror
|
||||
|
||||
$config['db']['database'] = $mirror;
|
||||
}
|
||||
}
|
||||
|
||||
function main()
|
||||
{
|
||||
// quick check for fancy URL auto-detection support in installer.
|
||||
if (isset($_SERVER['REDIRECT_URL']) && ((dirname($_SERVER['REQUEST_URI']) . '/check-fancy') === $_SERVER['REDIRECT_URL'])) {
|
||||
die("Fancy URL support detection succeeded. We suggest you enable this to get fancy (pretty) URLs.");
|
||||
}
|
||||
global $user, $action, $config;
|
||||
global $user, $action;
|
||||
|
||||
Snapshot::check();
|
||||
|
||||
|
@ -146,19 +178,7 @@ function main()
|
|||
} else {
|
||||
$action_obj = new $action_class();
|
||||
|
||||
// XXX: find somewhere for this little block to live
|
||||
|
||||
if (common_config('db', 'mirror') && $action_obj->isReadOnly($args)) {
|
||||
if (is_array(common_config('db', 'mirror'))) {
|
||||
// "load balancing", ha ha
|
||||
$arr = common_config('db', 'mirror');
|
||||
$k = array_rand($arr);
|
||||
$mirror = $arr[$k];
|
||||
} else {
|
||||
$mirror = common_config('db', 'mirror');
|
||||
}
|
||||
$config['db']['database'] = $mirror;
|
||||
}
|
||||
checkMirror($action_obj);
|
||||
|
||||
try {
|
||||
if ($action_obj->prepare($args)) {
|
||||
|
|
|
@ -254,6 +254,9 @@ $config =
|
|||
'oohembed' => array('endpoint' => 'http://oohembed.com/oohembed/'),
|
||||
'search' =>
|
||||
array('type' => 'fulltext'),
|
||||
'sessions' =>
|
||||
array('handle' => false, // whether to handle sessions ourselves
|
||||
'debug' => false), // debugging output for sessions
|
||||
);
|
||||
|
||||
$config['db'] = &PEAR::getStaticProperty('DB_DataObject','options');
|
||||
|
|
|
@ -23,6 +23,13 @@ if (!defined('LACONICA')) {
|
|||
|
||||
class Daemon
|
||||
{
|
||||
var $daemonize = true;
|
||||
|
||||
function __construct($daemonize = true)
|
||||
{
|
||||
$this->daemonize = $daemonize;
|
||||
}
|
||||
|
||||
function name()
|
||||
{
|
||||
return null;
|
||||
|
@ -129,13 +136,17 @@ class Daemon
|
|||
common_log(LOG_INFO, $this->name() . ' already running. Exiting.');
|
||||
exit(0);
|
||||
}
|
||||
if ($this->background()) {
|
||||
|
||||
if ($this->daemonize) {
|
||||
common_log(LOG_INFO, 'Backgrounding daemon "'.$this->name().'"');
|
||||
$this->background();
|
||||
}
|
||||
|
||||
$this->writePidFile();
|
||||
$this->changeUser();
|
||||
$this->run();
|
||||
$this->clearPidFile();
|
||||
}
|
||||
}
|
||||
|
||||
function run()
|
||||
{
|
||||
|
|
|
@ -27,11 +27,12 @@ require_once(INSTALLDIR.'/classes/Notice.php');
|
|||
|
||||
class QueueHandler extends Daemon
|
||||
{
|
||||
|
||||
var $_id = 'generic';
|
||||
|
||||
function QueueHandler($id=null)
|
||||
function __construct($id=null, $daemonize=true)
|
||||
{
|
||||
parent::__construct($daemonize);
|
||||
|
||||
if ($id) {
|
||||
$this->set_id($id);
|
||||
}
|
||||
|
|
92
lib/util.php
92
lib/util.php
|
@ -139,8 +139,23 @@ function common_have_session()
|
|||
|
||||
function common_ensure_session()
|
||||
{
|
||||
$c = null;
|
||||
if (array_key_exists(session_name, $_COOKIE)) {
|
||||
$c = $_COOKIE[session_name()];
|
||||
}
|
||||
if (!common_have_session()) {
|
||||
if (common_config('sessions', 'handle')) {
|
||||
common_log(LOG_INFO, "Using our own session handler");
|
||||
Session::setSaveHandler();
|
||||
}
|
||||
@session_start();
|
||||
if (!isset($_SESSION['started'])) {
|
||||
$_SESSION['started'] = time();
|
||||
if (!empty($c)) {
|
||||
common_log(LOG_WARNING, 'Session cookie "' . $_COOKIE[session_name()] . '" ' .
|
||||
' is set but started value is null');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -485,17 +500,19 @@ function common_linkify($url) {
|
|||
// It comes in special'd, so we unspecial it before passing to the stringifying
|
||||
// functions
|
||||
$url = htmlspecialchars_decode($url);
|
||||
$display = File_redirection::_canonUrl($url);
|
||||
|
||||
$canon = File_redirection::_canonUrl($url);
|
||||
|
||||
$longurl_data = File_redirection::where($url);
|
||||
if (is_array($longurl_data)) {
|
||||
$longurl = $longurl_data['url'];
|
||||
} elseif (is_string($longurl_data)) {
|
||||
$longurl = $longurl_data;
|
||||
} else {
|
||||
die('impossible to linkify');
|
||||
throw new ServerException("Can't linkify url '$url'");
|
||||
}
|
||||
|
||||
$attrs = array('href' => $longurl, 'rel' => 'external');
|
||||
$attrs = array('href' => $canon, 'rel' => 'external');
|
||||
|
||||
$is_attachment = false;
|
||||
$attachment_id = null;
|
||||
|
@ -549,7 +566,7 @@ function common_linkify($url) {
|
|||
$attrs['id'] = "attachment-{$attachment_id}";
|
||||
}
|
||||
|
||||
return XMLStringer::estring('a', $attrs, $display);
|
||||
return XMLStringer::estring('a', $attrs, $url);
|
||||
}
|
||||
|
||||
function common_shorten_links($text)
|
||||
|
@ -817,7 +834,12 @@ function common_date_iso8601($dt)
|
|||
|
||||
function common_sql_now()
|
||||
{
|
||||
return strftime('%Y-%m-%d %H:%M:%S', time());
|
||||
return common_sql_date(time());
|
||||
}
|
||||
|
||||
function common_sql_date($datetime)
|
||||
{
|
||||
return strftime('%Y-%m-%d %H:%M:%S', $datetime);
|
||||
}
|
||||
|
||||
function common_redirect($url, $code=307)
|
||||
|
@ -1082,15 +1104,20 @@ function common_ensure_syslog()
|
|||
}
|
||||
}
|
||||
|
||||
function common_log_line($priority, $msg)
|
||||
{
|
||||
static $syslog_priorities = array('LOG_EMERG', 'LOG_ALERT', 'LOG_CRIT', 'LOG_ERR',
|
||||
'LOG_WARNING', 'LOG_NOTICE', 'LOG_INFO', 'LOG_DEBUG');
|
||||
return date('Y-m-d H:i:s') . ' ' . $syslog_priorities[$priority] . ': ' . $msg . "\n";
|
||||
}
|
||||
|
||||
function common_log($priority, $msg, $filename=null)
|
||||
{
|
||||
$logfile = common_config('site', 'logfile');
|
||||
if ($logfile) {
|
||||
$log = fopen($logfile, "a");
|
||||
if ($log) {
|
||||
static $syslog_priorities = array('LOG_EMERG', 'LOG_ALERT', 'LOG_CRIT', 'LOG_ERR',
|
||||
'LOG_WARNING', 'LOG_NOTICE', 'LOG_INFO', 'LOG_DEBUG');
|
||||
$output = date('Y-m-d H:i:s') . ' ' . $syslog_priorities[$priority] . ': ' . $msg . "\n";
|
||||
$output = common_log_line($priority, $msg);
|
||||
fwrite($log, $output);
|
||||
fclose($log);
|
||||
}
|
||||
|
@ -1321,18 +1348,39 @@ function common_canonical_sms($sms)
|
|||
function common_error_handler($errno, $errstr, $errfile, $errline, $errcontext)
|
||||
{
|
||||
switch ($errno) {
|
||||
|
||||
case E_ERROR:
|
||||
case E_COMPILE_ERROR:
|
||||
case E_CORE_ERROR:
|
||||
case E_USER_ERROR:
|
||||
common_log(LOG_ERR, "[$errno] $errstr ($errfile:$errline)");
|
||||
exit(1);
|
||||
case E_PARSE:
|
||||
case E_RECOVERABLE_ERROR:
|
||||
common_log(LOG_ERR, "[$errno] $errstr ($errfile:$errline) [ABORT]");
|
||||
die();
|
||||
break;
|
||||
|
||||
case E_WARNING:
|
||||
case E_COMPILE_WARNING:
|
||||
case E_CORE_WARNING:
|
||||
case E_USER_WARNING:
|
||||
common_log(LOG_WARNING, "[$errno] $errstr ($errfile:$errline)");
|
||||
break;
|
||||
|
||||
case E_NOTICE:
|
||||
case E_USER_NOTICE:
|
||||
common_log(LOG_NOTICE, "[$errno] $errstr ($errfile:$errline)");
|
||||
break;
|
||||
|
||||
case E_STRICT:
|
||||
case E_DEPRECATED:
|
||||
case E_USER_DEPRECATED:
|
||||
// XXX: config variable to log this stuff, too
|
||||
break;
|
||||
|
||||
default:
|
||||
common_log(LOG_ERR, "[$errno] $errstr ($errfile:$errline) [UNKNOWN LEVEL, die()'ing]");
|
||||
die();
|
||||
break;
|
||||
}
|
||||
|
||||
// FIXME: show error page if we're on the Web
|
||||
|
@ -1471,3 +1519,27 @@ function common_shorten_url($long_url)
|
|||
|
||||
return $short_url;
|
||||
}
|
||||
|
||||
function common_client_ip()
|
||||
{
|
||||
if (!isset($_SERVER) || !array_key_exists('REQUEST_METHOD', $_SERVER)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($_SERVER['HTTP_X_FORWARDED_FOR']) {
|
||||
if ($_SERVER['HTTP_CLIENT_IP']) {
|
||||
$proxy = $_SERVER['HTTP_CLIENT_IP'];
|
||||
} else {
|
||||
$proxy = $_SERVER['REMOTE_ADDR'];
|
||||
}
|
||||
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||
} else {
|
||||
if ($_SERVER['HTTP_CLIENT_IP']) {
|
||||
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||||
} else {
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
}
|
||||
}
|
||||
|
||||
return array($ip, $proxy);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,14 @@ if (isset($longoptions)) {
|
|||
|
||||
$parser = new Console_Getopt();
|
||||
|
||||
list($options, $args) = $parser->getopt($argv, $shortoptions, $longoptions);
|
||||
$result = $parser->getopt($argv, $shortoptions, $longoptions);
|
||||
|
||||
if (PEAR::isError($result)) {
|
||||
print $result->getMessage()."\n";
|
||||
exit(1);
|
||||
} else {
|
||||
list($options, $args) = $result;
|
||||
}
|
||||
|
||||
function show_help()
|
||||
{
|
||||
|
@ -115,24 +122,53 @@ require_once INSTALLDIR . '/lib/common.php';
|
|||
|
||||
set_error_handler('common_error_handler');
|
||||
|
||||
function have_option($str)
|
||||
function _make_matches($opt, $alt)
|
||||
{
|
||||
$matches = array();
|
||||
|
||||
if (strlen($opt) > 1 && 0 != strncmp($opt, '--', 2)) {
|
||||
$matches[] = '--'.$opt;
|
||||
} else {
|
||||
$matches[] = $opt;
|
||||
}
|
||||
|
||||
if (!empty($alt)) {
|
||||
if (strlen($alt) > 1 && 0 != strncmp($alt, '--', 2)) {
|
||||
$matches[] = '--'.$alt;
|
||||
} else {
|
||||
$matches[] = $alt;
|
||||
}
|
||||
}
|
||||
|
||||
return $matches;
|
||||
}
|
||||
|
||||
function have_option($opt, $alt=null)
|
||||
{
|
||||
global $options;
|
||||
|
||||
$matches = _make_matches($opt, $alt);
|
||||
|
||||
foreach ($options as $option) {
|
||||
if ($option[0] == $str) {
|
||||
if (in_array($option[0], $matches)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function get_option_value($str)
|
||||
function get_option_value($opt, $alt=null)
|
||||
{
|
||||
global $options;
|
||||
|
||||
$matches = _make_matches($opt, $alt);
|
||||
|
||||
foreach ($options as $option) {
|
||||
if ($option[0] == $str) {
|
||||
if (in_array($option[0], $matches)) {
|
||||
return $option[1];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
|
@ -24,22 +24,17 @@ require_once INSTALLDIR.'/scripts/commandline.inc';
|
|||
|
||||
common_log(LOG_INFO, 'Fixing up conversations.');
|
||||
|
||||
$nid = new Notice();
|
||||
$nid->query('select id, reply_to from notice where conversation is null');
|
||||
|
||||
while ($nid->fetch()) {
|
||||
|
||||
$cid = null;
|
||||
|
||||
$notice = new Notice();
|
||||
$notice->whereAdd('conversation is null');
|
||||
$notice->orderBy('id');
|
||||
|
||||
$cnt = $notice->find();
|
||||
|
||||
print "Found $cnt notices.\n";
|
||||
|
||||
while ($notice->fetch()) {
|
||||
|
||||
print "$notice->id =>";
|
||||
|
||||
$orig = clone($notice);
|
||||
|
||||
if (empty($notice->reply_to)) {
|
||||
$notice->conversation = $notice->id;
|
||||
if (empty($nid->reply_to)) {
|
||||
$cid = $nid->id;
|
||||
} else {
|
||||
$reply = Notice::staticGet('id', $notice->reply_to);
|
||||
|
||||
|
@ -52,6 +47,9 @@ while ($notice->fetch()) {
|
|||
} else {
|
||||
$notice->conversation = $reply->conversation;
|
||||
}
|
||||
|
||||
unset($reply);
|
||||
$reply = null;
|
||||
}
|
||||
|
||||
print "$notice->conversation";
|
||||
|
@ -63,5 +61,10 @@ while ($notice->fetch()) {
|
|||
continue;
|
||||
}
|
||||
|
||||
$notice = null;
|
||||
$orig = null;
|
||||
unset($notice);
|
||||
unset($orig);
|
||||
|
||||
print ".\n";
|
||||
}
|
||||
|
|
|
@ -25,9 +25,14 @@ define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
|
|||
define('MAXCHILDREN', 2);
|
||||
define('POLL_INTERVAL', 60); // in seconds
|
||||
|
||||
$shortoptions = 'i::';
|
||||
$longoptions = array('id::');
|
||||
|
||||
$helptext = <<<END_OF_TRIM_HELP
|
||||
Batch script for retrieving Twitter messages from foreign service.
|
||||
|
||||
-i --id Identity (default 'generic')
|
||||
|
||||
END_OF_TRIM_HELP;
|
||||
|
||||
require_once INSTALLDIR.'/scripts/commandline.inc';
|
||||
|
@ -64,7 +69,7 @@ class TwitterStatusFetcher extends Daemon
|
|||
|
||||
function name()
|
||||
{
|
||||
return ('twitterstatusfetcher.generic');
|
||||
return ('twitterstatusfetcher.'.$this->_id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -625,6 +630,16 @@ class TwitterStatusFetcher extends Daemon
|
|||
|
||||
declare(ticks = 1);
|
||||
|
||||
$fetcher = new TwitterStatusFetcher();
|
||||
if (have_option('i')) {
|
||||
$id = get_option_value('i');
|
||||
} else if (have_option('--id')) {
|
||||
$id = get_option_value('--id');
|
||||
} else if (count($args) > 0) {
|
||||
$id = $args[0];
|
||||
} else {
|
||||
$id = null;
|
||||
}
|
||||
|
||||
$fetcher = new TwitterStatusFetcher($id);
|
||||
$fetcher->runOnce();
|
||||
|
||||
|
|
|
@ -20,13 +20,14 @@
|
|||
|
||||
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
|
||||
|
||||
$shortoptions = 'i::';
|
||||
$longoptions = array('id::');
|
||||
$shortoptions = 'fi::';
|
||||
$longoptions = array('id::', 'foreground');
|
||||
|
||||
$helptext = <<<END_OF_XMPP_HELP
|
||||
Daemon script for receiving new notices from Jabber users.
|
||||
|
||||
-i --id Identity (default none)
|
||||
-f --foreground Stay in the foreground (default background)
|
||||
|
||||
END_OF_XMPP_HELP;
|
||||
|
||||
|
@ -42,8 +43,10 @@ require_once INSTALLDIR . '/lib/daemon.php';
|
|||
|
||||
class XMPPDaemon extends Daemon
|
||||
{
|
||||
function XMPPDaemon($resource=null)
|
||||
function __construct($resource=null, $daemonize=true)
|
||||
{
|
||||
parent::__construct($daemonize);
|
||||
|
||||
static $attrs = array('server', 'port', 'user', 'password', 'host');
|
||||
|
||||
foreach ($attrs as $attr)
|
||||
|
@ -62,7 +65,6 @@ class XMPPDaemon extends Daemon
|
|||
|
||||
function connect()
|
||||
{
|
||||
|
||||
$connect_to = ($this->host) ? $this->host : $this->server;
|
||||
|
||||
$this->log(LOG_INFO, "Connecting to $connect_to on port $this->port");
|
||||
|
@ -73,10 +75,17 @@ class XMPPDaemon extends Daemon
|
|||
return false;
|
||||
}
|
||||
|
||||
$this->log(LOG_INFO, "Connected");
|
||||
|
||||
$this->conn->setReconnectTimeout(600);
|
||||
|
||||
$this->log(LOG_INFO, "Sending initial presence.");
|
||||
|
||||
jabber_send_presence("Send me a message to post a notice", 'available',
|
||||
null, 'available', 100);
|
||||
|
||||
$this->log(LOG_INFO, "Done connecting.");
|
||||
|
||||
return !$this->conn->isDisconnected();
|
||||
}
|
||||
|
||||
|
@ -89,17 +98,23 @@ class XMPPDaemon extends Daemon
|
|||
{
|
||||
if ($this->connect()) {
|
||||
|
||||
$this->log(LOG_DEBUG, "Initializing stanza handlers.");
|
||||
|
||||
$this->conn->addEventHandler('message', 'handle_message', $this);
|
||||
$this->conn->addEventHandler('presence', 'handle_presence', $this);
|
||||
$this->conn->addEventHandler('reconnect', 'handle_reconnect', $this);
|
||||
|
||||
$this->log(LOG_DEBUG, "Beginning processing loop.");
|
||||
|
||||
$this->conn->process();
|
||||
}
|
||||
}
|
||||
|
||||
function handle_reconnect(&$pl)
|
||||
{
|
||||
$this->log(LOG_DEBUG, "Got reconnection callback.");
|
||||
$this->conn->processUntil('session_start');
|
||||
$this->log(LOG_DEBUG, "Sending reconnection presence.");
|
||||
$this->conn->presence('Send me a message to post a notice', 'available', null, 'available', 100);
|
||||
}
|
||||
|
||||
|
@ -111,21 +126,27 @@ class XMPPDaemon extends Daemon
|
|||
|
||||
function handle_message(&$pl)
|
||||
{
|
||||
$from = jabber_normalize_jid($pl['from']);
|
||||
|
||||
if ($pl['type'] != 'chat') {
|
||||
return;
|
||||
}
|
||||
if (mb_strlen($pl['body']) == 0) {
|
||||
$this->log(LOG_WARNING, "Ignoring message of type ".$pl['type']." from $from.");
|
||||
return;
|
||||
}
|
||||
|
||||
$from = jabber_normalize_jid($pl['from']);
|
||||
if (mb_strlen($pl['body']) == 0) {
|
||||
$this->log(LOG_WARNING, "Ignoring message with empty body from $from.");
|
||||
return;
|
||||
}
|
||||
|
||||
# Forwarded from another daemon (probably a broadcaster) for
|
||||
# us to handle
|
||||
|
||||
if ($this->is_self($from)) {
|
||||
$this->log(LOG_INFO, "Got forwarded notice from self ($from).");
|
||||
$from = $this->get_ofrom($pl);
|
||||
$this->log(LOG_INFO, "Originally sent by $from.");
|
||||
if (is_null($from) || $this->is_self($from)) {
|
||||
$this->log(LOG_INFO, "Ignoring notice originally sent by $from.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -140,6 +161,7 @@ class XMPPDaemon extends Daemon
|
|||
return;
|
||||
}
|
||||
if ($this->handle_command($user, $pl['body'])) {
|
||||
$this->log(LOG_INFO, "Command messag by $from handled.");
|
||||
return;
|
||||
} else if ($this->is_autoreply($pl['body'])) {
|
||||
$this->log(LOG_INFO, 'Ignoring auto reply from ' . $from);
|
||||
|
@ -148,12 +170,20 @@ class XMPPDaemon extends Daemon
|
|||
$this->log(LOG_INFO, 'Ignoring OTR from ' . $from);
|
||||
return;
|
||||
} else if ($this->is_direct($pl['body'])) {
|
||||
$this->log(LOG_INFO, 'Got a direct message ' . $from);
|
||||
|
||||
preg_match_all('/d[\ ]*([a-z0-9]{1,64})/', $pl['body'], $to);
|
||||
|
||||
$to = preg_replace('/^d([\ ])*/', '', $to[0][0]);
|
||||
$body = preg_replace('/d[\ ]*('. $to .')[\ ]*/', '', $pl['body']);
|
||||
|
||||
$this->log(LOG_INFO, 'Direct message from '. $user->nickname . ' to ' . $to);
|
||||
|
||||
$this->add_direct($user, $body, $to, $from);
|
||||
} else {
|
||||
|
||||
$this->log(LOG_INFO, 'Posting a notice from ' . $user->nickname);
|
||||
|
||||
$this->add_notice($user, $pl);
|
||||
}
|
||||
|
||||
|
@ -261,6 +291,7 @@ class XMPPDaemon extends Daemon
|
|||
$notice = Notice::saveNew($user->id, $content_shortened, 'xmpp');
|
||||
if (is_string($notice)) {
|
||||
$this->log(LOG_ERR, $notice);
|
||||
$this->from_site($user->jabber, $notice);
|
||||
return;
|
||||
}
|
||||
common_broadcast_notice($notice);
|
||||
|
@ -307,7 +338,14 @@ class XMPPDaemon extends Daemon
|
|||
|
||||
function log($level, $msg)
|
||||
{
|
||||
common_log($level, 'XMPPDaemon('.$this->resource.'): '.$msg);
|
||||
$text = 'XMPPDaemon('.$this->resource.'): '.$msg;
|
||||
common_log($level, $text);
|
||||
if (!$this->daemonize)
|
||||
{
|
||||
$line = common_log_line($level, $text);
|
||||
echo $line;
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
|
||||
function subscribed($to)
|
||||
|
@ -323,16 +361,16 @@ if (common_config('xmpp','enabled')==false) {
|
|||
exit();
|
||||
}
|
||||
|
||||
if (have_option('i')) {
|
||||
$id = get_option_value('i');
|
||||
} else if (have_option('--id')) {
|
||||
$id = get_option_value('--id');
|
||||
if (have_option('i', 'id')) {
|
||||
$id = get_option_value('i', 'id');
|
||||
} else if (count($args) > 0) {
|
||||
$id = $args[0];
|
||||
} else {
|
||||
$id = null;
|
||||
}
|
||||
|
||||
$daemon = new XMPPDaemon($id);
|
||||
$foreground = have_option('f', 'foreground');
|
||||
|
||||
$daemon = new XMPPDaemon($id, !$foreground);
|
||||
|
||||
$daemon->runOnce();
|
||||
|
|
|
@ -273,7 +273,6 @@ clear:both;
|
|||
margin-bottom:18px;
|
||||
}
|
||||
|
||||
|
||||
#anon_notice {
|
||||
float:left;
|
||||
width:43.2%;
|
||||
|
@ -288,7 +287,6 @@ font-size:1.1em;
|
|||
font-weight:bold;
|
||||
}
|
||||
|
||||
|
||||
#footer {
|
||||
float:left;
|
||||
width:64%;
|
||||
|
@ -600,7 +598,6 @@ display:none;
|
|||
}
|
||||
/* entity_profile */
|
||||
|
||||
|
||||
/*entity_actions*/
|
||||
.entity_actions {
|
||||
float:right;
|
||||
|
@ -729,7 +726,6 @@ margin-bottom:0;
|
|||
min-height:60px;
|
||||
}
|
||||
|
||||
|
||||
.profile .form_group_join legend,
|
||||
.profile .form_group_leave legend,
|
||||
.profile .form_user_subscribe legend,
|
||||
|
@ -764,13 +760,11 @@ display:inline;
|
|||
margin-right:11px;
|
||||
}
|
||||
|
||||
|
||||
.profile .entity_profile .form_subscription_edit label {
|
||||
font-weight:normal;
|
||||
margin-right:11px;
|
||||
}
|
||||
|
||||
|
||||
/* NOTICE */
|
||||
.notice,
|
||||
.profile {
|
||||
|
@ -793,7 +787,6 @@ width:95%;
|
|||
float:left;
|
||||
}
|
||||
|
||||
|
||||
/* NOTICES */
|
||||
#notices_primary {
|
||||
float:left;
|
||||
|
@ -965,7 +958,6 @@ border:0;
|
|||
padding:0;
|
||||
}
|
||||
|
||||
|
||||
.notice .attachment {
|
||||
position:relative;
|
||||
padding-left:16px;
|
||||
|
@ -1062,7 +1054,6 @@ margin-bottom:18px;
|
|||
padding-left:20px;
|
||||
}
|
||||
|
||||
|
||||
#filter_tags {
|
||||
margin-bottom:11px;
|
||||
float:left;
|
||||
|
@ -1108,8 +1099,6 @@ top:3px;
|
|||
left:3px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.pagination {
|
||||
float:left;
|
||||
clear:both;
|
||||
|
@ -1155,7 +1144,6 @@ padding-right:30px;
|
|||
}
|
||||
/* END: NOTICE */
|
||||
|
||||
|
||||
.hentry .entry-content p {
|
||||
margin-bottom:18px;
|
||||
}
|
||||
|
@ -1172,7 +1160,6 @@ margin-bottom:18px;
|
|||
margin-left:18px;
|
||||
}
|
||||
|
||||
|
||||
/* TOP_POSTERS */
|
||||
.section tbody td {
|
||||
padding-right:18px;
|
||||
|
@ -1200,7 +1187,6 @@ margin-right:0;
|
|||
display:none;
|
||||
}
|
||||
|
||||
|
||||
/* tagcloud */
|
||||
.tag-cloud {
|
||||
list-style-type:none;
|
||||
|
@ -1317,3 +1303,6 @@ display:none;
|
|||
.guide {
|
||||
clear:both;
|
||||
}
|
||||
.admin_indicator {
|
||||
font-style:italic;
|
||||
}
|
Loading…
Reference in New Issue
Block a user