Merge branch '0.8.x' of git@gitorious.org:laconica/mainline into 0.8.x

This commit is contained in:
Sarven Capadisli 2009-08-04 15:53:15 +00:00
commit d0a020dd4e
22 changed files with 713 additions and 52 deletions

2
.gitignore vendored
View File

@ -23,4 +23,4 @@ config-*.php
good-config.php
lac08.log
php.log
config.php.*

View File

@ -130,6 +130,7 @@ class ApiAction extends Action
'laconica/wadl',
'tags/timeline',
'oembed/oembed',
'groups/show',
'groups/timeline');
static $bareauth = array('statuses/user_timeline',

View File

@ -167,6 +167,8 @@ class ConversationTree extends NoticeList
function _buildTree()
{
$cnt = 0;
$this->tree = array();
$this->table = array();

View File

@ -207,32 +207,10 @@ class TwitapifavoritesAction extends TwitterapiAction
$other = User::staticGet('id', $notice->profile_id);
if ($other && $other->id != $user->id) {
if ($other->email && $other->emailnotifyfav) {
$this->notify_mail($other, $user, $notice);
mail_notify_fave($other, $user, $notice);
}
# XXX: notify by IM
# XXX: notify by SMS
}
}
function notify_mail($other, $user, $notice)
{
$profile = $user->getProfile();
$bestname = $profile->getBestName();
$subject = sprintf(_('%s added your notice as a favorite'), $bestname);
$body = sprintf(_("%1\$s just added your notice from %2\$s as one of their favorites.\n\n" .
"In case you forgot, you can see the text of your notice here:\n\n" .
"%3\$s\n\n" .
"You can see the list of %1\$s's favorites here:\n\n" .
"%4\$s\n\n" .
"Faithfully yours,\n" .
"%5\$s\n"),
$bestname,
common_exact_date($notice->created),
common_local_url('shownotice', array('notice' => $notice->id)),
common_local_url('showfavorites', array('nickname' => $user->nickname)),
common_config('site', 'name'));
mail_to_user($other, $subject, $body);
}
}
}

View File

@ -51,6 +51,32 @@ require_once INSTALLDIR.'/lib/twitterapi.php';
class TwitapigroupsAction extends TwitterapiAction
{
function show($args, $apidata)
{
parent::handle($args);
common_debug("in groups api action");
$this->auth_user = $apidata['user'];
$group = $this->get_group($apidata['api_arg'], $apidata);
if (empty($group)) {
$this->clientError('Not Found', 404, $apidata['content-type']);
return;
}
switch($apidata['content-type']) {
case 'xml':
$this->show_single_xml_group($group);
break;
case 'json':
$this->show_single_json_group($group);
break;
default:
$this->clientError(_('API method not found!'), $code = 404);
}
}
function timeline($args, $apidata)
{
parent::handle($args);
@ -88,8 +114,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php';
$this->show_xml_timeline($notice);
break;
case 'rss':
$this->show_rss_timeline($notice, $title, $link,
$subtitle, $suplink);
$this->show_rss_timeline($notice, $title, $link, $subtitle);
break;
case 'atom':
if (isset($apidata['api_arg'])) {
@ -101,7 +126,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php';
'api/laconica/groups/timeline.atom';
}
$this->show_atom_timeline($notice, $title, $id, $link,
$subtitle, $suplink, $selfuri);
$subtitle, null, $selfuri);
break;
case 'json':
$this->show_json_timeline($notice);

View File

@ -88,8 +88,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php';
$this->show_xml_timeline($notice);
break;
case 'rss':
$this->show_rss_timeline($notice, $title, $link,
$subtitle, $suplink);
$this->show_rss_timeline($notice, $title, $link, $subtitle);
break;
case 'atom':
if (isset($apidata['api_arg'])) {
@ -101,7 +100,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php';
'api/laconica/tags/timeline.atom';
}
$this->show_atom_timeline($notice, $title, $id, $link,
$subtitle, $suplink, $selfuri);
$subtitle, null, $selfuri);
break;
case 'json':
$this->show_json_timeline($notice);

View File

@ -93,7 +93,6 @@ class File extends Memcached_DataObject
if (empty($file)) {
$file_redir = File_redirection::staticGet('url', $given_url);
if (empty($file_redir)) {
common_debug("processNew() '$given_url' not a known redirect.\n");
$redir_data = File_redirection::where($given_url);
$redir_url = $redir_data['url'];
if ($redir_url === $given_url) {
@ -114,7 +113,9 @@ class File extends Memcached_DataObject
if (empty($x)) {
$x = File::staticGet($file_id);
if (empty($x)) die('Impossible!');
if (empty($x)) {
throw new ServerException("Robin thinks something is impossible.");
}
}
File_to_post::processNew($file_id, $notice_id);

View File

@ -108,11 +108,24 @@ class Session extends Memcached_DataObject
$epoch = common_sql_date(time() - $maxlifetime);
$ids = array();
$session = new Session();
$session->whereAdd('modified < "'.$epoch.'"');
$result = $session->delete(DB_DATAOBJECT_WHEREADD_ONLY);
$session->selectAdd();
$session->selectAdd('id');
self::logdeb("garbage collection result = $result");
$session->find();
while ($session->fetch()) {
$ids[] = $session->id;
}
$session->free();
foreach ($ids as $id) {
self::destroy($id);
}
}
static function setSaveHandler()

108
db/074to080_pg.sql Normal file
View File

@ -0,0 +1,108 @@
BEGIN;
create sequence design_seq;
create table design (
id bigint default nextval('design_seq') /* comment 'design ID'*/,
backgroundcolor integer /* comment 'main background color'*/ ,
contentcolor integer /*comment 'content area background color'*/ ,
sidebarcolor integer /*comment 'sidebar background color'*/ ,
textcolor integer /*comment 'text color'*/ ,
linkcolor integer /*comment 'link color'*/,
backgroundimage varchar(255) /*comment 'background image, if any'*/,
disposition int default 1 /*comment 'bit 1 = hide background image, bit 2 = display background image, bit 4 = tile background image'*/,
primary key (id)
);
alter table "user"
add column design_id integer references design(id);
alter table "user"
add column viewdesigns integer default 1;
alter table notice add column
conversation integer references notice (id);
create index notice_conversation_idx on notice(conversation);
alter table foreign_user
alter column id TYPE bigint;
alter table foreign_user alter column id set not null;
alter table foreign_link
alter column foreign_id TYPE bigint;
alter table user_group
add column design_id integer;
/*attachments and URLs stuff */
create sequence file_seq;
create table file (
id bigint default nextval('file_seq') primary key /* comment 'unique identifier' */,
url varchar(255) unique,
mimetype varchar(50),
size integer,
title varchar(255),
date integer,
protected integer,
filename text /* comment 'if a local file, name of the file' */,
modified timestamp default CURRENT_TIMESTAMP /* comment 'date this record was modified'*/
);
create sequence file_oembed_seq;
create table file_oembed (
file_id bigint default nextval('file_oembed_seq') primary key /* comment 'unique identifier' */,
version varchar(20),
type varchar(20),
provider varchar(50),
provider_url varchar(255),
width integer,
height integer,
html text,
title varchar(255),
author_name varchar(50),
author_url varchar(255),
url varchar(255)
);
create sequence file_redirection_seq;
create table file_redirection (
url varchar(255) primary key,
file_id bigint,
redirections integer,
httpcode integer
);
create sequence file_thumbnail_seq;
create table file_thumbnail (
file_id bigint primary key,
url varchar(255) unique,
width integer,
height integer
);
create sequence file_to_post_seq;
create table file_to_post (
file_id bigint,
post_id bigint,
primary key (file_id, post_id)
);
create table group_block (
group_id integer not null /* comment 'group profile is blocked from' */ references user_group (id),
blocked integer not null /* comment 'profile that is blocked' */references profile (id),
blocker integer not null /* comment 'user making the block'*/ references "user" (id),
modified timestamp /* comment 'date of blocking'*/ ,
primary key (group_id, blocked)
);
create table group_alias (
alias varchar(64) /* comment 'additional nickname for the group'*/ ,
group_id integer not null /* comment 'group profile is blocked from'*/ references user_group (id),
modified timestamp /* comment 'date alias was created'*/,
primary key (alias)
);
create index group_alias_group_id_idx on group_alias (group_id);
COMMIT;

View File

@ -107,6 +107,25 @@ function checkMirror($action_obj)
function main()
{
// fake HTTP redirects using lighttpd's 404 redirects
if (strpos($_SERVER['SERVER_SOFTWARE'], 'lighttpd') !== false) {
$_lighty_url = $base_url.$_SERVER['REQUEST_URI'];
$_lighty_url = @parse_url($_lighty_url);
if ($_lighty_url['path'] != '/index.php' && $_lighty_url['path'] != '/') {
$_lighty_path = preg_replace('/^'.preg_quote(common_config('site','path')).'\//', '', substr($_lighty_url['path'], 1));
$_SERVER['QUERY_STRING'] = 'p='.$_lighty_path;
if ($_lighty_url['query'])
$_SERVER['QUERY_STRING'] .= '&'.$_lighty_url['query'];
parse_str($_lighty_url['query'], $_lighty_query);
foreach ($_lighty_query as $key => $val) {
$_GET[$key] = $_REQUEST[$key] = $val;
}
$_GET['p'] = $_REQUEST['p'] = $_lighty_path;
}
}
$_SERVER['REDIRECT_URL'] = preg_replace("/\?.+$/", "", $_SERVER['REQUEST_URI']);
// quick check for fancy URL auto-detection support in installer.
if (isset($_SERVER['REDIRECT_URL']) && (preg_replace("/^\/$/","",(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.");

View File

@ -163,7 +163,7 @@ E_O_T;
function updateStatus($status, $error=false)
{
?>
<li <?php echo ($error) ? 'class="error"': ''; ?>><?print $status;?></li>
<li <?php echo ($error) ? 'class="error"': ''; ?>><?php echo $status;?></li>
<?php
}

View File

@ -25,7 +25,7 @@ $(document).ready(function(){
var counter = $("#notice_text-count");
counter.text(remaining);
if (remaining <= 0) {
if (remaining < 0) {
$("#form_notice").addClass("warning");
} else {
$("#form_notice").removeClass("warning");
@ -256,10 +256,15 @@ function NoticeReplySet(nick,id) {
rgx_username = /^[0-9a-zA-Z\-_.]*$/;
if (nick.match(rgx_username)) {
replyto = "@" + nick + " ";
if ($("#notice_data-text").length) {
$("#notice_data-text").val(replyto);
var text = $("#notice_data-text");
if (text.length) {
text.val(replyto + text.val());
$("#form_notice input#notice_in-reply-to").val(id);
$("#notice_data-text").focus();
if (text.get(0).setSelectionRange) {
var len = text.val().length;
text.get(0).setSelectionRange(len,len);
text.get(0).focus();
}
return false;
}
}

View File

@ -97,7 +97,7 @@ class ProfileSection extends Section
$this->out->elementEnd('a');
$this->out->elementEnd('span');
$this->out->elementEnd('td');
if ($profile->value) {
if (isset($profile->value)) {
$this->out->element('td', 'value', $profile->value);
}

View File

@ -213,6 +213,26 @@ class TwitterapiAction extends Action
return $twitter_status;
}
function twitter_group_array($group)
{
$twitter_group=array();
$twitter_group['id']=$group->id;
$twitter_group['url']=$group->permalink();
$twitter_group['nickname']=$group->nickname;
$twitter_group['fullname']=$group->fullname;
$twitter_group['homepage_url']=$group->homepage_url;
$twitter_group['original_logo']=$group->original_logo;
$twitter_group['homepage_logo']=$group->homepage_logo;
$twitter_group['stream_logo']=$group->stream_logo;
$twitter_group['mini_logo']=$group->mini_logo;
$twitter_group['homepage']=$group->homepage;
$twitter_group['description']=$group->description;
$twitter_group['location']=$group->location;
$twitter_group['created']=$this->date_twitter($group->created);
$twitter_group['modified']=$this->date_twitter($group->modified);
return $twitter_group;
}
function twitter_rss_entry_array($notice)
{
$profile = $notice->getProfile();
@ -413,6 +433,15 @@ class TwitterapiAction extends Action
$this->elementEnd('status');
}
function show_twitter_xml_group($twitter_group)
{
$this->elementStart('group');
foreach($twitter_group as $element => $value) {
$this->element($element, null, $value);
}
$this->elementEnd('group');
}
function show_twitter_xml_user($twitter_user, $role='user')
{
$this->elementStart($role);
@ -450,12 +479,12 @@ class TwitterapiAction extends Action
$this->element('link', null, $entry['link']);
# RSS only supports 1 enclosure per item
if($entry['enclosures']){
if(array_key_exists('enclosures', $entry) and !empty($entry['enclosures'])){
$enclosure = $entry['enclosures'][0];
$this->element('enclosure', array('url'=>$enclosure['url'],'type'=>$enclosure['mimetype'],'length'=>$enclosure['size']), null);
}
if($entry['tags']){
if(array_key_exists('tags', $entry)){
foreach($entry['tags'] as $tag){
$this->element('category', null,$tag);
}
@ -639,6 +668,22 @@ class TwitterapiAction extends Action
$this->end_document('json');
}
function show_single_json_group($group)
{
$this->init_document('json');
$twitter_group = $this->twitter_group_array($group);
$this->show_json_objects($twitter_group);
$this->end_document('json');
}
function show_single_xml_group($group)
{
$this->init_document('xml');
$twitter_group = $this->twitter_group_array($group);
$this->show_twitter_xml_group($twitter_group);
$this->end_document('xml');
}
// Anyone know what date format this is?
// Twitter's dates look like this: "Mon Jul 14 23:52:38 +0000 2008" -- Zach
function date_twitter($dt)

View File

@ -140,7 +140,7 @@ function common_have_session()
function common_ensure_session()
{
$c = null;
if (array_key_exists(session_name, $_COOKIE)) {
if (array_key_exists(session_name(), $_COOKIE)) {
$c = $_COOKIE[session_name()];
}
if (!common_have_session()) {
@ -1410,20 +1410,21 @@ function common_client_ip()
return null;
}
if ($_SERVER['HTTP_X_FORWARDED_FOR']) {
if ($_SERVER['HTTP_CLIENT_IP']) {
if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
if (array_key_exists('HTTP_CLIENT_IP', $_SERVER)) {
$proxy = $_SERVER['HTTP_CLIENT_IP'];
} else {
$proxy = $_SERVER['REMOTE_ADDR'];
}
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
if ($_SERVER['HTTP_CLIENT_IP']) {
$proxy = null;
if (array_key_exists('HTTP_CLIENT_IP', $_SERVER)) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
}
return array($ip, $proxy);
return array($proxy, $ip);
}

2
lighttpd.conf.example Normal file
View File

@ -0,0 +1,2 @@
# Add this line to lighttpd.conf to enable pseudo-rewrites using 404s
server.error-handler-404 = "/index.php"

View File

@ -122,9 +122,7 @@ class FBConnectPlugin extends Plugin
FB_RequireFeatures(
["XFBML"],
function() {
FB.init("%s", "../xd_receiver.html",
{"doNotUseCachedConnectState":true });
FB.init("%s", "../xd_receiver.html");
}
); }
@ -222,7 +220,7 @@ class FBConnectPlugin extends Plugin
try {
$facebook = getFacebook();
$fbuid = $facebook->api_client->users_getLoggedInUser();
$fbuid = $facebook->get_loggedin_user();
} catch (Exception $e) {
common_log(LOG_WARNING,

22
plugins/recaptcha/LICENSE Normal file
View File

@ -0,0 +1,22 @@
Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
AUTHORS:
Mike Crawford
Ben Maurer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

23
plugins/recaptcha/README Normal file
View File

@ -0,0 +1,23 @@
Laconica reCAPTCHA plugin 0.2 8/3/09
====================================
Adds a captcha to your registration page to reduce automated spam bots registering.
Use:
1. Get an API key from http://recaptcha.net
2. In config.php add:
include_once('plugins/recaptcha.php');
$captcha = new recaptcha(publickey, privatekey, showErrors);
Changelog
=========
0.1 initial release
0.2 Work around for webkit browsers
reCAPTCHA README
================
The reCAPTCHA PHP Lirary helps you use the reCAPTCHA API. Documentation
for this library can be found at
http://recaptcha.net/plugins/php

View File

@ -0,0 +1,106 @@
<?php
/**
* Laconica, the distributed open-source microblogging tool
*
* Plugin to show reCaptcha when a user registers
*
* PHP version 5
*
* LICENCE: 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/>.
*
* @category Plugin
* @package Laconica
* @author Eric Helgeson <erichelgeson@gmail.com>
* @copyright 2009
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*/
if (!defined('LACONICA')) {
exit(1);
}
define('RECAPTCHA', '0.2');
class recaptcha extends Plugin
{
var $private_key;
var $public_key;
var $display_errors;
var $failed;
var $ssl;
function __construct($public_key, $private_key, $display_errors=false)
{
parent::__construct();
require_once(INSTALLDIR.'/plugins/recaptcha/recaptchalib.php');
$this->public_key = $public_key;
$this->private_key = $private_key;
$this->display_errors = $display_errors;
}
function checkssl(){
if(common_config('site', 'ssl') === 'sometimes' || common_config('site', 'ssl') === 'always') {
return true;
}
return false;
}
function onStartShowHTML($action)
{
//XXX: Horrible hack to make Safari, FF2, and Chrome work with
//reChapcha. reChapcha beaks xhtml strict
header('Content-Type: text/html');
$action->extraHeaders();
$action->startXML('html',
'-//W3C//DTD XHTML 1.0 Strict//EN',
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd');
$action->raw('<style type="text/css">#recaptcha_area{float:left;}</style>');
return false;
}
function onEndRegistrationFormData($action)
{
$action->elementStart('li');
$action->raw('<label for="recaptcha_area">Captcha</label>');
if($this->checkssl() === true){
$action->raw(recaptcha_get_html($this->public_key), null, true);
} else {
$action->raw(recaptcha_get_html($this->public_key));
}
$action->elementEnd('li');
return true;
}
function onStartRegistrationTry($action)
{
$resp = recaptcha_check_answer ($this->private_key,
$_SERVER["REMOTE_ADDR"],
$action->trimmed('recaptcha_challenge_field'),
$action->trimmed('recaptcha_response_field'));
if (!$resp->is_valid)
{
if($this->display_errors)
{
$action->showForm ("(reCAPTCHA said: " . $resp->error . ")");
}
$action->showForm("Captcha does not match!");
return false;
}
}
}

View File

@ -0,0 +1,277 @@
<?php
/*
* This is a PHP library that handles calling reCAPTCHA.
* - Documentation and latest version
* http://recaptcha.net/plugins/php/
* - Get a reCAPTCHA API Key
* http://recaptcha.net/api/getkey
* - Discussion group
* http://groups.google.com/group/recaptcha
*
* Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
* AUTHORS:
* Mike Crawford
* Ben Maurer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* The reCAPTCHA server URL's
*/
define("RECAPTCHA_API_SERVER", "http://api.recaptcha.net");
define("RECAPTCHA_API_SECURE_SERVER", "https://api-secure.recaptcha.net");
define("RECAPTCHA_VERIFY_SERVER", "api-verify.recaptcha.net");
/**
* Encodes the given data into a query string format
* @param $data - array of string elements to be encoded
* @return string - encoded request
*/
function _recaptcha_qsencode ($data) {
$req = "";
foreach ( $data as $key => $value )
$req .= $key . '=' . urlencode( stripslashes($value) ) . '&';
// Cut the last '&'
$req=substr($req,0,strlen($req)-1);
return $req;
}
/**
* Submits an HTTP POST to a reCAPTCHA server
* @param string $host
* @param string $path
* @param array $data
* @param int port
* @return array response
*/
function _recaptcha_http_post($host, $path, $data, $port = 80) {
$req = _recaptcha_qsencode ($data);
$http_request = "POST $path HTTP/1.0\r\n";
$http_request .= "Host: $host\r\n";
$http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
$http_request .= "Content-Length: " . strlen($req) . "\r\n";
$http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
$http_request .= "\r\n";
$http_request .= $req;
$response = '';
if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
die ('Could not open socket');
}
fwrite($fs, $http_request);
while ( !feof($fs) )
$response .= fgets($fs, 1160); // One TCP-IP packet
fclose($fs);
$response = explode("\r\n\r\n", $response, 2);
return $response;
}
/**
* Gets the challenge HTML (javascript and non-javascript version).
* This is called from the browser, and the resulting reCAPTCHA HTML widget
* is embedded within the HTML form it was called from.
* @param string $pubkey A public key for reCAPTCHA
* @param string $error The error given by reCAPTCHA (optional, default is null)
* @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
* @return string - The HTML to be embedded in the user's form.
*/
function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
{
if ($pubkey == null || $pubkey == '') {
die ("To use reCAPTCHA you must get an API key from <a href='http://recaptcha.net/api/getkey'>http://recaptcha.net/api/getkey</a>");
}
if ($use_ssl) {
$server = RECAPTCHA_API_SECURE_SERVER;
} else {
$server = RECAPTCHA_API_SERVER;
}
$errorpart = "";
if ($error) {
$errorpart = "&amp;error=" . $error;
}
return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script>
<noscript>
<iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
</noscript>';
}
/**
* A ReCaptchaResponse is returned from recaptcha_check_answer()
*/
class ReCaptchaResponse {
var $is_valid;
var $error;
}
/**
* Calls an HTTP POST function to verify if the user's guess was correct
* @param string $privkey
* @param string $remoteip
* @param string $challenge
* @param string $response
* @param array $extra_params an array of extra variables to post to the server
* @return ReCaptchaResponse
*/
function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array())
{
if ($privkey == null || $privkey == '') {
die ("To use reCAPTCHA you must get an API key from <a href='http://recaptcha.net/api/getkey'>http://recaptcha.net/api/getkey</a>");
}
if ($remoteip == null || $remoteip == '') {
die ("For security reasons, you must pass the remote ip to reCAPTCHA");
}
//discard spam submissions
if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
$recaptcha_response = new ReCaptchaResponse();
$recaptcha_response->is_valid = false;
$recaptcha_response->error = 'incorrect-captcha-sol';
return $recaptcha_response;
}
$response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/verify",
array (
'privatekey' => $privkey,
'remoteip' => $remoteip,
'challenge' => $challenge,
'response' => $response
) + $extra_params
);
$answers = explode ("\n", $response [1]);
$recaptcha_response = new ReCaptchaResponse();
if (trim ($answers [0]) == 'true') {
$recaptcha_response->is_valid = true;
}
else {
$recaptcha_response->is_valid = false;
$recaptcha_response->error = $answers [1];
}
return $recaptcha_response;
}
/**
* gets a URL where the user can sign up for reCAPTCHA. If your application
* has a configuration page where you enter a key, you should provide a link
* using this function.
* @param string $domain The domain where the page is hosted
* @param string $appname The name of your application
*/
function recaptcha_get_signup_url ($domain = null, $appname = null) {
return "http://recaptcha.net/api/getkey?" . _recaptcha_qsencode (array ('domain' => $domain, 'app' => $appname));
}
function _recaptcha_aes_pad($val) {
$block_size = 16;
$numpad = $block_size - (strlen ($val) % $block_size);
return str_pad($val, strlen ($val) + $numpad, chr($numpad));
}
/* Mailhide related code */
function _recaptcha_aes_encrypt($val,$ky) {
if (! function_exists ("mcrypt_encrypt")) {
die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
}
$mode=MCRYPT_MODE_CBC;
$enc=MCRYPT_RIJNDAEL_128;
$val=_recaptcha_aes_pad($val);
return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
}
function _recaptcha_mailhide_urlbase64 ($x) {
return strtr(base64_encode ($x), '+/', '-_');
}
/* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
function recaptcha_mailhide_url($pubkey, $privkey, $email) {
if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) {
die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
"you can do so at <a href='http://mailhide.recaptcha.net/apikey'>http://mailhide.recaptcha.net/apikey</a>");
}
$ky = pack('H*', $privkey);
$cryptmail = _recaptcha_aes_encrypt ($email, $ky);
return "http://mailhide.recaptcha.net/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail);
}
/**
* gets the parts of the email to expose to the user.
* eg, given johndoe@example,com return ["john", "example.com"].
* the email is then displayed as john...@example.com
*/
function _recaptcha_mailhide_email_parts ($email) {
$arr = preg_split("/@/", $email );
if (strlen ($arr[0]) <= 4) {
$arr[0] = substr ($arr[0], 0, 1);
} else if (strlen ($arr[0]) <= 6) {
$arr[0] = substr ($arr[0], 0, 3);
} else {
$arr[0] = substr ($arr[0], 0, 4);
}
return $arr;
}
/**
* Gets html to display an email address given a public an private key.
* to get a key, go to:
*
* http://mailhide.recaptcha.net/apikey
*/
function recaptcha_mailhide_html($pubkey, $privkey, $email) {
$emailparts = _recaptcha_mailhide_email_parts ($email);
$url = recaptcha_mailhide_url ($pubkey, $privkey, $email);
return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
"' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
}
?>

36
scripts/sessiongc.php Normal file
View File

@ -0,0 +1,36 @@
#!/usr/bin/env php
<?php
/*
* Laconica - a distributed open-source microblogging tool
* Copyright (C) 2008, 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/>.
*/
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
$helptext = <<<END_OF_GC_HELP
sessiongc.php
Delete old sessions from the server
END_OF_GC_HELP;
require_once INSTALLDIR.'/scripts/commandline.inc';
$maxlifetime = ini_get('session.gc_maxlifetime');
print "Deleting sessions older than $maxlifetime seconds.\n";
Session::gc($maxlifetime);