2008-05-20 14:05:35 +01:00
< ? php
2008-05-20 20:14:12 +01:00
/*
2008-05-20 14:05:35 +01:00
* Laconica - a distributed open - source microblogging tool
* Copyright ( C ) 2008 , Controlez - Vous , Inc .
2008-05-20 20:14:12 +01:00
*
2008-05-20 14:05:35 +01:00
* 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 .
2008-05-20 20:14:12 +01:00
*
2008-05-20 14:05:35 +01:00
* 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 .
2008-05-20 20:14:12 +01:00
*
2008-05-20 14:05:35 +01:00
* 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 />.
*/
2009-01-13 16:44:09 +00:00
/* XXX: break up into separate modules (HTTP, user, files) */
2008-05-20 14:05:35 +01:00
2008-12-21 00:30:16 +00:00
// Show a server error
2008-05-20 14:05:35 +01:00
2008-12-23 19:33:23 +00:00
function common_server_error ( $msg , $code = 500 )
{
2008-12-21 00:30:16 +00:00
static $status = array ( 500 => 'Internal Server Error' ,
501 => 'Not Implemented' ,
502 => 'Bad Gateway' ,
503 => 'Service Unavailable' ,
504 => 'Gateway Timeout' ,
505 => 'HTTP Version Not Supported' );
if ( ! array_key_exists ( $code , $status )) {
$code = 500 ;
}
2008-06-06 17:04:37 +01:00
2008-12-21 00:30:16 +00:00
$status_string = $status [ $code ];
2008-06-06 17:04:37 +01:00
2008-12-21 00:30:16 +00:00
header ( 'HTTP/1.1 ' . $code . ' ' . $status_string );
header ( 'Content-type: text/plain' );
2008-05-20 14:05:35 +01:00
2008-12-21 00:30:16 +00:00
print $msg ;
print " \n " ;
exit ();
2008-05-20 14:05:35 +01:00
}
2008-12-21 00:30:16 +00:00
// Show a user error
2008-12-23 19:33:23 +00:00
function common_user_error ( $msg , $code = 400 )
{
2008-12-21 00:30:16 +00:00
static $status = array ( 400 => 'Bad Request' ,
401 => 'Unauthorized' ,
402 => 'Payment Required' ,
403 => 'Forbidden' ,
404 => 'Not Found' ,
405 => 'Method Not Allowed' ,
406 => 'Not Acceptable' ,
407 => 'Proxy Authentication Required' ,
408 => 'Request Timeout' ,
409 => 'Conflict' ,
410 => 'Gone' ,
411 => 'Length Required' ,
412 => 'Precondition Failed' ,
413 => 'Request Entity Too Large' ,
414 => 'Request-URI Too Long' ,
415 => 'Unsupported Media Type' ,
416 => 'Requested Range Not Satisfiable' ,
417 => 'Expectation Failed' );
if ( ! array_key_exists ( $code , $status )) {
$code = 400 ;
}
$status_string = $status [ $code ];
header ( 'HTTP/1.1 ' . $code . ' ' . $status_string );
common_show_header ( 'Error' );
common_element ( 'div' , array ( 'class' => 'error' ), $msg );
common_show_footer ();
2008-05-20 14:05:35 +01:00
}
2008-12-23 19:33:23 +00:00
function common_init_locale ( $language = null )
{
2008-12-04 20:34:33 +00:00
if ( ! $language ) {
$language = common_language ();
}
putenv ( 'LANGUAGE=' . $language );
putenv ( 'LANG=' . $language );
return setlocale ( LC_ALL , $language . " .utf8 " ,
2008-12-21 00:30:16 +00:00
$language . " .UTF8 " ,
$language . " .utf-8 " ,
$language . " .UTF-8 " ,
$language );
2008-12-04 20:34:33 +00:00
}
2008-12-23 19:33:23 +00:00
function common_init_language ()
{
2008-12-21 00:30:16 +00:00
mb_internal_encoding ( 'UTF-8' );
$language = common_language ();
// So we don't have to make people install the gettext locales
$locale_set = common_init_locale ( $language );
bindtextdomain ( " laconica " , common_config ( 'site' , 'locale_path' ));
bind_textdomain_codeset ( " laconica " , " UTF-8 " );
textdomain ( " laconica " );
setlocale ( LC_CTYPE , 'C' );
if ( ! $locale_set ) {
common_log ( LOG_INFO , 'Language requested:' . $language . ' - locale could not be set:' , __FILE__ );
}
2008-08-06 05:04:33 +01:00
}
2008-12-23 19:33:23 +00:00
function common_show_header ( $pagetitle , $callable = null , $data = null , $headercall = null )
{
2008-12-03 03:27:43 +00:00
2008-12-21 00:30:16 +00:00
global $config , $xw ;
2008-12-08 05:50:23 +00:00
global $action ; /* XXX: kind of cheating here. */
2008-08-06 05:04:33 +01:00
2008-12-21 00:30:16 +00:00
common_start_html ();
common_element_start ( 'head' );
common_element ( 'title' , null ,
$pagetitle . " - " . $config [ 'site' ][ 'name' ]);
common_element ( 'link' , array ( 'rel' => 'stylesheet' ,
'type' => 'text/css' ,
'href' => theme_path ( 'display.css' ) . '?version=' . LACONICA_VERSION ,
'media' => 'screen, projection, tv' ));
foreach ( array ( 6 , 7 ) as $ver ) {
if ( file_exists ( theme_file ( 'ie' . $ver . '.css' ))) {
// Yes, IE people should be put in jail.
$xw -> writeComment ( '[if lte IE ' . $ver . ']><link rel="stylesheet" type="text/css" ' .
'href="' . theme_path ( 'ie' . $ver . '.css' ) . '?version=' . LACONICA_VERSION . '" /><![endif]' );
}
}
common_element ( 'script' , array ( 'type' => 'text/javascript' ,
'src' => common_path ( 'js/jquery.min.js' )),
' ' );
common_element ( 'script' , array ( 'type' => 'text/javascript' ,
'src' => common_path ( 'js/jquery.form.js' )),
' ' );
common_element ( 'script' , array ( 'type' => 'text/javascript' ,
'src' => common_path ( 'js/xbImportNode.js' )),
' ' );
common_element ( 'script' , array ( 'type' => 'text/javascript' ,
'src' => common_path ( 'js/util.js?version=' . LACONICA_VERSION )),
' ' );
common_element ( 'link' , array ( 'rel' => 'search' , 'type' => 'application/opensearchdescription+xml' ,
'href' => common_local_url ( 'opensearch' , array ( 'type' => 'people' )),
'title' => common_config ( 'site' , 'name' ) . ' People Search' ));
common_element ( 'link' , array ( 'rel' => 'search' , 'type' => 'application/opensearchdescription+xml' ,
'href' => common_local_url ( 'opensearch' , array ( 'type' => 'notice' )),
'title' => common_config ( 'site' , 'name' ) . ' Notice Search' ));
if ( $callable ) {
if ( $data ) {
call_user_func ( $callable , $data );
} else {
call_user_func ( $callable );
}
}
common_element_end ( 'head' );
common_element_start ( 'body' , $action );
common_element_start ( 'div' , array ( 'id' => 'wrap' ));
common_element_start ( 'div' , array ( 'id' => 'header' ));
common_nav_menu ();
if (( isset ( $config [ 'site' ][ 'logo' ]) && is_string ( $config [ 'site' ][ 'logo' ]) && ( strlen ( $config [ 'site' ][ 'logo' ]) > 0 ))
|| file_exists ( theme_file ( 'logo.png' )))
{
common_element_start ( 'a' , array ( 'href' => common_local_url ( 'public' )));
common_element ( 'img' , array ( 'src' => isset ( $config [ 'site' ][ 'logo' ]) ?
( $config [ 'site' ][ 'logo' ]) : theme_path ( 'logo.png' ),
'alt' => $config [ 'site' ][ 'name' ],
'id' => 'logo' ));
common_element_end ( 'a' );
} else {
common_element_start ( 'p' , array ( 'id' => 'branding' ));
common_element ( 'a' , array ( 'href' => common_local_url ( 'public' )),
$config [ 'site' ][ 'name' ]);
common_element_end ( 'p' );
}
common_element ( 'h1' , 'pagetitle' , $pagetitle );
if ( $headercall ) {
if ( $data ) {
call_user_func ( $headercall , $data );
} else {
call_user_func ( $headercall );
}
}
common_element_end ( 'div' );
common_element_start ( 'div' , array ( 'id' => 'content' ));
}
2008-12-23 19:33:23 +00:00
function common_show_footer ()
{
2008-12-21 00:30:16 +00:00
global $xw , $config ;
common_element_end ( 'div' ); // content div
common_foot_menu ();
common_element_start ( 'div' , array ( 'id' => 'footer' ));
common_element_start ( 'div' , 'laconica' );
if ( common_config ( 'site' , 'broughtby' )) {
$instr = _ ( '**%%site.name%%** is a microblogging service brought to you by [%%site.broughtby%%](%%site.broughtbyurl%%). ' );
} else {
$instr = _ ( '**%%site.name%%** is a microblogging service. ' );
}
$instr .= sprintf ( _ ( 'It runs the [Laconica](http://laconi.ca/) microblogging software, version %s, available under the [GNU Affero General Public License](http://www.fsf.org/licensing/licenses/agpl-3.0.html).' ), LACONICA_VERSION );
2008-07-01 18:56:11 +01:00
$output = common_markup_to_html ( $instr );
common_raw ( $output );
2008-12-21 00:30:16 +00:00
common_element_end ( 'div' );
common_element ( 'img' , array ( 'id' => 'cc' ,
'src' => $config [ 'license' ][ 'image' ],
'alt' => $config [ 'license' ][ 'title' ]));
common_element_start ( 'p' );
common_text ( _ ( 'Unless otherwise specified, contents of this site are copyright by the contributors and available under the ' ));
common_element ( 'a' , array ( 'class' => 'license' ,
'rel' => 'license' ,
'href' => $config [ 'license' ][ 'url' ]),
$config [ 'license' ][ 'title' ]);
common_text ( _ ( '. Contributors should be attributed by full name or nickname.' ));
common_element_end ( 'p' );
common_element_end ( 'div' );
common_element_end ( 'div' );
common_element_end ( 'body' );
common_element_end ( 'html' );
common_end_xml ();
2008-05-20 14:05:35 +01:00
}
2008-12-23 19:33:23 +00:00
function common_nav_menu ()
{
2008-12-21 00:30:16 +00:00
$user = common_current_user ();
common_element_start ( 'ul' , array ( 'id' => 'nav' ));
if ( $user ) {
common_menu_item ( common_local_url ( 'all' , array ( 'nickname' => $user -> nickname )),
_ ( 'Home' ));
}
common_menu_item ( common_local_url ( 'peoplesearch' ), _ ( 'Search' ));
if ( $user ) {
common_menu_item ( common_local_url ( 'profilesettings' ),
_ ( 'Settings' ));
common_menu_item ( common_local_url ( 'invite' ),
_ ( 'Invite' ));
common_menu_item ( common_local_url ( 'logout' ),
_ ( 'Logout' ));
} else {
common_menu_item ( common_local_url ( 'login' ), _ ( 'Login' ));
if ( ! common_config ( 'site' , 'closed' )) {
common_menu_item ( common_local_url ( 'register' ), _ ( 'Register' ));
}
common_menu_item ( common_local_url ( 'openidlogin' ), _ ( 'OpenID' ));
}
common_menu_item ( common_local_url ( 'doc' , array ( 'title' => 'help' )),
_ ( 'Help' ));
common_element_end ( 'ul' );
2008-05-20 14:05:35 +01:00
}
2008-12-23 19:33:23 +00:00
function common_foot_menu ()
{
2008-12-21 00:30:16 +00:00
common_element_start ( 'ul' , array ( 'id' => 'nav_sub' ));
common_menu_item ( common_local_url ( 'doc' , array ( 'title' => 'help' )),
_ ( 'Help' ));
common_menu_item ( common_local_url ( 'doc' , array ( 'title' => 'about' )),
_ ( 'About' ));
common_menu_item ( common_local_url ( 'doc' , array ( 'title' => 'faq' )),
_ ( 'FAQ' ));
common_menu_item ( common_local_url ( 'doc' , array ( 'title' => 'privacy' )),
_ ( 'Privacy' ));
common_menu_item ( common_local_url ( 'doc' , array ( 'title' => 'source' )),
_ ( 'Source' ));
common_menu_item ( common_local_url ( 'doc' , array ( 'title' => 'contact' )),
_ ( 'Contact' ));
common_element_end ( 'ul' );
}
2008-12-23 19:33:23 +00:00
function common_menu_item ( $url , $text , $title = null , $is_selected = false )
{
2008-12-21 00:30:16 +00:00
$lattrs = array ();
if ( $is_selected ) {
$lattrs [ 'class' ] = 'current' ;
}
common_element_start ( 'li' , $lattrs );
$attrs [ 'href' ] = $url ;
if ( $title ) {
$attrs [ 'title' ] = $title ;
}
common_element ( 'a' , $attrs , $text );
common_element_end ( 'li' );
}
2008-12-23 19:33:23 +00:00
function common_timezone ()
{
2008-12-21 00:30:16 +00:00
if ( common_logged_in ()) {
$user = common_current_user ();
if ( $user -> timezone ) {
return $user -> timezone ;
}
}
2008-07-20 15:13:25 +01:00
2008-12-21 00:30:16 +00:00
global $config ;
return $config [ 'site' ][ 'timezone' ];
2008-07-20 15:13:25 +01:00
}
2008-12-23 19:33:23 +00:00
function common_language ()
{
2008-07-19 01:34:17 +01:00
2008-12-21 00:30:16 +00:00
// If there is a user logged in and they've set a language preference
// then return that one...
if ( common_logged_in ()) {
$user = common_current_user ();
$user_language = $user -> language ;
if ( $user_language )
return $user_language ;
}
2008-07-19 01:34:17 +01:00
2008-12-21 00:30:16 +00:00
// Otherwise, find the best match for the languages requested by the
// user's browser...
$httplang = isset ( $_SERVER [ 'HTTP_ACCEPT_LANGUAGE' ]) ? $_SERVER [ 'HTTP_ACCEPT_LANGUAGE' ] : null ;
if ( ! empty ( $httplang )) {
$language = client_prefered_language ( $httplang );
if ( $language )
return $language ;
}
2008-10-02 19:13:38 +01:00
2008-12-21 00:30:16 +00:00
// Finally, if none of the above worked, use the site's default...
return common_config ( 'site' , 'language' );
2008-07-19 01:34:17 +01:00
}
2008-12-21 00:30:16 +00:00
// salted, hashed passwords are stored in the DB
2008-05-20 14:05:35 +01:00
2008-12-23 19:33:23 +00:00
function common_munge_password ( $password , $id )
{
2008-12-21 00:30:16 +00:00
return md5 ( $password . $id );
2008-05-20 14:05:35 +01:00
}
2008-12-21 00:30:16 +00:00
// check if a username exists and has matching password
2008-12-23 19:33:23 +00:00
function common_check_user ( $nickname , $password )
{
2008-12-21 00:30:16 +00:00
// NEVER allow blank passwords, even if they match the DB
if ( mb_strlen ( $password ) == 0 ) {
return false ;
}
$user = User :: staticGet ( 'nickname' , $nickname );
if ( is_null ( $user )) {
return false ;
} else {
if ( 0 == strcmp ( common_munge_password ( $password , $user -> id ),
$user -> password )) {
return $user ;
} else {
return false ;
}
}
}
// is the current user logged in?
2008-12-23 19:33:23 +00:00
function common_logged_in ()
{
2008-12-21 00:30:16 +00:00
return ( ! is_null ( common_current_user ()));
2008-05-20 14:05:35 +01:00
}
2008-12-23 19:33:23 +00:00
function common_have_session ()
{
2008-12-21 00:30:16 +00:00
return ( 0 != strcmp ( session_id (), '' ));
2008-05-20 14:05:35 +01:00
}
2008-12-23 19:33:23 +00:00
function common_ensure_session ()
{
2008-12-21 00:30:16 +00:00
if ( ! common_have_session ()) {
@ session_start ();
}
2008-05-20 14:05:35 +01:00
}
2008-12-21 00:30:16 +00:00
// Three kinds of arguments:
// 1) a user object
// 2) a nickname
// 3) null to clear
2008-07-09 06:53:43 +01:00
2008-12-21 00:30:16 +00:00
// Initialize to false; set to null if none found
2008-12-09 17:34:02 +00:00
$_cur = false ;
2008-12-23 19:33:23 +00:00
function common_set_user ( $user )
{
2008-12-09 17:34:02 +00:00
global $_cur ;
2008-12-21 00:30:16 +00:00
if ( is_null ( $user ) && common_have_session ()) {
$_cur = null ;
unset ( $_SESSION [ 'userid' ]);
return true ;
} else if ( is_string ( $user )) {
$nickname = $user ;
$user = User :: staticGet ( 'nickname' , $nickname );
} else if ( ! ( $user instanceof User )) {
return false ;
}
if ( $user ) {
common_ensure_session ();
$_SESSION [ 'userid' ] = $user -> id ;
2008-12-09 17:34:02 +00:00
$_cur = $user ;
2008-12-21 00:30:16 +00:00
return $_cur ;
}
return false ;
2008-05-20 14:05:35 +01:00
}
2008-12-23 19:33:23 +00:00
function common_set_cookie ( $key , $value , $expiration = 0 )
{
2008-12-21 00:30:16 +00:00
$path = common_config ( 'site' , 'path' );
$server = common_config ( 'site' , 'server' );
2008-06-24 03:52:34 +01:00
2008-12-21 00:30:16 +00:00
if ( $path && ( $path != '/' )) {
$cookiepath = '/' . $path . '/' ;
} else {
$cookiepath = '/' ;
}
return setcookie ( $key ,
$value ,
$expiration ,
$cookiepath ,
$server );
2008-06-24 03:52:34 +01:00
}
define ( 'REMEMBERME' , 'rememberme' );
2008-12-21 00:30:16 +00:00
define ( 'REMEMBERME_EXPIRY' , 30 * 24 * 60 * 60 ); // 30 days
2008-06-24 03:52:34 +01:00
2008-12-23 19:33:23 +00:00
function common_rememberme ( $user = null )
{
2008-12-21 00:30:16 +00:00
if ( ! $user ) {
$user = common_current_user ();
if ( ! $user ) {
common_debug ( 'No current user to remember' , __FILE__ );
return false ;
}
}
2008-12-09 17:54:46 +00:00
2008-12-21 00:30:16 +00:00
$rm = new Remember_me ();
2008-12-09 18:54:24 +00:00
2008-12-21 00:30:16 +00:00
$rm -> code = common_good_rand ( 16 );
$rm -> user_id = $user -> id ;
2008-12-09 18:54:24 +00:00
2008-12-21 00:30:16 +00:00
// Wrap the insert in some good ol' fashioned transaction code
2008-12-09 18:54:24 +00:00
$rm -> query ( 'BEGIN' );
2008-12-21 00:30:16 +00:00
$result = $rm -> insert ();
2008-12-09 17:54:46 +00:00
2008-12-21 00:30:16 +00:00
if ( ! $result ) {
common_log_db_error ( $rm , 'INSERT' , __FILE__ );
common_debug ( 'Error adding rememberme record for ' . $user -> nickname , __FILE__ );
return false ;
2008-12-09 17:54:46 +00:00
}
2008-12-09 18:54:24 +00:00
$rm -> query ( 'COMMIT' );
2008-12-21 00:30:16 +00:00
common_debug ( 'Inserted rememberme record (' . $rm -> code . ', ' . $rm -> user_id . '); result = ' . $result . '.' , __FILE__ );
2008-12-09 17:54:46 +00:00
$cookieval = $rm -> user_id . ':' . $rm -> code ;
2008-12-21 00:30:16 +00:00
common_log ( LOG_INFO , 'adding rememberme cookie "' . $cookieval . '" for ' . $user -> nickname );
2008-12-09 17:54:46 +00:00
2008-12-21 00:30:16 +00:00
common_set_cookie ( REMEMBERME , $cookieval , time () + REMEMBERME_EXPIRY );
2008-12-09 17:54:46 +00:00
2008-12-21 00:30:16 +00:00
return true ;
2008-06-24 03:52:34 +01:00
}
2008-12-23 19:33:23 +00:00
function common_remembered_user ()
{
2008-12-09 17:04:13 +00:00
2008-12-21 00:30:16 +00:00
$user = null ;
2008-12-09 17:04:13 +00:00
2008-12-21 00:30:16 +00:00
$packed = isset ( $_COOKIE [ REMEMBERME ]) ? $_COOKIE [ REMEMBERME ] : null ;
2008-12-09 17:04:13 +00:00
2008-12-21 00:30:16 +00:00
if ( ! $packed ) {
return null ;
2008-12-09 17:04:13 +00:00
}
list ( $id , $code ) = explode ( ':' , $packed );
if ( ! $id || ! $code ) {
2008-12-09 17:42:33 +00:00
common_log ( LOG_WARNING , 'Malformed rememberme cookie: ' . $packed );
2008-12-09 17:04:13 +00:00
common_forgetme ();
2008-12-21 00:30:16 +00:00
return null ;
2008-12-09 17:04:13 +00:00
}
$rm = Remember_me :: staticGet ( $code );
if ( ! $rm ) {
2008-12-09 17:42:33 +00:00
common_log ( LOG_WARNING , 'No such remember code: ' . $code );
2008-12-09 17:04:13 +00:00
common_forgetme ();
2008-12-21 00:30:16 +00:00
return null ;
2008-12-09 17:04:13 +00:00
}
if ( $rm -> user_id != $id ) {
2008-12-09 17:42:33 +00:00
common_log ( LOG_WARNING , 'Rememberme code for wrong user: ' . $rm -> user_id . ' != ' . $id );
2008-12-09 17:04:13 +00:00
common_forgetme ();
2008-12-21 00:30:16 +00:00
return null ;
2008-12-09 17:04:13 +00:00
}
$user = User :: staticGet ( $rm -> user_id );
if ( ! $user ) {
2008-12-09 17:42:33 +00:00
common_log ( LOG_WARNING , 'No such user for rememberme: ' . $rm -> user_id );
2008-12-09 17:04:13 +00:00
common_forgetme ();
2008-12-21 00:30:16 +00:00
return null ;
2008-12-09 17:04:13 +00:00
}
2008-12-21 00:30:16 +00:00
// successful!
2008-12-09 17:04:13 +00:00
$result = $rm -> delete ();
if ( ! $result ) {
common_log_db_error ( $rm , 'DELETE' , __FILE__ );
2008-12-09 17:42:33 +00:00
common_log ( LOG_WARNING , 'Could not delete rememberme: ' . $code );
2008-12-09 17:04:13 +00:00
common_forgetme ();
2008-12-21 00:30:16 +00:00
return null ;
2008-12-09 17:04:13 +00:00
}
common_log ( LOG_INFO , 'logging in ' . $user -> nickname . ' using rememberme code ' . $rm -> code );
2008-12-09 17:34:02 +00:00
common_set_user ( $user );
2008-12-09 17:04:13 +00:00
common_real_login ( false );
2008-12-21 00:30:16 +00:00
// We issue a new cookie, so they can log in
// automatically again after this session
2008-12-09 17:04:13 +00:00
common_rememberme ( $user );
2008-12-21 00:30:16 +00:00
return $user ;
2008-06-24 03:52:34 +01:00
}
2008-12-21 00:30:16 +00:00
// must be called with a valid user!
2008-06-24 03:52:34 +01:00
2008-12-23 19:33:23 +00:00
function common_forgetme ()
{
2008-12-21 00:30:16 +00:00
common_set_cookie ( REMEMBERME , '' , 0 );
2008-06-24 03:52:34 +01:00
}
2008-12-21 00:30:16 +00:00
// who is the current user?
2008-12-23 19:33:23 +00:00
function common_current_user ()
{
2008-12-09 17:34:02 +00:00
global $_cur ;
if ( $_cur === false ) {
if ( isset ( $_REQUEST [ session_name ()]) || ( isset ( $_SESSION [ 'userid' ]) && $_SESSION [ 'userid' ])) {
common_ensure_session ();
$id = isset ( $_SESSION [ 'userid' ]) ? $_SESSION [ 'userid' ] : false ;
if ( $id ) {
$_cur = User :: staticGet ( $id );
return $_cur ;
}
}
2008-12-21 00:30:16 +00:00
// that didn't work; try to remember; will init $_cur to null on failure
2008-12-09 17:34:02 +00:00
$_cur = common_remembered_user ();
if ( $_cur ) {
common_debug ( " Got User " . $_cur -> nickname );
common_debug ( " Faking session on remembered user " );
2008-12-21 00:30:16 +00:00
// XXX: Is this necessary?
2008-12-09 17:34:02 +00:00
$_SESSION [ 'userid' ] = $_cur -> id ;
}
}
2008-12-21 00:30:16 +00:00
return $_cur ;
2008-05-20 14:05:35 +01:00
}
2008-12-21 00:30:16 +00:00
// Logins that are 'remembered' aren't 'real' -- they're subject to
// cookie-stealing. So, we don't let them do certain things. New reg,
// OpenID, and password logins _are_ real.
2008-06-24 03:52:34 +01:00
2008-12-23 19:33:23 +00:00
function common_real_login ( $real = true )
{
2008-12-21 00:30:16 +00:00
common_ensure_session ();
$_SESSION [ 'real_login' ] = $real ;
2008-06-24 03:52:34 +01:00
}
2008-12-23 19:33:23 +00:00
function common_is_real_login ()
{
2008-12-21 00:30:16 +00:00
return common_logged_in () && $_SESSION [ 'real_login' ];
2008-06-24 03:52:34 +01:00
}
2008-12-21 00:30:16 +00:00
// get canonical version of nickname for comparison
2008-12-23 19:33:23 +00:00
function common_canonical_nickname ( $nickname )
{
2008-12-21 00:30:16 +00:00
// XXX: UTF-8 canonicalization (like combining chars)
return strtolower ( $nickname );
2008-05-20 14:05:35 +01:00
}
2008-12-21 00:30:16 +00:00
// get canonical version of email for comparison
2008-12-23 19:33:23 +00:00
function common_canonical_email ( $email )
{
2008-12-21 00:30:16 +00:00
// XXX: canonicalize UTF-8
// XXX: lcase the domain part
return $email ;
2008-05-20 14:05:35 +01:00
}
2008-05-29 19:12:44 +01:00
define ( 'URL_REGEX' , '^|[ \t\r\n])((ftp|http|https|gopher|mailto|news|nntp|telnet|wais|file|prospero|aim|webcal):(([A-Za-z0-9$_.+!*(),;/?:@&~=-])|%[A-Fa-f0-9]{2}){2,}(#([a-zA-Z0-9][a-zA-Z0-9$_.+!*(),;/?:@&~=%-]*))?([A-Za-z0-9$_+!*();/?:~-]))' );
2008-12-23 19:33:23 +00:00
function common_render_content ( $text , $notice )
{
2008-12-21 00:30:16 +00:00
$r = common_render_text ( $text );
$id = $notice -> profile_id ;
$r = preg_replace ( '/(^|\s+)@([A-Za-z0-9]{1,64})/e' , " ' \\ 1@'.common_at_link( $id , ' \\ 2') " , $r );
$r = preg_replace ( '/^T ([A-Z0-9]{1,64}) /e' , " 'T '.common_at_link( $id , ' \\ 1').' ' " , $r );
$r = preg_replace ( '/(^|\s+)@#([A-Za-z0-9]{1,64})/e' , " ' \\ 1@#'.common_at_hash_link( $id , ' \\ 2') " , $r );
return $r ;
2008-09-17 12:27:30 +01:00
}
2008-12-23 19:33:23 +00:00
function common_render_text ( $text )
{
2008-12-21 00:30:16 +00:00
$r = htmlspecialchars ( $text );
2008-07-20 13:28:32 +01:00
2008-12-21 00:30:16 +00:00
$r = preg_replace ( '/[\x{0}-\x{8}\x{b}-\x{c}\x{e}-\x{19}]/' , '' , $r );
$r = preg_replace_callback ( '@https?://[^\]>\s]+@' , 'common_render_uri_thingy' , $r );
$r = preg_replace ( '/(^|\s+)#([A-Za-z0-9_\-\.]{1,64})/e' , " ' \\ 1#'.common_tag_link(' \\ 2') " , $r );
// XXX: machine tags
return $r ;
2008-05-29 18:08:01 +01:00
}
2008-12-23 19:33:23 +00:00
function common_render_uri_thingy ( $matches )
{
2008-12-21 00:30:16 +00:00
$uri = $matches [ 0 ];
$trailer = '' ;
// Some heuristics for extracting URIs from surrounding punctuation
// Strip from trailing text...
if ( preg_match ( '/^(.*)([,.:"\']+)$/' , $uri , $matches )) {
$uri = $matches [ 1 ];
$trailer = $matches [ 2 ];
}
$pairs = array (
']' => '[' , // technically disallowed in URIs, but used in Java docs
')' => '(' , // far too frequent in Wikipedia and MSDN
);
$final = substr ( $uri , - 1 , 1 );
if ( isset ( $pairs [ $final ])) {
$openers = substr_count ( $uri , $pairs [ $final ]);
$closers = substr_count ( $uri , $final );
if ( $closers > $openers ) {
// Assume the paren was opened outside the URI
$uri = substr ( $uri , 0 , - 1 );
$trailer = $final . $trailer ;
}
}
if ( $longurl = common_longurl ( $uri )) {
$longurl = htmlentities ( $longurl , ENT_QUOTES , 'UTF-8' );
$title = " title=' $longurl ' " ;
}
else $title = '' ;
return '<a href="' . $uri . '"' . $title . ' class="extlink">' . $uri . '</a>' . $trailer ;
2008-11-13 18:28:34 +00:00
}
2008-12-23 19:33:23 +00:00
function common_longurl ( $short_url )
{
2008-11-28 20:00:04 +00:00
$long_url = common_shorten_link ( $short_url , true );
if ( $long_url === $short_url ) return false ;
return $long_url ;
}
2008-12-23 19:33:23 +00:00
function common_longurl2 ( $uri )
{
2008-12-21 00:30:16 +00:00
$uri_e = urlencode ( $uri );
$longurl = unserialize ( file_get_contents ( " http://api.longurl.org/v1/expand?format=php&url= $uri_e " ));
if ( empty ( $longurl [ 'long_url' ]) || $uri === $longurl [ 'long_url' ]) return false ;
return stripslashes ( $longurl [ 'long_url' ]);
2008-11-02 09:02:41 +00:00
}
2008-12-23 19:33:23 +00:00
function common_shorten_links ( $text )
{
2008-11-28 20:00:04 +00:00
if ( mb_strlen ( $text ) <= 140 ) return $text ;
2008-11-28 21:01:14 +00:00
static $cache = array ();
if ( isset ( $cache [ $text ])) return $cache [ $text ];
2008-11-07 20:30:39 +00:00
// \s = not a horizontal whitespace character (since PHP 5.2.4)
2008-12-21 00:30:16 +00:00
return $cache [ $text ] = preg_replace ( '@https?://[^)\]>\s]+@e' , " common_shorten_link(' \\ 0') " , $text );
2008-11-06 20:59:26 +00:00
}
2008-12-23 19:33:23 +00:00
function common_shorten_link ( $url , $reverse = false )
{
2008-12-21 00:30:16 +00:00
static $url_cache = array ();
2008-12-03 04:17:30 +00:00
if ( $reverse ) return isset ( $url_cache [ $url ]) ? $url_cache [ $url ] : $url ;
2008-12-21 00:30:16 +00:00
$user = common_current_user ();
$curlh = curl_init ();
curl_setopt ( $curlh , CURLOPT_CONNECTTIMEOUT , 20 ); // # seconds to wait
curl_setopt ( $curlh , CURLOPT_USERAGENT , 'Laconica' );
curl_setopt ( $curlh , CURLOPT_RETURNTRANSFER , true );
switch ( $user -> urlshorteningservice ) {
case 'ur1.ca' :
$short_url_service = new LilUrl ;
$short_url = $short_url_service -> shorten ( $url );
break ;
case '2tu.us' :
$short_url_service = new TightUrl ;
$short_url = $short_url_service -> shorten ( $url );
break ;
case 'ptiturl.com' :
$short_url_service = new PtitUrl ;
$short_url = $short_url_service -> shorten ( $url );
break ;
case 'bit.ly' :
curl_setopt ( $curlh , CURLOPT_URL , 'http://bit.ly/api?method=shorten&long_url=' . urlencode ( $url ));
$short_url = current ( json_decode ( curl_exec ( $curlh )) -> results ) -> hashUrl ;
break ;
case 'is.gd' :
curl_setopt ( $curlh , CURLOPT_URL , 'http://is.gd/api.php?longurl=' . urlencode ( $url ));
$short_url = curl_exec ( $curlh );
break ;
case 'snipr.com' :
curl_setopt ( $curlh , CURLOPT_URL , 'http://snipr.com/site/snip?r=simple&link=' . urlencode ( $url ));
$short_url = curl_exec ( $curlh );
break ;
case 'metamark.net' :
curl_setopt ( $curlh , CURLOPT_URL , 'http://metamark.net/api/rest/simple?long_url=' . urlencode ( $url ));
$short_url = curl_exec ( $curlh );
break ;
case 'tinyurl.com' :
curl_setopt ( $curlh , CURLOPT_URL , 'http://tinyurl.com/api-create.php?url=' . urlencode ( $url ));
$short_url = curl_exec ( $curlh );
break ;
default :
$short_url = false ;
}
curl_close ( $curlh );
if ( $short_url ) {
2008-11-28 20:00:04 +00:00
$url_cache [( string ) $short_url ] = $url ;
2008-12-21 00:30:16 +00:00
return ( string ) $short_url ;
}
return $url ;
2008-11-06 20:59:26 +00:00
}
2008-12-23 19:33:23 +00:00
function common_xml_safe_str ( $str )
{
2008-12-21 00:30:16 +00:00
$xmlStr = htmlentities ( iconv ( 'UTF-8' , 'UTF-8//IGNORE' , $str ), ENT_NOQUOTES , 'UTF-8' );
2008-12-03 03:27:43 +00:00
2008-12-21 00:30:16 +00:00
// Replace control, formatting, and surrogate characters with '*', ala Twitter
return preg_replace ( '/[\p{Cc}\p{Cf}\p{Cs}]/u' , '*' , $str );
2008-11-04 08:40:27 +00:00
}
2008-12-23 19:33:23 +00:00
function common_tag_link ( $tag )
{
2008-12-21 00:30:16 +00:00
$canonical = common_canonical_tag ( $tag );
$url = common_local_url ( 'tag' , array ( 'tag' => $canonical ));
return '<a href="' . htmlspecialchars ( $url ) . '" rel="tag" class="hashlink">' . htmlspecialchars ( $tag ) . '</a>' ;
2008-09-17 12:22:34 +01:00
}
2008-12-23 19:33:23 +00:00
function common_canonical_tag ( $tag )
{
2008-12-21 00:30:16 +00:00
return strtolower ( str_replace ( array ( '-' , '_' , '.' ), '' , $tag ));
2008-07-20 06:57:02 +01:00
}
2008-12-23 19:33:23 +00:00
function common_valid_profile_tag ( $str )
{
2008-12-21 00:30:16 +00:00
return preg_match ( '/^[A-Za-z0-9_\-\.]{1,64}$/' , $str );
2008-11-20 21:48:21 +00:00
}
2008-12-23 19:33:23 +00:00
function common_at_link ( $sender_id , $nickname )
{
2008-12-21 00:30:16 +00:00
$sender = Profile :: staticGet ( $sender_id );
$recipient = common_relative_profile ( $sender , common_canonical_nickname ( $nickname ));
if ( $recipient ) {
return '<a href="' . htmlspecialchars ( $recipient -> profileurl ) . '" class="atlink">' . $nickname . '</a>' ;
} else {
return $nickname ;
}
2008-07-07 06:43:58 +01:00
}
2008-12-23 19:33:23 +00:00
function common_at_hash_link ( $sender_id , $tag )
{
2008-12-21 00:30:16 +00:00
$user = User :: staticGet ( $sender_id );
if ( ! $user ) {
return $tag ;
}
$tagged = Profile_tag :: getTagged ( $user -> id , common_canonical_tag ( $tag ));
if ( $tagged ) {
$url = common_local_url ( 'subscriptions' ,
array ( 'nickname' => $user -> nickname ,
'tag' => $tag ));
return '<a href="' . htmlspecialchars ( $url ) . '" class="atlink">' . $tag . '</a>' ;
} else {
return $tag ;
}
}
2008-12-23 19:33:23 +00:00
function common_relative_profile ( $sender , $nickname , $dt = null )
{
2008-12-21 00:30:16 +00:00
// Try to find profiles this profile is subscribed to that have this nickname
$recipient = new Profile ();
// XXX: use a join instead of a subquery
$recipient -> whereAdd ( 'EXISTS (SELECT subscribed from subscription where subscriber = ' . $sender -> id . ' and subscribed = id)' , 'AND' );
$recipient -> whereAdd ( 'nickname = "' . trim ( $nickname ) . '"' , 'AND' );
2008-12-23 19:44:28 +00:00
if ( $recipient -> find ( true )) {
2008-12-21 00:30:16 +00:00
// XXX: should probably differentiate between profiles with
// the same name by date of most recent update
return $recipient ;
}
// Try to find profiles that listen to this profile and that have this nickname
$recipient = new Profile ();
// XXX: use a join instead of a subquery
$recipient -> whereAdd ( 'EXISTS (SELECT subscriber from subscription where subscribed = ' . $sender -> id . ' and subscriber = id)' , 'AND' );
$recipient -> whereAdd ( 'nickname = "' . trim ( $nickname ) . '"' , 'AND' );
2008-12-23 19:44:28 +00:00
if ( $recipient -> find ( true )) {
2008-12-21 00:30:16 +00:00
// XXX: should probably differentiate between profiles with
// the same name by date of most recent update
return $recipient ;
}
// If this is a local user, try to find a local user with that nickname.
$sender = User :: staticGet ( $sender -> id );
if ( $sender ) {
$recipient_user = User :: staticGet ( 'nickname' , $nickname );
if ( $recipient_user ) {
return $recipient_user -> getProfile ();
}
}
// Otherwise, no links. @messages from local users to remote users,
// or from remote users to other remote users, are just
// outside our ability to make intelligent guesses about
return null ;
2008-05-20 14:05:35 +01:00
}
// where should the avatar go for this user?
2008-12-23 19:33:23 +00:00
function common_avatar_filename ( $id , $extension , $size = null , $extra = null )
{
2008-12-21 00:30:16 +00:00
global $config ;
2008-05-20 14:05:35 +01:00
2008-12-21 00:30:16 +00:00
if ( $size ) {
return $id . '-' . $size . (( $extra ) ? ( '-' . $extra ) : '' ) . $extension ;
} else {
return $id . '-original' . (( $extra ) ? ( '-' . $extra ) : '' ) . $extension ;
}
2008-05-20 14:05:35 +01:00
}
2008-12-23 19:33:23 +00:00
function common_avatar_path ( $filename )
{
2008-12-21 00:30:16 +00:00
global $config ;
return INSTALLDIR . '/avatar/' . $filename ;
2008-05-20 14:05:35 +01:00
}
2008-12-23 19:33:23 +00:00
function common_avatar_url ( $filename )
{
2008-12-21 00:30:16 +00:00
return common_path ( 'avatar/' . $filename );
2008-07-03 18:03:47 +01:00
}
2008-12-23 19:33:23 +00:00
function common_avatar_display_url ( $avatar )
{
2008-12-21 00:30:16 +00:00
$server = common_config ( 'avatar' , 'server' );
if ( $server ) {
return 'http://' . $server . '/' . $avatar -> filename ;
} else {
return $avatar -> url ;
}
2008-05-20 14:05:35 +01:00
}
2008-12-23 19:33:23 +00:00
function common_default_avatar ( $size )
{
2008-12-21 00:30:16 +00:00
static $sizenames = array ( AVATAR_PROFILE_SIZE => 'profile' ,
AVATAR_STREAM_SIZE => 'stream' ,
AVATAR_MINI_SIZE => 'mini' );
return theme_path ( 'default-avatar-' . $sizenames [ $size ] . '.png' );
}
2008-12-23 19:33:23 +00:00
function common_local_url ( $action , $args = null , $fragment = null )
{
2008-12-21 00:30:16 +00:00
$url = null ;
if ( common_config ( 'site' , 'fancy' )) {
$url = common_fancy_url ( $action , $args );
} else {
$url = common_simple_url ( $action , $args );
}
if ( ! is_null ( $fragment )) {
$url .= '#' . $fragment ;
}
return $url ;
}
2008-12-23 19:33:23 +00:00
function common_fancy_url ( $action , $args = null )
{
2008-12-21 00:30:16 +00:00
switch ( strtolower ( $action )) {
case 'public' :
if ( $args && isset ( $args [ 'page' ])) {
return common_path ( '?page=' . $args [ 'page' ]);
} else {
return common_path ( '' );
}
case 'featured' :
if ( $args && isset ( $args [ 'page' ])) {
return common_path ( 'featured?page=' . $args [ 'page' ]);
} else {
return common_path ( 'featured' );
}
case 'favorited' :
if ( $args && isset ( $args [ 'page' ])) {
return common_path ( 'favorited?page=' . $args [ 'page' ]);
} else {
return common_path ( 'favorited' );
}
case 'publicrss' :
return common_path ( 'rss' );
case 'publicatom' :
return common_path ( " api/statuses/public_timeline.atom " );
case 'publicxrds' :
return common_path ( 'xrds' );
case 'featuredrss' :
return common_path ( 'featuredrss' );
case 'favoritedrss' :
return common_path ( 'favoritedrss' );
case 'opensearch' :
if ( $args && $args [ 'type' ]) {
return common_path ( 'opensearch/' . $args [ 'type' ]);
} else {
return common_path ( 'opensearch/people' );
}
case 'doc' :
return common_path ( 'doc/' . $args [ 'title' ]);
2008-12-08 07:15:21 +00:00
case 'block' :
2008-12-21 00:30:16 +00:00
case 'login' :
case 'logout' :
case 'subscribe' :
case 'unsubscribe' :
case 'invite' :
return common_path ( 'main/' . $action );
case 'tagother' :
return common_path ( 'main/tagother?id=' . $args [ 'id' ]);
case 'register' :
if ( $args && $args [ 'code' ]) {
return common_path ( 'main/register/' . $args [ 'code' ]);
} else {
return common_path ( 'main/register' );
}
case 'remotesubscribe' :
if ( $args && $args [ 'nickname' ]) {
return common_path ( 'main/remote?nickname=' . $args [ 'nickname' ]);
} else {
return common_path ( 'main/remote' );
}
case 'nudge' :
return common_path ( $args [ 'nickname' ] . '/nudge' );
case 'openidlogin' :
return common_path ( 'main/openid' );
case 'profilesettings' :
return common_path ( 'settings/profile' );
case 'emailsettings' :
return common_path ( 'settings/email' );
case 'openidsettings' :
return common_path ( 'settings/openid' );
case 'smssettings' :
return common_path ( 'settings/sms' );
case 'twittersettings' :
return common_path ( 'settings/twitter' );
case 'othersettings' :
return common_path ( 'settings/other' );
2008-12-04 18:02:33 +00:00
case 'deleteprofile' :
return common_path ( 'settings/delete' );
2008-12-21 00:30:16 +00:00
case 'newnotice' :
if ( $args && $args [ 'replyto' ]) {
return common_path ( 'notice/new?replyto=' . $args [ 'replyto' ]);
} else {
return common_path ( 'notice/new' );
}
case 'shownotice' :
return common_path ( 'notice/' . $args [ 'notice' ]);
case 'deletenotice' :
if ( $args && $args [ 'notice' ]) {
return common_path ( 'notice/delete/' . $args [ 'notice' ]);
} else {
return common_path ( 'notice/delete' );
}
case 'microsummary' :
case 'xrds' :
case 'foaf' :
return common_path ( $args [ 'nickname' ] . '/' . $action );
case 'all' :
case 'replies' :
case 'inbox' :
case 'outbox' :
if ( $args && isset ( $args [ 'page' ])) {
return common_path ( $args [ 'nickname' ] . '/' . $action . '?page=' . $args [ 'page' ]);
} else {
return common_path ( $args [ 'nickname' ] . '/' . $action );
}
case 'subscriptions' :
case 'subscribers' :
$nickname = $args [ 'nickname' ];
unset ( $args [ 'nickname' ]);
if ( isset ( $args [ 'tag' ])) {
$tag = $args [ 'tag' ];
unset ( $args [ 'tag' ]);
}
$params = http_build_query ( $args );
if ( $params ) {
return common_path ( $nickname . '/' . $action . (( $tag ) ? '/' . $tag : '' ) . '?' . $params );
} else {
return common_path ( $nickname . '/' . $action . (( $tag ) ? '/' . $tag : '' ));
}
case 'allrss' :
return common_path ( $args [ 'nickname' ] . '/all/rss' );
case 'repliesrss' :
return common_path ( $args [ 'nickname' ] . '/replies/rss' );
case 'userrss' :
2008-11-24 00:50:54 +00:00
if ( isset ( $args [ 'limit' ]))
2008-12-21 00:30:16 +00:00
return common_path ( $args [ 'nickname' ] . '/rss?limit=' . $args [ 'limit' ]);
return common_path ( $args [ 'nickname' ] . '/rss' );
case 'showstream' :
if ( $args && isset ( $args [ 'page' ])) {
return common_path ( $args [ 'nickname' ] . '?page=' . $args [ 'page' ]);
} else {
return common_path ( $args [ 'nickname' ]);
}
case 'usertimeline' :
return common_path ( " api/statuses/user_timeline/ " . $args [ 'nickname' ] . " .atom " );
case 'confirmaddress' :
return common_path ( 'main/confirmaddress/' . $args [ 'code' ]);
case 'userbyid' :
return common_path ( 'user/' . $args [ 'id' ]);
case 'recoverpassword' :
$path = 'main/recoverpassword' ;
if ( $args [ 'code' ]) {
$path .= '/' . $args [ 'code' ];
}
return common_path ( $path );
case 'imsettings' :
return common_path ( 'settings/im' );
case 'peoplesearch' :
return common_path ( 'search/people' . (( $args ) ? ( '?' . http_build_query ( $args )) : '' ));
case 'noticesearch' :
return common_path ( 'search/notice' . (( $args ) ? ( '?' . http_build_query ( $args )) : '' ));
case 'noticesearchrss' :
return common_path ( 'search/notice/rss' . (( $args ) ? ( '?' . http_build_query ( $args )) : '' ));
case 'avatarbynickname' :
return common_path ( $args [ 'nickname' ] . '/avatar/' . $args [ 'size' ]);
case 'tag' :
if ( isset ( $args [ 'tag' ]) && $args [ 'tag' ]) {
$path = 'tag/' . $args [ 'tag' ];
unset ( $args [ 'tag' ]);
} else {
$path = 'tags' ;
}
return common_path ( $path . (( $args ) ? ( '?' . http_build_query ( $args )) : '' ));
case 'peopletag' :
$path = 'peopletag/' . $args [ 'tag' ];
unset ( $args [ 'tag' ]);
return common_path ( $path . (( $args ) ? ( '?' . http_build_query ( $args )) : '' ));
case 'tags' :
return common_path ( 'tags' . (( $args ) ? ( '?' . http_build_query ( $args )) : '' ));
case 'favor' :
return common_path ( 'main/favor' );
case 'disfavor' :
return common_path ( 'main/disfavor' );
case 'showfavorites' :
if ( $args && isset ( $args [ 'page' ])) {
return common_path ( $args [ 'nickname' ] . '/favorites?page=' . $args [ 'page' ]);
} else {
return common_path ( $args [ 'nickname' ] . '/favorites' );
}
case 'favoritesrss' :
return common_path ( $args [ 'nickname' ] . '/favorites/rss' );
case 'showmessage' :
return common_path ( 'message/' . $args [ 'message' ]);
case 'newmessage' :
return common_path ( 'message/new' . (( $args ) ? ( '?' . http_build_query ( $args )) : '' ));
case 'api' :
// XXX: do fancy URLs for all the API methods
switch ( strtolower ( $args [ 'apiaction' ])) {
case 'statuses' :
switch ( strtolower ( $args [ 'method' ])) {
case 'user_timeline.rss' :
return common_path ( 'api/statuses/user_timeline/' . $args [ 'argument' ] . '.rss' );
case 'user_timeline.atom' :
return common_path ( 'api/statuses/user_timeline/' . $args [ 'argument' ] . '.atom' );
case 'user_timeline.json' :
return common_path ( 'api/statuses/user_timeline/' . $args [ 'argument' ] . '.json' );
case 'user_timeline.xml' :
return common_path ( 'api/statuses/user_timeline/' . $args [ 'argument' ] . '.xml' );
default : return common_simple_url ( $action , $args );
}
default : return common_simple_url ( $action , $args );
}
case 'sup' :
if ( $args && isset ( $args [ 'seconds' ])) {
return common_path ( 'main/sup?seconds=' . $args [ 'seconds' ]);
} else {
return common_path ( 'main/sup' );
}
default :
return common_simple_url ( $action , $args );
}
}
2008-12-23 19:33:23 +00:00
function common_simple_url ( $action , $args = null )
{
2008-12-21 00:30:16 +00:00
global $config ;
/* XXX: pretty URLs */
$extra = '' ;
if ( $args ) {
foreach ( $args as $key => $value ) {
$extra .= " & ${ key}=${value } " ;
}
}
return common_path ( " index.php?action= ${ action}${extra } " );
2008-05-30 17:24:29 +01:00
}
2008-12-23 19:33:23 +00:00
function common_path ( $relative )
{
2008-12-21 00:30:16 +00:00
global $config ;
$pathpart = ( $config [ 'site' ][ 'path' ]) ? $config [ 'site' ][ 'path' ] . " / " : '' ;
return " http:// " . $config [ 'site' ][ 'server' ] . '/' . $pathpart . $relative ;
2008-05-20 14:05:35 +01:00
}
2008-12-23 19:33:23 +00:00
function common_date_string ( $dt )
{
2008-12-21 00:30:16 +00:00
// XXX: do some sexy date formatting
// return date(DATE_RFC822, $dt);
$t = strtotime ( $dt );
$now = time ();
$diff = $now - $t ;
if ( $now < $t ) { // that shouldn't happen!
return common_exact_date ( $dt );
} else if ( $diff < 60 ) {
return _ ( 'a few seconds ago' );
} else if ( $diff < 92 ) {
return _ ( 'about a minute ago' );
} else if ( $diff < 3300 ) {
return sprintf ( _ ( 'about %d minutes ago' ), round ( $diff / 60 ));
} else if ( $diff < 5400 ) {
return _ ( 'about an hour ago' );
} else if ( $diff < 22 * 3600 ) {
return sprintf ( _ ( 'about %d hours ago' ), round ( $diff / 3600 ));
} else if ( $diff < 37 * 3600 ) {
return _ ( 'about a day ago' );
} else if ( $diff < 24 * 24 * 3600 ) {
return sprintf ( _ ( 'about %d days ago' ), round ( $diff / ( 24 * 3600 )));
} else if ( $diff < 46 * 24 * 3600 ) {
return _ ( 'about a month ago' );
} else if ( $diff < 330 * 24 * 3600 ) {
return sprintf ( _ ( 'about %d months ago' ), round ( $diff / ( 30 * 24 * 3600 )));
} else if ( $diff < 480 * 24 * 3600 ) {
return _ ( 'about a year ago' );
} else {
return common_exact_date ( $dt );
}
2008-06-27 23:25:22 +01:00
}
2008-12-23 19:33:23 +00:00
function common_exact_date ( $dt )
{
2008-07-25 00:46:19 +01:00
static $_utc ;
static $_siteTz ;
if ( ! $_utc ) {
$_utc = new DateTimeZone ( 'UTC' );
$_siteTz = new DateTimeZone ( common_timezone ());
}
2008-12-21 00:30:16 +00:00
$dateStr = date ( 'd F Y H:i:s' , strtotime ( $dt ));
$d = new DateTime ( $dateStr , $_utc );
$d -> setTimezone ( $_siteTz );
return $d -> format ( DATE_RFC850 );
2008-05-20 14:05:35 +01:00
}
2008-12-23 19:33:23 +00:00
function common_date_w3dtf ( $dt )
{
2008-12-21 00:30:16 +00:00
$dateStr = date ( 'd F Y H:i:s' , strtotime ( $dt ));
$d = new DateTime ( $dateStr , new DateTimeZone ( 'UTC' ));
$d -> setTimezone ( new DateTimeZone ( common_timezone ()));
return $d -> format ( DATE_W3C );
2008-05-21 15:59:16 +01:00
}
2008-12-23 19:33:23 +00:00
function common_date_rfc2822 ( $dt )
{
2008-12-21 00:30:16 +00:00
$dateStr = date ( 'd F Y H:i:s' , strtotime ( $dt ));
$d = new DateTime ( $dateStr , new DateTimeZone ( 'UTC' ));
$d -> setTimezone ( new DateTimeZone ( common_timezone ()));
return $d -> format ( 'r' );
2008-07-16 23:02:23 +01:00
}
2008-12-23 19:33:23 +00:00
function common_date_iso8601 ( $dt )
{
2008-12-21 00:30:16 +00:00
$dateStr = date ( 'd F Y H:i:s' , strtotime ( $dt ));
$d = new DateTime ( $dateStr , new DateTimeZone ( 'UTC' ));
$d -> setTimezone ( new DateTimeZone ( common_timezone ()));
return $d -> format ( 'c' );
2008-07-16 23:02:23 +01:00
}
2008-12-23 19:33:23 +00:00
function common_sql_now ()
{
2008-12-21 00:30:16 +00:00
return strftime ( '%Y-%m-%d %H:%M:%S' , time ());
2008-08-25 19:23:38 +01:00
}
2008-12-23 19:33:23 +00:00
function common_redirect ( $url , $code = 307 )
{
2008-12-21 00:30:16 +00:00
static $status = array ( 301 => " Moved Permanently " ,
302 => " Found " ,
303 => " See Other " ,
307 => " Temporary Redirect " );
header ( " Status: ${ code } $status[$code] " );
header ( " Location: $url " );
common_start_xml ( 'a' ,
'-//W3C//DTD XHTML 1.0 Strict//EN' ,
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd' );
common_element ( 'a' , array ( 'href' => $url ), $url );
common_end_xml ();
2008-07-10 06:57:26 +01:00
exit ;
2008-05-20 14:05:35 +01:00
}
2008-12-23 19:33:23 +00:00
function common_save_replies ( $notice )
{
2008-12-21 00:30:16 +00:00
// Alternative reply format
$tname = false ;
if ( preg_match ( '/^T ([A-Z0-9]{1,64}) /' , $notice -> content , $match )) {
$tname = $match [ 1 ];
}
// extract all @messages
$cnt = preg_match_all ( '/(?:^|\s)@([a-z0-9]{1,64})/' , $notice -> content , $match );
$names = array ();
if ( $cnt || $tname ) {
// XXX: is there another way to make an array copy?
$names = ( $tname ) ? array_unique ( array_merge ( array ( strtolower ( $tname )), $match [ 1 ])) : array_unique ( $match [ 1 ]);
}
$sender = Profile :: staticGet ( $notice -> profile_id );
$replied = array ();
// store replied only for first @ (what user/notice what the reply directed,
// we assume first @ is it)
for ( $i = 0 ; $i < count ( $names ); $i ++ ) {
$nickname = $names [ $i ];
$recipient = common_relative_profile ( $sender , $nickname , $notice -> created );
if ( ! $recipient ) {
continue ;
}
if ( $i == 0 && ( $recipient -> id != $sender -> id ) && ! $notice -> reply_to ) { // Don't save reply to self
$reply_for = $recipient ;
$recipient_notice = $reply_for -> getCurrentNotice ();
if ( $recipient_notice ) {
$orig = clone ( $notice );
$notice -> reply_to = $recipient_notice -> id ;
$notice -> update ( $orig );
}
}
// Don't save replies from blocked profile to local user
2008-12-08 03:14:08 +00:00
$recipient_user = User :: staticGet ( 'id' , $recipient -> id );
if ( $recipient_user && $recipient_user -> hasBlocked ( $sender )) {
continue ;
}
2008-12-21 00:30:16 +00:00
$reply = new Reply ();
$reply -> notice_id = $notice -> id ;
$reply -> profile_id = $recipient -> id ;
$id = $reply -> insert ();
if ( ! $id ) {
$last_error = & PEAR :: getStaticProperty ( 'DB_DataObject' , 'lastError' );
common_log ( LOG_ERR , 'DB error inserting reply: ' . $last_error -> message );
common_server_error ( sprintf ( _ ( 'DB error inserting reply: %s' ), $last_error -> message ));
return ;
} else {
$replied [ $recipient -> id ] = 1 ;
}
}
// Hash format replies, too
$cnt = preg_match_all ( '/(?:^|\s)@#([a-z0-9]{1,64})/' , $notice -> content , $match );
if ( $cnt ) {
foreach ( $match [ 1 ] as $tag ) {
$tagged = Profile_tag :: getTagged ( $sender -> id , $tag );
foreach ( $tagged as $t ) {
if ( ! $replied [ $t -> id ]) {
// Don't save replies from blocked profile to local user
2008-12-08 03:14:08 +00:00
$t_user = User :: staticGet ( 'id' , $t -> id );
if ( $t_user && $t_user -> hasBlocked ( $sender )) {
continue ;
}
2008-12-21 00:30:16 +00:00
$reply = new Reply ();
$reply -> notice_id = $notice -> id ;
$reply -> profile_id = $t -> id ;
$id = $reply -> insert ();
if ( ! $id ) {
common_log_db_error ( $reply , 'INSERT' , __FILE__ );
return ;
}
}
}
}
}
2008-06-23 04:08:37 +01:00
}
2008-12-23 19:33:23 +00:00
function common_broadcast_notice ( $notice , $remote = false )
{
2008-09-24 03:36:15 +01:00
2008-12-21 00:30:16 +00:00
// Check to see if notice should go to Twitter
$flink = Foreign_link :: getByUserID ( $notice -> profile_id , 1 ); // 1 == Twitter
if (( $flink -> noticesync & FOREIGN_NOTICE_SEND ) == FOREIGN_NOTICE_SEND ) {
2008-09-26 20:05:43 +01:00
2008-12-21 00:30:16 +00:00
// If it's not a Twitter-style reply, or if the user WANTS to send replies...
2008-09-26 20:05:43 +01:00
2008-12-21 00:30:16 +00:00
if ( ! preg_match ( '/^@[a-zA-Z0-9_]{1,15}\b/u' , $notice -> content ) ||
(( $flink -> noticesync & FOREIGN_NOTICE_SEND_REPLY ) == FOREIGN_NOTICE_SEND_REPLY )) {
2008-09-26 20:05:43 +01:00
2008-12-21 00:30:16 +00:00
$result = common_twitter_broadcast ( $notice , $flink );
2008-09-24 03:36:15 +01:00
2008-12-21 00:30:16 +00:00
if ( ! $result ) {
common_debug ( 'Unable to send notice: ' . $notice -> id . ' to Twitter.' , __FILE__ );
}
}
}
2008-09-24 03:36:15 +01:00
2008-12-21 00:30:16 +00:00
if ( common_config ( 'queue' , 'enabled' )) {
// Do it later!
return common_enqueue_notice ( $notice );
} else {
return common_real_broadcast ( $notice , $remote );
}
2008-07-04 06:04:25 +01:00
}
2008-12-23 19:33:23 +00:00
function common_twitter_broadcast ( $notice , $flink )
{
2008-12-21 00:30:16 +00:00
global $config ;
$success = true ;
$fuser = $flink -> getForeignUser ();
$twitter_user = $fuser -> nickname ;
$twitter_password = $flink -> credentials ;
$uri = 'http://www.twitter.com/statuses/update.json' ;
// XXX: Hack to get around PHP cURL's use of @ being a a meta character
$statustxt = preg_replace ( '/^@/' , ' @' , $notice -> content );
$options = array (
CURLOPT_USERPWD => " $twitter_user : $twitter_password " ,
CURLOPT_POST => true ,
CURLOPT_POSTFIELDS => array (
'status' => $statustxt ,
'source' => $config [ 'integration' ][ 'source' ]
),
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_FAILONERROR => true ,
CURLOPT_HEADER => false ,
CURLOPT_FOLLOWLOCATION => true ,
CURLOPT_USERAGENT => " Laconica " ,
CURLOPT_CONNECTTIMEOUT => 120 , // XXX: Scary!!!! How long should this be?
2008-12-25 15:22:07 +00:00
CURLOPT_TIMEOUT => 120 ,
# Twitter is strict about accepting invalid "Expect" headers
CURLOPT_HTTPHEADER => array ( 'Expect:' )
2008-12-21 00:30:16 +00:00
);
$ch = curl_init ( $uri );
2008-08-28 20:25:09 +01:00
curl_setopt_array ( $ch , $options );
$data = curl_exec ( $ch );
$errmsg = curl_error ( $ch );
2008-12-21 00:30:16 +00:00
if ( $errmsg ) {
common_debug ( " cURL error: $errmsg - trying to send notice for $twitter_user . " ,
__FILE__ );
$success = false ;
}
2008-08-28 20:25:09 +01:00
2008-12-21 00:30:16 +00:00
curl_close ( $ch );
2008-09-24 03:36:15 +01:00
2008-12-21 00:30:16 +00:00
if ( ! $data ) {
common_debug ( " No data returned by Twitter's API trying to send update for $twitter_user " ,
__FILE__ );
$success = false ;
}
2008-08-28 20:25:09 +01:00
2008-12-21 00:30:16 +00:00
// Twitter should return a status
$status = json_decode ( $data );
2008-08-28 20:25:09 +01:00
2008-12-21 00:30:16 +00:00
if ( ! $status -> id ) {
common_debug ( " Unexpected data returned by Twitter API trying to send update for $twitter_user " ,
__FILE__ );
$success = false ;
}
2008-09-24 03:36:15 +01:00
2008-12-21 00:30:16 +00:00
return $success ;
2008-08-28 20:25:09 +01:00
}
2008-12-21 00:30:16 +00:00
// Stick the notice on the queue
2008-07-04 06:04:25 +01:00
2008-12-23 19:33:23 +00:00
function common_enqueue_notice ( $notice )
{
2008-12-21 00:30:16 +00:00
foreach ( array ( 'jabber' , 'omb' , 'sms' , 'public' ) as $transport ) {
$qi = new Queue_item ();
$qi -> notice_id = $notice -> id ;
$qi -> transport = $transport ;
$qi -> created = $notice -> created ;
2008-07-08 08:04:57 +01:00
$result = $qi -> insert ();
2008-12-21 00:30:16 +00:00
if ( ! $result ) {
$last_error = & PEAR :: getStaticProperty ( 'DB_DataObject' , 'lastError' );
common_log ( LOG_ERR , 'DB error inserting queue item: ' . $last_error -> message );
return false ;
}
common_log ( LOG_DEBUG , 'complete queueing notice ID = ' . $notice -> id . ' for ' . $transport );
}
return $result ;
2008-07-04 06:04:25 +01:00
}
2008-07-08 10:45:31 +01:00
2008-12-23 19:33:23 +00:00
function common_dequeue_notice ( $notice )
{
2008-12-21 00:30:16 +00:00
$qi = Queue_item :: staticGet ( $notice -> id );
if ( $qi ) {
$result = $qi -> delete ();
if ( ! $result ) {
$last_error = & PEAR :: getStaticProperty ( 'DB_DataObject' , 'lastError' );
common_log ( LOG_ERR , 'DB error deleting queue item: ' . $last_error -> message );
2008-07-16 04:20:45 +01:00
return false ;
}
2008-12-21 00:30:16 +00:00
common_log ( LOG_DEBUG , 'complete dequeueing notice ID = ' . $notice -> id );
return $result ;
} else {
return false ;
}
2008-07-16 04:20:45 +01:00
}
2008-12-23 19:33:23 +00:00
function common_real_broadcast ( $notice , $remote = false )
{
2008-12-21 00:30:16 +00:00
$success = true ;
if ( ! $remote ) {
// Make sure we have the OMB stuff
require_once ( INSTALLDIR . '/lib/omb.php' );
$success = omb_broadcast_remote_subscribers ( $notice );
if ( ! $success ) {
common_log ( LOG_ERR , 'Error in OMB broadcast for notice ' . $notice -> id );
}
}
if ( $success ) {
require_once ( INSTALLDIR . '/lib/jabber.php' );
$success = jabber_broadcast_notice ( $notice );
if ( ! $success ) {
common_log ( LOG_ERR , 'Error in jabber broadcast for notice ' . $notice -> id );
}
}
if ( $success ) {
require_once ( INSTALLDIR . '/lib/mail.php' );
$success = mail_broadcast_notice_sms ( $notice );
if ( ! $success ) {
common_log ( LOG_ERR , 'Error in sms broadcast for notice ' . $notice -> id );
}
}
if ( $success ) {
$success = jabber_public_notice ( $notice );
if ( ! $success ) {
common_log ( LOG_ERR , 'Error in public broadcast for notice ' . $notice -> id );
}
}
// XXX: broadcast notices to other IM
return $success ;
2008-05-20 14:05:35 +01:00
}
2008-12-23 19:33:23 +00:00
function common_broadcast_profile ( $profile )
{
2008-12-21 00:30:16 +00:00
// XXX: optionally use a queue system like http://code.google.com/p/microapps/wiki/NQDQ
require_once ( INSTALLDIR . '/lib/omb.php' );
omb_broadcast_profile ( $profile );
// XXX: Other broadcasts...?
return true ;
2008-06-12 19:40:28 +01:00
}
2008-06-06 17:04:37 +01:00
2008-12-23 19:33:23 +00:00
function common_profile_url ( $nickname )
{
2008-12-21 00:30:16 +00:00
return common_local_url ( 'showstream' , array ( 'nickname' => $nickname ));
2008-05-20 14:05:35 +01:00
}
2008-12-21 00:30:16 +00:00
// Don't call if nobody's logged in
2008-06-10 19:52:38 +01:00
2008-12-23 19:33:23 +00:00
function common_notice_form ( $action = null , $content = null )
{
2008-12-21 00:30:16 +00:00
$user = common_current_user ();
assert ( ! is_null ( $user ));
common_element_start ( 'form' , array ( 'id' => 'status_form' ,
'method' => 'post' ,
'action' => common_local_url ( 'newnotice' )));
common_element_start ( 'p' );
common_element ( 'label' , array ( 'for' => 'status_textarea' ,
'id' => 'status_label' ),
sprintf ( _ ( 'What\'s up, %s?' ), $user -> nickname ));
2008-11-11 02:23:30 +00:00
common_element ( 'span' , array ( 'id' => 'counter' , 'class' => 'counter' ), '140' );
2008-12-21 00:30:16 +00:00
common_element ( 'textarea' , array ( 'id' => 'status_textarea' ,
'cols' => 60 ,
'rows' => 3 ,
'name' => 'status_textarea' ),
( $content ) ? $content : '' );
common_hidden ( 'token' , common_session_token ());
if ( $action ) {
common_hidden ( 'returnto' , $action );
}
// set by JavaScript
common_hidden ( 'inreplyto' , 'false' );
common_element ( 'input' , array ( 'id' => 'status_submit' ,
'name' => 'status_submit' ,
'type' => 'submit' ,
'value' => _ ( 'Send' )));
common_element_end ( 'p' );
common_element_end ( 'form' );
}
// Should make up a reasonable root URL
2008-05-27 12:42:19 +01:00
2008-12-23 19:33:23 +00:00
function common_root_url ()
{
2008-12-21 00:30:16 +00:00
return common_path ( '' );
2008-05-27 12:42:19 +01:00
}
2008-12-21 00:30:16 +00:00
// returns $bytes bytes of random data as a hexadecimal string
// "good" here is a goal and not a guarantee
2008-05-27 21:07:21 +01:00
2008-12-23 19:33:23 +00:00
function common_good_rand ( $bytes )
{
2008-12-21 00:30:16 +00:00
// XXX: use random.org...?
if ( file_exists ( '/dev/urandom' )) {
return common_urandom ( $bytes );
} else { // FIXME: this is probably not good enough
return common_mtrand ( $bytes );
}
2008-05-27 21:07:21 +01:00
}
2008-12-23 19:33:23 +00:00
function common_urandom ( $bytes )
{
2008-12-21 00:30:16 +00:00
$h = fopen ( '/dev/urandom' , 'rb' );
// should not block
$src = fread ( $h , $bytes );
fclose ( $h );
$enc = '' ;
for ( $i = 0 ; $i < $bytes ; $i ++ ) {
$enc .= sprintf ( " %02x " , ( ord ( $src [ $i ])));
}
return $enc ;
2008-05-27 21:07:21 +01:00
}
2008-12-23 19:33:23 +00:00
function common_mtrand ( $bytes )
{
2008-12-21 00:30:16 +00:00
$enc = '' ;
for ( $i = 0 ; $i < $bytes ; $i ++ ) {
$enc .= sprintf ( " %02x " , mt_rand ( 0 , 255 ));
}
return $enc ;
2008-05-27 21:07:21 +01:00
}
2008-12-23 19:33:23 +00:00
function common_set_returnto ( $url )
{
2008-12-21 00:30:16 +00:00
common_ensure_session ();
$_SESSION [ 'returnto' ] = $url ;
2008-05-30 15:23:24 +01:00
}
2008-12-23 19:33:23 +00:00
function common_get_returnto ()
{
2008-12-21 00:30:16 +00:00
common_ensure_session ();
return $_SESSION [ 'returnto' ];
2008-05-30 15:23:24 +01:00
}
2008-12-23 19:33:23 +00:00
function common_timestamp ()
{
2008-12-21 00:30:16 +00:00
return date ( 'YmdHis' );
2008-05-28 15:03:21 +01:00
}
2008-06-06 17:04:37 +01:00
2008-12-23 19:33:23 +00:00
function common_ensure_syslog ()
{
2008-12-21 00:30:16 +00:00
static $initialized = false ;
if ( ! $initialized ) {
global $config ;
openlog ( $config [ 'syslog' ][ 'appname' ], 0 , LOG_USER );
$initialized = true ;
}
}
2008-12-23 19:33:23 +00:00
function common_log ( $priority , $msg , $filename = null )
{
2008-12-21 00:30:16 +00:00
$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 " ;
fwrite ( $log , $output );
fclose ( $log );
}
} else {
common_ensure_syslog ();
syslog ( $priority , $msg );
}
}
2008-12-23 19:33:23 +00:00
function common_debug ( $msg , $filename = null )
{
2008-12-21 00:30:16 +00:00
if ( $filename ) {
common_log ( LOG_DEBUG , basename ( $filename ) . ' - ' . $msg );
} else {
common_log ( LOG_DEBUG , $msg );
}
}
2008-12-23 19:33:23 +00:00
function common_log_db_error ( & $object , $verb , $filename = null )
{
2008-12-21 00:30:16 +00:00
$objstr = common_log_objstring ( $object );
$last_error = & PEAR :: getStaticProperty ( 'DB_DataObject' , 'lastError' );
common_log ( LOG_ERR , $last_error -> message . '(' . $verb . ' on ' . $objstr . ')' , $filename );
2008-06-22 15:09:41 +01:00
}
2008-12-23 19:33:23 +00:00
function common_log_objstring ( & $object )
{
2008-12-21 00:30:16 +00:00
if ( is_null ( $object )) {
return " null " ;
}
$arr = $object -> toArray ();
$fields = array ();
foreach ( $arr as $k => $v ) {
$fields [] = " $k =' $v ' " ;
}
$objstring = $object -> tableName () . '[' . implode ( ',' , $fields ) . ']' ;
return $objstring ;
2008-06-22 15:09:41 +01:00
}
2008-12-23 19:33:23 +00:00
function common_valid_http_url ( $url )
{
2008-12-21 00:30:16 +00:00
return Validate :: uri ( $url , array ( 'allowed_schemes' => array ( 'http' , 'https' )));
2008-06-04 19:51:31 +01:00
}
2008-06-05 05:01:53 +01:00
2008-12-23 19:33:23 +00:00
function common_valid_tag ( $tag )
{
2008-12-21 00:30:16 +00:00
if ( preg_match ( '/^tag:(.*?),(\d{4}(-\d{2}(-\d{2})?)?):(.*)$/' , $tag , $matches )) {
return ( Validate :: email ( $matches [ 1 ]) ||
preg_match ( '/^([\w-\.]+)$/' , $matches [ 1 ]));
}
return false ;
2008-06-05 05:01:53 +01:00
}
2008-06-10 20:21:01 +01:00
2008-12-21 00:30:16 +00:00
// Does a little before-after block for next/prev page
2008-06-10 20:21:01 +01:00
2008-12-23 19:33:23 +00:00
function common_pagination ( $have_before , $have_after , $page , $action , $args = null )
{
2008-06-20 07:56:19 +01:00
2008-12-21 00:30:16 +00:00
if ( $have_before || $have_after ) {
common_element_start ( 'div' , array ( 'id' => 'pagination' ));
common_element_start ( 'ul' , array ( 'id' => 'nav_pagination' ));
}
2008-06-20 07:56:19 +01:00
2008-12-21 00:30:16 +00:00
if ( $have_before ) {
$pargs = array ( 'page' => $page - 1 );
$newargs = ( $args ) ? array_merge ( $args , $pargs ) : $pargs ;
2008-06-20 07:56:19 +01:00
2008-12-21 00:30:16 +00:00
common_element_start ( 'li' , 'before' );
common_element ( 'a' , array ( 'href' => common_local_url ( $action , $newargs ), 'rel' => 'prev' ),
_ ( '« After' ));
common_element_end ( 'li' );
}
2008-06-10 20:21:01 +01:00
2008-12-21 00:30:16 +00:00
if ( $have_after ) {
$pargs = array ( 'page' => $page + 1 );
$newargs = ( $args ) ? array_merge ( $args , $pargs ) : $pargs ;
common_element_start ( 'li' , 'after' );
common_element ( 'a' , array ( 'href' => common_local_url ( $action , $newargs ), 'rel' => 'next' ),
_ ( 'Before »' ));
common_element_end ( 'li' );
}
2008-06-20 07:56:19 +01:00
2008-12-21 00:30:16 +00:00
if ( $have_before || $have_after ) {
common_element_end ( 'ul' );
common_element_end ( 'div' );
}
2008-06-10 20:21:01 +01:00
}
2008-06-13 15:49:13 +01:00
/* Following functions are copied from MediaWiki GlobalFunctions . php
* and written by Evan Prodromou . */
2008-12-23 19:33:23 +00:00
function common_accept_to_prefs ( $accept , $def = '*/*' )
{
2008-12-21 00:30:16 +00:00
// No arg means accept anything (per HTTP spec)
if ( ! $accept ) {
return array ( $def => 1 );
}
2008-06-13 15:49:13 +01:00
2008-12-21 00:30:16 +00:00
$prefs = array ();
2008-06-13 15:49:13 +01:00
2008-12-21 00:30:16 +00:00
$parts = explode ( ',' , $accept );
2008-06-13 15:49:13 +01:00
2008-12-21 00:30:16 +00:00
foreach ( $parts as $part ) {
// FIXME: doesn't deal with params like 'text/html; level=1'
@ list ( $value , $qpart ) = explode ( ';' , $part );
$match = array ();
if ( ! isset ( $qpart )) {
$prefs [ $value ] = 1 ;
} elseif ( preg_match ( '/q\s*=\s*(\d*\.\d+)/' , $qpart , $match )) {
$prefs [ $value ] = $match [ 1 ];
}
}
2008-06-13 15:49:13 +01:00
2008-12-21 00:30:16 +00:00
return $prefs ;
2008-06-13 15:49:13 +01:00
}
2008-12-23 19:33:23 +00:00
function common_mime_type_match ( $type , $avail )
{
2008-12-21 00:30:16 +00:00
if ( array_key_exists ( $type , $avail )) {
return $type ;
} else {
$parts = explode ( '/' , $type );
if ( array_key_exists ( $parts [ 0 ] . '/*' , $avail )) {
return $parts [ 0 ] . '/*' ;
} elseif ( array_key_exists ( '*/*' , $avail )) {
return '*/*' ;
} else {
return null ;
}
}
2008-06-13 15:49:13 +01:00
}
2008-12-23 19:33:23 +00:00
function common_negotiate_type ( $cprefs , $sprefs )
{
2008-12-21 00:30:16 +00:00
$combine = array ();
foreach ( array_keys ( $sprefs ) as $type ) {
$parts = explode ( '/' , $type );
if ( $parts [ 1 ] != '*' ) {
$ckey = common_mime_type_match ( $type , $cprefs );
if ( $ckey ) {
$combine [ $type ] = $sprefs [ $type ] * $cprefs [ $ckey ];
}
}
}
foreach ( array_keys ( $cprefs ) as $type ) {
$parts = explode ( '/' , $type );
if ( $parts [ 1 ] != '*' && ! array_key_exists ( $type , $sprefs )) {
$skey = common_mime_type_match ( $type , $sprefs );
if ( $skey ) {
$combine [ $type ] = $sprefs [ $skey ] * $cprefs [ $type ];
}
}
}
$bestq = 0 ;
$besttype = " text/html " ;
foreach ( array_keys ( $combine ) as $type ) {
if ( $combine [ $type ] > $bestq ) {
$besttype = $type ;
$bestq = $combine [ $type ];
}
}
return $besttype ;
2008-06-13 15:49:13 +01:00
}
2008-06-13 18:53:44 +01:00
2008-12-23 19:33:23 +00:00
function common_config ( $main , $sub )
{
2008-12-21 00:30:16 +00:00
global $config ;
return isset ( $config [ $main ][ $sub ]) ? $config [ $main ][ $sub ] : false ;
2008-06-13 18:53:44 +01:00
}
2008-06-19 15:11:07 +01:00
2008-12-23 19:33:23 +00:00
function common_copy_args ( $from )
{
2008-12-21 00:30:16 +00:00
$to = array ();
$strip = get_magic_quotes_gpc ();
foreach ( $from as $k => $v ) {
$to [ $k ] = ( $strip ) ? stripslashes ( $v ) : $v ;
}
return $to ;
2008-06-20 07:54:55 +01:00
}
2008-06-20 08:17:00 +01:00
2008-09-04 07:55:04 +01:00
// Neutralise the evil effects of magic_quotes_gpc in the current request.
// This is used before handing a request off to OAuthRequest::from_request.
2008-12-23 19:33:23 +00:00
function common_remove_magic_from_request ()
{
2008-12-21 00:30:16 +00:00
if ( get_magic_quotes_gpc ()) {
$_POST = array_map ( 'stripslashes' , $_POST );
$_GET = array_map ( 'stripslashes' , $_GET );
}
2008-09-04 07:55:04 +01:00
}
2008-12-23 19:33:23 +00:00
function common_user_uri ( & $user )
{
2008-12-21 00:30:16 +00:00
return common_local_url ( 'userbyid' , array ( 'id' => $user -> id ));
2008-06-20 08:17:00 +01:00
}
2008-12-23 19:33:23 +00:00
function common_notice_uri ( & $notice )
{
2008-12-21 00:30:16 +00:00
return common_local_url ( 'shownotice' ,
array ( 'notice' => $notice -> id ));
2008-06-20 08:17:00 +01:00
}
2008-06-22 17:32:41 +01:00
2008-12-21 00:30:16 +00:00
// 36 alphanums - lookalikes (0, O, 1, I) = 32 chars = 5 bits
2008-06-22 17:32:41 +01:00
2008-12-23 19:33:23 +00:00
function common_confirmation_code ( $bits )
{
2008-12-21 00:30:16 +00:00
// 36 alphanums - lookalikes (0, O, 1, I) = 32 chars = 5 bits
static $codechars = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ' ;
$chars = ceil ( $bits / 5 );
$code = '' ;
for ( $i = 0 ; $i < $chars ; $i ++ ) {
// XXX: convert to string and back
$num = hexdec ( common_good_rand ( 1 ));
// XXX: randomness is too precious to throw away almost
// 40% of the bits we get!
$code .= $codechars [ $num % 32 ];
}
return $code ;
}
// convert markup to HTML
2008-06-30 18:03:42 +01:00
2008-12-23 19:33:23 +00:00
function common_markup_to_html ( $c )
{
2008-12-21 00:30:16 +00:00
$c = preg_replace ( '/%%action.(\w+)%%/e' , " common_local_url(' \\ 1') " , $c );
$c = preg_replace ( '/%%doc.(\w+)%%/e' , " common_local_url('doc', array('title'=>' \\ 1')) " , $c );
$c = preg_replace ( '/%%(\w+).(\w+)%%/e' , 'common_config(\'\\1\', \'\\2\')' , $c );
return Markdown ( $c );
2008-06-30 18:03:42 +01:00
}
2008-07-14 04:44:43 +01:00
2008-12-23 19:33:23 +00:00
function common_profile_avatar_url ( $profile , $size = AVATAR_PROFILE_SIZE )
{
2008-12-21 00:30:16 +00:00
$avatar = $profile -> getAvatar ( $size );
if ( $avatar ) {
return common_avatar_display_url ( $avatar );
} else {
return common_default_avatar ( $size );
}
2008-07-14 04:44:43 +01:00
}
2008-07-16 16:25:11 +01:00
2008-12-23 19:33:23 +00:00
function common_profile_uri ( $profile )
{
2008-12-21 00:30:16 +00:00
if ( ! $profile ) {
return null ;
}
$user = User :: staticGet ( $profile -> id );
if ( $user ) {
return $user -> uri ;
}
$remote = Remote_profile :: staticGet ( $profile -> id );
if ( $remote ) {
return $remote -> uri ;
}
// XXX: this is a very bad profile!
return null ;
2008-07-20 20:30:05 +01:00
}
2008-12-23 19:33:23 +00:00
function common_canonical_sms ( $sms )
{
2008-12-21 00:30:16 +00:00
// strip non-digits
preg_replace ( '/\D/' , '' , $sms );
return $sms ;
2008-07-29 09:06:41 +01:00
}
2008-08-29 18:40:12 +01:00
2008-12-23 19:33:23 +00:00
function common_error_handler ( $errno , $errstr , $errfile , $errline , $errcontext )
{
2008-08-29 18:40:12 +01:00
switch ( $errno ) {
case E_USER_ERROR :
2008-12-21 00:30:16 +00:00
common_log ( LOG_ERR , " [ $errno ] $errstr ( $errfile : $errline ) " );
exit ( 1 );
break ;
2008-08-29 18:40:12 +01:00
2008-12-21 00:30:16 +00:00
case E_USER_WARNING :
common_log ( LOG_WARNING , " [ $errno ] $errstr ( $errfile : $errline ) " );
break ;
2008-08-29 18:40:12 +01:00
case E_USER_NOTICE :
2008-12-21 00:30:16 +00:00
common_log ( LOG_NOTICE , " [ $errno ] $errstr ( $errfile : $errline ) " );
break ;
2008-08-29 18:40:12 +01:00
}
2008-12-21 00:30:16 +00:00
// FIXME: show error page if we're on the Web
2008-08-29 18:40:12 +01:00
/* Don't execute PHP internal error handler */
return true ;
}
2008-12-23 19:33:23 +00:00
function common_session_token ()
{
2008-12-21 00:30:16 +00:00
common_ensure_session ();
if ( ! array_key_exists ( 'token' , $_SESSION )) {
$_SESSION [ 'token' ] = common_good_rand ( 64 );
}
return $_SESSION [ 'token' ];
2008-08-29 18:40:12 +01:00
}
2008-09-15 07:56:16 +01:00
2008-12-23 19:33:23 +00:00
function common_disfavor_form ( $notice )
{
2008-12-21 00:30:16 +00:00
common_element_start ( 'form' , array ( 'id' => 'disfavor-' . $notice -> id ,
'method' => 'post' ,
'class' => 'disfavor' ,
'action' => common_local_url ( 'disfavor' )));
common_element ( 'input' , array ( 'type' => 'hidden' ,
'name' => 'token-' . $notice -> id ,
'id' => 'token-' . $notice -> id ,
'class' => 'token' ,
'value' => common_session_token ()));
common_element ( 'input' , array ( 'type' => 'hidden' ,
'name' => 'notice' ,
'id' => 'notice-n' . $notice -> id ,
'class' => 'notice' ,
'value' => $notice -> id ));
common_element ( 'input' , array ( 'type' => 'submit' ,
'id' => 'disfavor-submit-' . $notice -> id ,
'name' => 'disfavor-submit-' . $notice -> id ,
'class' => 'disfavor' ,
'value' => 'Disfavor favorite' ,
'title' => 'Remove this message from favorites' ));
common_element_end ( 'form' );
2008-09-08 19:16:24 +01:00
}
2008-12-23 19:33:23 +00:00
function common_favor_form ( $notice )
{
2008-12-21 00:30:16 +00:00
common_element_start ( 'form' , array ( 'id' => 'favor-' . $notice -> id ,
'method' => 'post' ,
'class' => 'favor' ,
'action' => common_local_url ( 'favor' )));
common_element ( 'input' , array ( 'type' => 'hidden' ,
'name' => 'token-' . $notice -> id ,
'id' => 'token-' . $notice -> id ,
'class' => 'token' ,
'value' => common_session_token ()));
common_element ( 'input' , array ( 'type' => 'hidden' ,
'name' => 'notice' ,
'id' => 'notice-n' . $notice -> id ,
'class' => 'notice' ,
'value' => $notice -> id ));
common_element ( 'input' , array ( 'type' => 'submit' ,
'id' => 'favor-submit-' . $notice -> id ,
'name' => 'favor-submit-' . $notice -> id ,
'class' => 'favor' ,
'value' => 'Add to favorites' ,
'title' => 'Add this message to favorites' ));
common_element_end ( 'form' );
2008-09-08 19:16:24 +01:00
}
2008-12-23 19:33:23 +00:00
function common_nudge_form ( $profile )
{
2008-12-21 00:30:16 +00:00
common_element_start ( 'form' , array ( 'id' => 'nudge' , 'method' => 'post' ,
'action' => common_local_url ( 'nudge' , array ( 'nickname' => $profile -> nickname ))));
common_hidden ( 'token' , common_session_token ());
common_element ( 'input' , array ( 'type' => 'submit' ,
'class' => 'submit' ,
'value' => _ ( 'Send a nudge' )));
common_element_end ( 'form' );
2008-11-16 02:27:35 +00:00
}
2008-12-23 19:33:23 +00:00
function common_nudge_response ()
{
2008-12-21 00:30:16 +00:00
common_element ( 'p' , array ( 'id' => 'nudge_response' ), _ ( 'Nudge sent!' ));
2008-11-20 23:26:55 +00:00
}
2008-11-16 02:27:35 +00:00
2008-12-23 19:33:23 +00:00
function common_subscribe_form ( $profile )
{
2008-12-21 00:30:16 +00:00
common_element_start ( 'form' , array ( 'id' => 'subscribe-' . $profile -> id ,
'method' => 'post' ,
'class' => 'subscribe' ,
'action' => common_local_url ( 'subscribe' )));
common_hidden ( 'token' , common_session_token ());
common_element ( 'input' , array ( 'id' => 'subscribeto-' . $profile -> id ,
'name' => 'subscribeto' ,
'type' => 'hidden' ,
'value' => $profile -> id ));
common_element ( 'input' , array ( 'type' => 'submit' ,
'class' => 'submit' ,
'value' => _ ( 'Subscribe' )));
common_element_end ( 'form' );
2008-11-18 17:48:57 +00:00
}
2008-12-23 19:33:23 +00:00
function common_unsubscribe_form ( $profile )
{
2008-12-21 00:30:16 +00:00
common_element_start ( 'form' , array ( 'id' => 'unsubscribe-' . $profile -> id ,
'method' => 'post' ,
'class' => 'unsubscribe' ,
'action' => common_local_url ( 'unsubscribe' )));
common_hidden ( 'token' , common_session_token ());
common_element ( 'input' , array ( 'id' => 'unsubscribeto-' . $profile -> id ,
'name' => 'unsubscribeto' ,
'type' => 'hidden' ,
'value' => $profile -> id ));
common_element ( 'input' , array ( 'type' => 'submit' ,
'class' => 'submit' ,
'value' => _ ( 'Unsubscribe' )));
common_element_end ( 'form' );
2008-11-18 17:48:57 +00:00
}
2008-11-20 23:26:55 +00:00
// XXX: Refactor this code
2008-12-23 19:33:23 +00:00
function common_profile_new_message_nudge ( $cur , $profile )
{
2008-12-21 00:30:16 +00:00
$user = User :: staticGet ( 'id' , $profile -> id );
2008-11-20 23:26:55 +00:00
2008-12-21 00:30:16 +00:00
if ( $cur && $cur -> id != $user -> id && $cur -> mutuallySubscribed ( $user )) {
2008-11-20 23:26:55 +00:00
common_element_start ( 'li' , array ( 'id' => 'profile_send_a_new_message' ));
2008-12-21 00:30:16 +00:00
common_element ( 'a' , array ( 'href' => common_local_url ( 'newmessage' , array ( 'to' => $user -> id ))),
_ ( 'Send a message' ));
2008-11-20 23:26:55 +00:00
common_element_end ( 'li' );
2008-12-03 03:27:43 +00:00
2008-12-21 00:30:16 +00:00
if ( $user -> email && $user -> emailnotifynudge ) {
2008-11-20 23:26:55 +00:00
common_element_start ( 'li' , array ( 'id' => 'profile_nudge' ));
common_nudge_form ( $user );
common_element_end ( 'li' );
}
2008-12-21 00:30:16 +00:00
}
2008-11-16 02:27:35 +00:00
}
2008-12-23 19:33:23 +00:00
function common_cache_key ( $extra )
{
2008-12-21 00:30:16 +00:00
return 'laconica:' . common_keyize ( common_config ( 'site' , 'name' )) . ':' . $extra ;
2008-09-15 07:56:16 +01:00
}
2008-12-23 19:33:23 +00:00
function common_keyize ( $str )
{
2008-12-21 00:30:16 +00:00
$str = strtolower ( $str );
$str = preg_replace ( '/\s/' , '_' , $str );
return $str ;
2008-09-15 07:56:16 +01:00
}
2008-09-24 21:41:31 +01:00
2008-12-23 19:33:23 +00:00
function common_message_form ( $content , $user , $to )
{
2008-12-03 03:27:43 +00:00
2008-12-21 00:30:16 +00:00
common_element_start ( 'form' , array ( 'id' => 'message_form' ,
'method' => 'post' ,
'action' => common_local_url ( 'newmessage' )));
2008-12-03 03:27:43 +00:00
2008-12-21 00:30:16 +00:00
$mutual_users = $user -> mutuallySubscribedUsers ();
2008-12-03 03:27:43 +00:00
2008-12-21 00:30:16 +00:00
$mutual = array ();
2008-12-03 03:27:43 +00:00
2008-12-21 00:30:16 +00:00
while ( $mutual_users -> fetch ()) {
if ( $mutual_users -> id != $user -> id ) {
$mutual [ $mutual_users -> id ] = $mutual_users -> nickname ;
}
}
2008-12-03 03:27:43 +00:00
2008-12-21 00:30:16 +00:00
$mutual_users -> free ();
unset ( $mutual_users );
2008-12-03 03:27:43 +00:00
2008-12-23 19:44:28 +00:00
common_dropdown ( 'to' , _ ( 'To' ), $mutual , null , false , $to -> id );
2008-12-03 03:27:43 +00:00
2008-12-21 00:30:16 +00:00
common_element_start ( 'p' );
2008-12-03 03:27:43 +00:00
2008-12-21 00:30:16 +00:00
common_element ( 'textarea' , array ( 'id' => 'message_content' ,
'cols' => 60 ,
'rows' => 3 ,
'name' => 'content' ),
( $content ) ? $content : '' );
2008-12-03 03:27:43 +00:00
2008-12-21 00:30:16 +00:00
common_element ( 'input' , array ( 'id' => 'message_send' ,
'name' => 'message_send' ,
'type' => 'submit' ,
'value' => _ ( 'Send' )));
2008-12-03 03:27:43 +00:00
2008-12-21 00:30:16 +00:00
common_hidden ( 'token' , common_session_token ());
2008-12-03 03:27:43 +00:00
2008-12-21 00:30:16 +00:00
common_element_end ( 'p' );
common_element_end ( 'form' );
2008-09-26 21:01:02 +01:00
}
2008-12-23 19:33:23 +00:00
function common_memcache ()
{
2008-12-21 00:30:16 +00:00
static $cache = null ;
if ( ! common_config ( 'memcached' , 'enabled' )) {
return null ;
} else {
if ( ! $cache ) {
$cache = new Memcache ();
$servers = common_config ( 'memcached' , 'server' );
if ( is_array ( $servers )) {
foreach ( $servers as $server ) {
$cache -> addServer ( $server );
}
} else {
$cache -> addServer ( $servers );
}
}
return $cache ;
}
2008-09-26 21:01:02 +01:00
}
2008-12-03 03:27:05 +00:00
2008-12-23 19:33:23 +00:00
function common_compatible_license ( $from , $to )
{
2008-12-21 00:30:16 +00:00
// XXX: better compatibility check needed here!
return ( $from == $to );
2008-12-04 18:02:33 +00:00
}
2008-12-08 05:55:11 +00:00
2008-12-08 17:37:22 +00:00
/* These are almost identical, so we use a helper function */
2008-12-23 19:33:23 +00:00
function common_block_form ( $profile , $args = null )
{
2008-12-08 17:37:22 +00:00
common_blocking_form ( 'block' , _ ( 'Block' ), $profile , $args );
}
2008-12-23 19:33:23 +00:00
function common_unblock_form ( $profile , $args = null )
{
2008-12-08 17:37:22 +00:00
common_blocking_form ( 'unblock' , _ ( 'Unblock' ), $profile , $args );
}
2008-12-23 19:33:23 +00:00
function common_blocking_form ( $type , $label , $profile , $args = null )
{
2008-12-08 17:37:22 +00:00
common_element_start ( 'form' , array ( 'id' => $type . '-' . $profile -> id ,
2008-12-08 05:55:11 +00:00
'method' => 'post' ,
2008-12-08 17:37:22 +00:00
'class' => $type ,
'action' => common_local_url ( $type )));
2008-12-08 05:55:11 +00:00
common_hidden ( 'token' , common_session_token ());
2008-12-08 17:37:22 +00:00
common_element ( 'input' , array ( 'id' => $type . 'to-' . $profile -> id ,
'name' => $type . 'to' ,
2008-12-08 05:55:11 +00:00
'type' => 'hidden' ,
'value' => $profile -> id ));
common_element ( 'input' , array ( 'type' => 'submit' ,
'class' => 'submit' ,
2008-12-08 17:37:22 +00:00
'name' => $type ,
'value' => $label ));
2008-12-08 17:09:31 +00:00
if ( $args ) {
foreach ( $args as $k => $v ) {
common_hidden ( 'returnto-' . $k , $v );
}
}
2008-12-08 05:55:11 +00:00
common_element_end ( 'form' );
return ;
}