Merge branch 'master' of /var/www/trunk

This commit is contained in:
Zach Copley 2009-01-23 08:43:34 +00:00
commit 1305ecf4bd
78 changed files with 50881 additions and 25128 deletions

View File

@ -72,10 +72,14 @@ class ApiAction extends Action
}
} else {
# Look for the user in the session
if (common_logged_in()) {
$this->user = common_current_user();
}
# Caller might give us a username even if not required
if (isset($_SERVER['PHP_AUTH_USER'])) {
$user = User::staticGet('nickname', $_SERVER['PHP_AUTH_USER']);
if ($user) {
$this->user = $user;
}
# Twitter doesn't throw an error if the user isn't found
}
$this->process_command();
}

511
actions/grouplogo.php Normal file
View File

@ -0,0 +1,511 @@
<?php
/**
* Laconica, the distributed open-source microblogging tool
*
* Upload an avatar
*
* 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 Settings
* @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca>
* @author Zach Copley <zach@controlyourself.ca>
* @copyright 2008-2009 Control Yourself, Inc.
* @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);
}
require_once INSTALLDIR.'/lib/accountsettingsaction.php';
/**
* Upload an avatar
*
* We use jCrop plugin for jQuery to crop the image after upload.
*
* @category Settings
* @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca>
* @author Zach Copley <zach@controlyourself.ca>
* @author Sarven Capadisli <csarven@controlyourself.ca>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://laconi.ca/
*/
class GrouplogoAction extends Action
{
var $mode = null;
var $imagefile = null;
var $filename = null;
/**
* Prepare to run
*/
function prepare($args)
{
parent::prepare($args);
if (!common_config('inboxes','enabled')) {
$this->serverError(_('Inboxes must be enabled for groups to work'));
return false;
}
if (!common_logged_in()) {
$this->clientError(_('You must be logged in to create a group.'));
return false;
}
$nickname_arg = $this->trimmed('nickname');
$nickname = common_canonical_nickname($nickname_arg);
// Permanent redirect on non-canonical nickname
if ($nickname_arg != $nickname) {
$args = array('nickname' => $nickname);
common_redirect(common_local_url('editgroup', $args), 301);
return false;
}
if (!$nickname) {
$this->clientError(_('No nickname'), 404);
return false;
}
$groupid = $this->trimmed('groupid');
if ($groupid) {
$this->group = User_group::staticGet('id', $groupid);
} else {
$this->group = User_group::staticGet('nickname', $nickname);
}
if (!$this->group) {
$this->clientError(_('No such group'), 404);
return false;
}
$cur = common_current_user();
if (!$cur->isAdmin($this->group)) {
$this->clientError(_('You must be an admin to edit the group'), 403);
return false;
}
return true;
}
function handle($args)
{
parent::handle($args);
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$this->handlePost();
} else {
$this->showForm();
}
}
function showForm($msg = null)
{
$this->msg = $msg;
$this->showPage();
}
/**
* Title of the page
*
* @return string Title of the page
*/
function title()
{
return _('Group logo');
}
/**
* Instructions for use
*
* @return instructions for use
*/
function getInstructions()
{
return _('You can upload a logo image for your group.');
}
/**
* Content area of the page
*
* Shows a form for uploading an avatar.
*
* @return void
*/
function showContent()
{
if ($this->mode == 'crop') {
$this->showCropForm();
} else {
$this->showUploadForm();
}
}
function showUploadForm()
{
$user = common_current_user();
$profile = $user->getProfile();
if (!$profile) {
common_log_db_error($user, 'SELECT', __FILE__);
$this->serverError(_('User without matching profile'));
return;
}
$original = $this->group->original_logo;
$this->elementStart('form', array('enctype' => 'multipart/form-data',
'method' => 'post',
'id' => 'form_settings_logo',
'class' => 'form_settings',
'action' =>
common_local_url('grouplogo',
array('nickname' => $this->group->nickname))));
$this->elementStart('fieldset');
$this->element('legend', null, _('Group logo'));
$this->hidden('token', common_session_token());
$this->elementStart('ul', 'form_data');
if ($original) {
$this->elementStart('li', array('id' => 'avatar_original',
'class' => 'avatar_view'));
$this->element('h2', null, _("Original"));
$this->elementStart('div', array('id'=>'avatar_original_view'));
$this->element('img', array('src' => $this->group->original_logo,
'alt' => $this->group->nickname));
$this->elementEnd('div');
$this->elementEnd('li');
}
if ($this->group->homepage_logo) {
$this->elementStart('li', array('id' => 'avatar_preview',
'class' => 'avatar_view'));
$this->element('h2', null, _("Preview"));
$this->elementStart('div', array('id'=>'avatar_preview_view'));
$this->element('img', array('src' => $this->group->homepage_logo,
'width' => AVATAR_PROFILE_SIZE,
'height' => AVATAR_PROFILE_SIZE,
'alt' => $this->group->nickname));
$this->elementEnd('div');
$this->elementEnd('li');
}
$this->elementStart('li', array ('id' => 'settings_attach'));
$this->element('input', array('name' => 'avatarfile',
'type' => 'file',
'id' => 'avatarfile'));
$this->element('input', array('name' => 'MAX_FILE_SIZE',
'type' => 'hidden',
'id' => 'MAX_FILE_SIZE',
'value' => MAX_AVATAR_SIZE));
$this->elementEnd('li');
$this->elementEnd('ul');
$this->elementStart('ul', 'form_actions');
$this->elementStart('li');
$this->submit('upload', _('Upload'));
$this->elementEnd('li');
$this->elementEnd('ul');
$this->elementEnd('fieldset');
$this->elementEnd('form');
}
function showCropForm()
{
$this->elementStart('form', array('method' => 'post',
'id' => 'form_settings_avatar',
'class' => 'form_settings',
'action' =>
common_local_url('grouplogo',
array('nickname' => $this->group->nickname))));
$this->elementStart('fieldset');
$this->element('legend', null, _('Avatar settings'));
$this->hidden('token', common_session_token());
$this->elementStart('ul', 'form_data');
$this->elementStart('li',
array('id' => 'avatar_original',
'class' => 'avatar_view'));
$this->element('h2', null, _("Original"));
$this->elementStart('div', array('id'=>'avatar_original_view'));
$this->element('img', array('src' => common_avatar_url($this->filedata['filename']),
'width' => $this->filedata['width'],
'height' => $this->filedata['height'],
'alt' => $this->group->nickname));
$this->elementEnd('div');
$this->elementEnd('li');
$this->elementStart('li',
array('id' => 'avatar_preview',
'class' => 'avatar_view'));
$this->element('h2', null, _("Preview"));
$this->elementStart('div', array('id'=>'avatar_preview_view'));
$this->element('img', array('src' => common_avatar_url($this->filedata['filename']),
'width' => AVATAR_PROFILE_SIZE,
'height' => AVATAR_PROFILE_SIZE,
'alt' => $this->group->nickname));
$this->elementEnd('div');
foreach (array('avatar_crop_x', 'avatar_crop_y',
'avatar_crop_w', 'avatar_crop_h') as $crop_info) {
$this->element('input', array('name' => $crop_info,
'type' => 'hidden',
'id' => $crop_info));
}
$this->submit('crop', _('Crop'));
$this->elementEnd('li');
$this->elementEnd('ul');
$this->elementEnd('fieldset');
$this->elementEnd('form');
}
/**
* Handle a post
*
* We mux on the button name to figure out what the user actually wanted.
*
* @return void
*/
function handlePost()
{
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
$this->show_form(_('There was a problem with your session token. '.
'Try again, please.'));
return;
}
if ($this->arg('upload')) {
$this->uploadAvatar();
} else if ($this->arg('crop')) {
$this->cropAvatar();
} else {
$this->showForm(_('Unexpected form submission.'));
}
}
/**
* Handle an image upload
*
* Does all the magic for handling an image upload, and crops the
* image by default.
*
* @return void
*/
function uploadAvatar()
{
try {
$imagefile = ImageFile::fromUpload('avatarfile');
} catch (Exception $e) {
$this->showForm($e->getMessage());
return;
}
$filename = common_avatar_filename($this->group->id,
image_type_to_extension($imagefile->type),
null,
'group-temp-'.common_timestamp());
$filepath = common_avatar_path($filename);
move_uploaded_file($imagefile->filename, $filepath);
$filedata = array('filename' => $filename,
'filepath' => $filepath,
'width' => $imagefile->width,
'height' => $imagefile->height,
'type' => $imagefile->type);
$_SESSION['FILEDATA'] = $filedata;
$this->filedata = $filedata;
$this->mode = 'crop';
$this->showForm(_('Pick a square area of the image to be your avatar'),
true);
}
/**
* Handle the results of jcrop.
*
* @return void
*/
function cropAvatar()
{
$user = common_current_user();
$profile = $user->getProfile();
$x = $this->arg('avatar_crop_x');
$y = $this->arg('avatar_crop_y');
$w = $this->arg('avatar_crop_w');
$h = $this->arg('avatar_crop_h');
$filedata = $_SESSION['FILEDATA'];
if (!$filedata) {
$this->serverError(_('Lost our file data.'));
return;
}
$filepath = common_avatar_path($filedata['filename']);
if (!file_exists($filepath)) {
$this->serverError(_('Lost our file.'));
return;
}
switch ($filedata['type']) {
case IMAGETYPE_GIF:
$image_src = imagecreatefromgif($filepath);
break;
case IMAGETYPE_JPEG:
$image_src = imagecreatefromjpeg($filepath);
break;
case IMAGETYPE_PNG:
$image_src = imagecreatefrompng($filepath);
break;
default:
$this->serverError(_('Unknown file type'));
return;
}
common_debug("W = $w, H = $h, X = $x, Y = $y");
$image_dest = imagecreatetruecolor($w, $h);
$background = imagecolorallocate($image_dest, 0, 0, 0);
ImageColorTransparent($image_dest, $background);
imagealphablending($image_dest, false);
imagecopyresized($image_dest, $image_src, 0, 0, $x, $y, $w, $h, $w, $h);
$cur = common_current_user();
$filename = common_avatar_filename($this->group->id,
image_type_to_extension($imagefile->type),
null,
'group-'.common_timestamp());
$filepath = common_avatar_path($filename);
switch ($filedata['type']) {
case IMAGETYPE_GIF:
imagegif($image_dest, $filepath);
break;
case IMAGETYPE_JPEG:
imagejpeg($image_dest, $filepath);
break;
case IMAGETYPE_PNG:
imagepng($image_dest, $filepath);
break;
default:
$this->serverError(_('Unknown file type'));
return;
}
if ($this->group->setOriginal($filename, $filedata['type'])) {
@unlink(common_avatar_path($filedata['filename']));
unset($_SESSION['FILEDATA']);
$this->mode = 'upload';
$this->showForm(_('Logo updated.'), true);
} else {
$this->showForm(_('Failed updating logo.'));
}
}
function showPageNotice()
{
if ($this->msg) {
$this->element('div', ($this->success) ? 'success' : 'error',
$this->msg);
} else {
$inst = $this->getInstructions();
$output = common_markup_to_html($inst);
$this->elementStart('div', 'instructions');
$this->raw($output);
$this->elementEnd('div');
}
}
/**
* Add the jCrop stylesheet
*
* @return void
*/
function showStylesheets()
{
parent::showStylesheets();
$jcropStyle =
common_path('theme/base/css/jquery.Jcrop.css?version='.LACONICA_VERSION);
$this->element('link', array('rel' => 'stylesheet',
'type' => 'text/css',
'href' => $jcropStyle,
'media' => 'screen, projection, tv'));
}
/**
* Add the jCrop scripts
*
* @return void
*/
function showScripts()
{
parent::showScripts();
$jcropPack = common_path('js/jcrop/jquery.Jcrop.pack.js');
$jcropGo = common_path('js/jcrop/jquery.Jcrop.go.js');
$this->element('script', array('type' => 'text/javascript',
'src' => $jcropPack));
$this->element('script', array('type' => 'text/javascript',
'src' => $jcropGo));
}
function showLocalNav()
{
$nav = new GroupNav($this, $this->group);
$nav->show();
}
}

View File

@ -24,17 +24,20 @@ require_once(INSTALLDIR.'/lib/twitterapi.php');
class TwitapiaccountAction extends TwitterapiAction
{
function verify_credentials($args, $apidata)
function verify_credentials($args, $apidata)
{
parent::handle($args);
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
$this->clientError(_('API method not found!'), $code = 404);
return;
}
if ($apidata['content-type'] == 'xml') {
header('Content-Type: application/xml; charset=utf-8');
print '<authorized>true</authorized>';
} elseif ($apidata['content-type'] == 'json') {
header('Content-Type: application/json; charset=utf-8');
print '{"authorized":true}';
} else {
common_user_error(_('API method not found!'), $code=404);
}
$this->show_extended_profile($apidata['user'], $apidata);
}
}
function end_session($args, $apidata)
{
@ -99,4 +102,4 @@ class TwitapiaccountAction extends TwitterapiAction
parent::handle($args);
$this->serverError(_('API method under construction.'), $code=501);
}
}
}

View File

@ -33,22 +33,88 @@ class TwitapiusersAction extends TwitterapiAction
return;
}
$user = null;
$email = $this->arg('email');
$this->auth_user = $apidata['user'];
$user = null;
$email = $this->arg('email');
if ($email) {
$user = User::staticGet('email', $email);
} elseif (isset($apidata['api_arg'])) {
$user = $this->get_user($apidata['api_arg']);
}
if ($email) {
$user = User::staticGet('email', $email);
} elseif (isset($apidata['api_arg'])) {
$user = $this->get_user($apidata['api_arg']);
}
if (!$user) {
// XXX: Twitter returns a random(?) user instead of throwing and err! -- Zach
$this->clientError(_('Not found.'), 404, $apidata['content-type']);
return;
}
if (!$user) {
// XXX: Twitter returns a random(?) user instead of throwing and err! -- Zach
$this->client_error(_('Not found.'), 404, $apidata['content-type']);
return;
}
$this->show_extended_profile($user, $apidata);
}
$profile = $user->getProfile();
if (!$profile) {
common_server_error(_('User has no profile.'));
return;
}
$twitter_user = $this->twitter_user_array($profile, true);
// Add in extended user fields offered up by this method
$twitter_user['created_at'] = $this->date_twitter($profile->created);
$subbed = DB_DataObject::factory('subscription');
$subbed->subscriber = $profile->id;
$subbed_count = (int) $subbed->count() - 1;
$notices = DB_DataObject::factory('notice');
$notices->profile_id = $profile->id;
$notice_count = (int) $notices->count();
$twitter_user['friends_count'] = (is_int($subbed_count)) ? $subbed_count : 0;
$twitter_user['statuses_count'] = (is_int($notice_count)) ? $notice_count : 0;
// Other fields Twitter sends...
$twitter_user['profile_background_color'] = '';
$twitter_user['profile_text_color'] = '';
$twitter_user['profile_link_color'] = '';
$twitter_user['profile_sidebar_fill_color'] = '';
$faves = DB_DataObject::factory('fave');
$faves->user_id = $user->id;
$faves_count = (int) $faves->count();
$twitter_user['favourites_count'] = $faves_count;
$timezone = 'UTC';
if ($user->timezone) {
$timezone = $user->timezone;
}
$t = new DateTime;
$t->setTimezone(new DateTimeZone($timezone));
$twitter_user['utc_offset'] = $t->format('Z');
$twitter_user['time_zone'] = $timezone;
if (isset($this->auth_user)) {
if ($this->auth_user->isSubscribed($profile)) {
$twitter_user['following'] = 'true';
} else {
$twitter_user['following'] = 'false';
}
// Not implemented yet
$twitter_user['notifications'] = 'false';
}
if ($apidata['content-type'] == 'xml') {
$this->init_document('xml');
$this->show_twitter_xml_user($twitter_user);
$this->end_document('xml');
} elseif ($apidata['content-type'] == 'json') {
$this->init_document('json');
$this->show_json_objects($twitter_user);
$this->end_document('json');
}
}
}

View File

@ -472,7 +472,7 @@ class TwittersettingsAction extends ConnectSettingsAction
function verifyCredentials($screen_name, $password)
{
$uri = 'http://twitter.com/account/verifyCredentials.json';
$uri = 'http://twitter.com/account/verify_credentials.json';
$data = get_twitter_data($uri, $screen_name, $password);

View File

@ -129,6 +129,8 @@ class Notice extends Memcached_DataObject
$notice->is_local = $is_local;
}
$notice->query('BEGIN');
$notice->reply_to = $reply_to;
$notice->created = common_sql_now();
$notice->content = common_shorten_links($content);
@ -160,6 +162,9 @@ class Notice extends Memcached_DataObject
$notice->saveTags();
$notice->saveGroups();
$notice->addToInboxes();
$notice->query('COMMIT');
# Clear the cache for subscribed users, so they'll update at next request
# XXX: someone clever could prepend instead of clearing the cache
@ -167,7 +172,6 @@ class Notice extends Memcached_DataObject
$notice->blowCaches();
}
$notice->addToInboxes();
return $notice;
}

View File

@ -403,7 +403,7 @@ class User extends Memcached_DataObject
'FROM notice JOIN notice_inbox ON notice.id = notice_inbox.notice_id ' .
'WHERE notice_inbox.user_id = %d ';
# NOTE: we override ORDER
$order = 'ORDER BY notice_inbox.created DESC, notice_inbox.notice_id DESC ';
$order = null;
}
return Notice::getStream(sprintf($qry, $this->id),
'user:notices_with_friends:' . $this->id,

View File

@ -86,4 +86,82 @@ class User_group extends Memcached_DataObject
return $members;
}
function setOriginal($filename, $type)
{
$orig = clone($this);
$this->original_logo = common_avatar_url($filename);
$this->homepage_logo = common_avatar_url($this->scale($filename,
AVATAR_PROFILE_SIZE,
$type));
$this->stream_logo = common_avatar_url($this->scale($filename,
AVATAR_STREAM_SIZE,
$type));
$this->mini_logo = common_avatar_url($this->scale($filename,
AVATAR_MINI_SIZE,
$type));
common_debug(common_log_objstring($this));
return $this->update($orig);
}
function scale($filename, $size, $type)
{
$filepath = common_avatar_path($filename);
if (!file_exists($filepath)) {
$this->serverError(_('Lost our file.'));
return;
}
$info = @getimagesize($filepath);
switch ($type) {
case IMAGETYPE_GIF:
$image_src = imagecreatefromgif($filepath);
break;
case IMAGETYPE_JPEG:
$image_src = imagecreatefromjpeg($filepath);
break;
case IMAGETYPE_PNG:
$image_src = imagecreatefrompng($filepath);
break;
default:
$this->serverError(_('Unknown file type'));
return;
}
$image_dest = imagecreatetruecolor($size, $size);
$background = imagecolorallocate($image_dest, 0, 0, 0);
ImageColorTransparent($image_dest, $background);
imagealphablending($image_dest, false);
imagecopyresized($image_dest, $image_src, 0, 0, $x, $y, $size, $size, $info[0], $info[1]);
$cur = common_current_user();
$outname = common_avatar_filename($cur->id,
image_type_to_extension($type),
null,
common_timestamp());
$outpath = common_avatar_path($outname);
switch ($type) {
case IMAGETYPE_GIF:
imagegif($image_dest, $outpath);
break;
case IMAGETYPE_JPEG:
imagejpeg($image_dest, $outpath);
break;
case IMAGETYPE_PNG:
imagepng($image_dest, $outpath);
break;
default:
$this->serverError(_('Unknown file type'));
return;
}
return $outname;
}
}

View File

@ -49,7 +49,8 @@ create table "user" (
emailnotifysub integer default 1 /* comment 'Notify by email of subscriptions' */,
emailnotifyfav integer default 1 /* comment 'Notify by email of favorites' */,
emailnotifynudge integer default 1 /* comment 'Notify by email of nudges' */,
emailmicroid integer default 1 /* comment 'whether to publish email microid' */,
emailnotifymsg integer default 1 / * comment 'Notify by email of direct messages' */,
emailmicroid integer default 1 /* comment 'whether to publish email microid' */,
language varchar(50) /* comment 'preferred language' */,
timezone varchar(50) /* comment 'timezone' */,
emailpost integer default 1 /* comment 'Post by email' */,
@ -66,6 +67,7 @@ create table "user" (
uri varchar(255) unique /* comment 'universally unique identifier, usually a tag URI' */,
autosubscribe integer default 0 /* comment 'automatically subscribe to users who subscribe to us' */,
urlshorteningservice varchar(50) default 'ur1.ca' /* comment 'service to use for auto-shortening URLs' */,
inboxed integer default 0 /* comment 'has an inbox been created for this user?' */,
created timestamp not null /* comment 'date this record was created' */,
modified timestamp /* comment 'date this record was modified' */
@ -86,6 +88,8 @@ create table remote_profile (
create table subscription (
subscriber integer not null /* comment 'profile listening' */,
subscribed integer not null /* comment 'profile being listened to' */,
jabber integer default 1 /* comment 'deliver jabber messages',
sms integer default 1 comment 'deliver sms messages',
token varchar(255) /* comment 'authorization token' */,
secret varchar(255) /* comment 'token secret' */,
created timestamp not null /* comment 'date this record was created' */,
@ -271,8 +275,6 @@ create table foreign_user (
service int not null /* comment 'foreign key to service' */ references foreign_service(id) ,
uri varchar(255) not null unique /* comment 'identifying URI' */,
nickname varchar(255) /* comment 'nickname on foreign service' */,
user_id int /* comment 'link to user on this system, if exists' */ references "user" (id),
credentials varchar(255) /* comment 'authc credentials, typically a password' */,
created timestamp not null /* comment 'date this record was created' */,
modified timestamp /* comment 'date this record was modified' */,
@ -280,11 +282,25 @@ create table foreign_user (
);
create index foreign_user_user_id_idx on foreign_user using btree(user_id);
create table foreign_link (
user_id int /* comment 'link to user on this system, if exists' */ references "user" (id),
foreign_id int /* comment 'link' */ references foreign_user (id),
service int not null /* comment 'foreign key to service' */ references foreign_service (id),
credentials varchar(255) /* comment 'authc credentials, typically a password',
noticesync int not null default 1 /* comment 'notice synchronisation, bit 1 = sync outgoing, bit 2 = sync incoming, bit 3 = filter local replies' */,
friendsync int not null default 2 /* comment 'friend synchronisation, bit 1 = sync outgoing, bit 2 = sync incoming
created timestamp not null /* comment 'date this record was created' */,
modified timestamp not null /* comment 'date this record was modified' */,
primary key (user_id,foreign_id,service)
);
create index foreign_user_user_id_idx on foreign_link using btree(user_id);
create table foreign_subscription (
service int not null /* comment 'service where relationship happens' */ references foreign_service(id) ,
subscriber int not null /* comment 'subscriber on foreign service' */ ,
subscribed int not null /* comment 'subscribed user' */ ,
created timestamp not null /* comment 'date this record was created' */,
created timestamp not null /* comment 'date this record was created' /,
primary key (service, subscriber, subscribed)
);
@ -320,6 +336,38 @@ create index message_from_idx on message using btree(from_profile);
create index message_to_idx on message using btree(to_profile);
create index message_created_idx on message using btree(created);
create table notice_inbox (
user_id integer not null /* comment 'user receiving the message' */ references user (id),
notice_id integer not null /* comment 'notice received' */ references notice (id),
created datetime not null /* comment 'date the notice was created' */,
source integer default 1 /* comment 'reason it is in the inbox; 1=subscription' */,
primary key (user_id, notice_id)
);
create index notice_inbox_notice_id_idx (notice_id) on notice_inbox using btree(notice_id);
create table profile_tag (
tagger integer not null /* comment 'user making the tag' */ references "user" (id),
tagged integer not null /* comment 'profile tagged' */ references profile (id),
tag varchar(64) not null /* comment 'hash tag associated with this notice' */,
modified timestamp /* comment 'date the tag was added' */,
primary key (tagger, tagged, tag)
);
create index profile_tag_modified_idx on profile_tag using btree(modified);
create index profile_tag_tagger_tag_idx on profile_tag using btree(tagger,tag);
create table profile_block (
blocker integer not null i/* comment 'user making the block' */ references user (id),
blocked integer not null /* comment 'profile that is blocked' */ references profile (id),
modified timestamp /* comment 'date of blocking' */,
primary key (blocker, blocked)
);
/* Textsearch stuff */
create index textsearch_idx on profile using gist(textsearch);

View File

@ -89,13 +89,14 @@ RewriteRule ^peopletag/([a-zA-Z0-9]+)$ index.php?action=peopletag&tag=$1 [L,QSA]
RewriteRule ^featured/?$ index.php?action=featured [L,QSA]
RewriteRule ^favorited/?$ index.php?action=favorited [L,QSA]
RewriteRule ^group/new index.php?action=newgroup [L,QSA]
RewriteRule ^group/([a-zA-Z0-9]+)/edit index.php?action=editgroup&nickname=$1 [L,QSA]
RewriteRule ^group/([a-zA-Z0-9]+)/join index.php?action=joingroup&nickname=$1 [L,QSA]
RewriteRule ^group/([a-zA-Z0-9]+)/leave index.php?action=leavegroup&nickname=$1 [L,QSA]
RewriteRule ^group/([a-zA-Z0-9]+)/members index.php?action=groupmembers&nickname=$1 [L,QSA]
RewriteRule ^group/([0-9]+)/id index.php?action=groupbyid&id=$1 [L,QSA]
RewriteRule ^group/([a-zA-Z0-9]+)/rss index.php?action=grouprss&nickname=$1 [L,QSA]
RewriteRule ^group/new$ index.php?action=newgroup [L,QSA]
RewriteRule ^group/([a-zA-Z0-9]+)/edit$ index.php?action=editgroup&nickname=$1 [L,QSA]
RewriteRule ^group/([a-zA-Z0-9]+)/join$ index.php?action=joingroup&nickname=$1 [L,QSA]
RewriteRule ^group/([a-zA-Z0-9]+)/leave$ index.php?action=leavegroup&nickname=$1 [L,QSA]
RewriteRule ^group/([a-zA-Z0-9]+)/members$ index.php?action=groupmembers&nickname=$1 [L,QSA]
RewriteRule ^group/([a-zA-Z0-9]+)/logo$ index.php?action=grouplogo&nickname=$1 [L,QSA]
RewriteRule ^group/([0-9]+)/id$ index.php?action=groupbyid&id=$1 [L,QSA]
RewriteRule ^group/([a-zA-Z0-9]+)/rss$ index.php?action=grouprss&nickname=$1 [L,QSA]
RewriteRule ^group/([a-zA-Z0-9]+)$ index.php?action=showgroup&nickname=$1 [L,QSA]
RewriteRule ^group$ index.php?action=groups [L,QSA]

View File

@ -19,7 +19,7 @@
if (!defined('LACONICA')) { exit(1); }
define('LACONICA_VERSION', '0.6.4.1');
define('LACONICA_VERSION', '0.7.0');
define('AVATAR_PROFILE_SIZE', 96);
define('AVATAR_STREAM_SIZE', 48);

View File

@ -101,6 +101,12 @@ class GroupNav extends Widget
sprintf(_('Edit %s group properties'), $nickname),
$action_name == 'editgroup',
'nav_group_admin');
$this->out->menuItem(common_local_url('grouplogo', array('nickname' =>
$nickname)),
_('Logo'),
sprintf(_('Add or edit %s logo'), $nickname),
$action_name == 'grouplogo',
'nav_group_logo');
}
$this->out->elementEnd('ul');
}

View File

@ -99,54 +99,35 @@ function get_nice_language_list()
*
* @return array mapping of language codes to language info
*/
function get_all_languages()
{
return
array('en-us' => array('q' => 1, 'lang' => 'en_US',
'name' => 'English (US)', 'direction' => 'ltr'),
'en-nz' => array('q' => 1, 'lang' => 'en_NZ',
'name' => 'English (NZ)', 'direction' => 'ltr'),
'en-gb' => array('q' => 1, 'lang' => 'en_GB',
'name' => 'English (British)', 'direction' => 'ltr'),
'en' => array('q' => 1, 'lang' => 'en',
'name' => 'English', 'direction' => 'ltr'),
'da' => array('q' => 0.1, 'lang' => 'da_DK',
'name' => 'Danish', 'direction' => 'ltr'),
'nl' => array('q' => 1, 'lang' => 'nl_NL',
'name' => 'Dutch', 'direction' => 'ltr'),
'eo' => array('q' => 0.1, 'lang' => 'eo',
'name' => 'Esperanto', 'direction' => 'ltr'),
'fr-fr' => array('q' => 0.9, 'lang' => 'fr_FR',
'name' => 'French', 'direction' => 'ltr'),
'de' => array('q' => 1, 'lang' => 'de_DE',
'name' => 'German', 'direction' => 'ltr'),
'it' => array('q' => 1, 'lang' => 'it_IT',
'name' => 'Italian', 'direction' => 'ltr'),
'ko' => array('q' => 0.1, 'lang' => 'ko',
'name' => 'Korean', 'direction' => 'ltr'),
'nb' => array('q' => 1, 'lang' => 'nb_NO',
'name' => 'Norwegian (bokmal)', 'direction' => 'ltr'),
'pt' => array('q' => 0.2, 'lang' => 'pt',
'name' => 'Portuguese', 'direction' => 'ltr'),
'pt-br' => array('q' => 1, 'lang' => 'pt_BR',
'name' => 'Portuguese Brazil', 'direction' => 'ltr'),
'es' => array('q' => 1, 'lang' => 'es',
'name' => 'Spanish', 'direction' => 'ltr'),
'tr' => array('q' => 1, 'lang' => 'tr_TR',
'name' => 'Turkish', 'direction' => 'ltr'),
'uk' => array('q' => 1, 'lang' => 'uk_UA',
'name' => 'Ukrainian', 'direction' => 'ltr'),
'pl' => array('q' => 1, 'lang' => 'pl_PL',
'name' => 'Polish', 'direction' => 'ltr'),
'mk' => array('q' => 1, 'lang' => 'mk_MK',
'name' => 'Macedonian', 'direction' => 'ltr'),
'jp' => array('q' => 0.1, 'lang' => 'ja_JP',
'name' => 'Japanese', 'direction' => 'ltr'),
'cs' => array('q' => 1, 'lang' => 'cs_CZ',
'name' => 'Czech', 'direction' => 'ltr'),
'ca' => array('q' => 1, 'lang' => 'ca_ES',
'name' => 'Catalan', 'direction' => 'ltr'),
);
function get_all_languages() {
return array(
'bg' => array('q' => 0.8, 'lang' => 'bg_BG', 'name' => 'Bulgarian', 'direction' => 'ltr'),
'ca' => array('q' => 0.5, 'lang' => 'ca_ES', 'name' => 'Catalan', 'direction' => 'ltr'),
'cs' => array('q' => 0.5, 'lang' => 'cs_CZ', 'name' => 'Czech', 'direction' => 'ltr'),
'de' => array('q' => 0.5, 'lang' => 'de_DE', 'name' => 'German', 'direction' => 'ltr'),
'el' => array('q' => 0.1, 'lang' => 'el', 'name' => 'Greek', 'direction' => 'ltr'),
'en-us' => array('q' => 1, 'lang' => 'en_US', 'name' => 'English (US)', 'direction' => 'ltr'),
'en-gb' => array('q' => 0.3, 'lang' => 'en_GB', 'name' => 'English (British)', 'direction' => 'ltr'),
'en' => array('q' => 1, 'lang' => 'en', 'name' => 'English', 'direction' => 'ltr'),
'es' => array('q' => 0.5, 'lang' => 'es', 'name' => 'Spanish', 'direction' => 'ltr'),
'fr-fr' => array('q' => 0.2, 'lang' => 'fr_FR', 'name' => 'French', 'direction' => 'ltr'),
'he' => array('q' => 0.5, 'lang' => 'he_IL', 'name' => 'Hebrew', 'direction' => 'ltr'),
'it' => array('q' => 0.9, 'lang' => 'it_IT', 'name' => 'Italian', 'direction' => 'rtl'),
'jp' => array('q' => 0.5, 'lang' => 'ja_JP', 'name' => 'Japanese', 'direction' => 'ltr'),
# 'ko' => array('q' => 0, 'lang' => 'ko', 'name' => 'Korean', 'direction' => 'ltr'),
'mk' => array('q' => 0.5, 'lang' => 'mk_MK', 'name' => 'Macedonian', 'direction' => 'ltr'),
'nb' => array('q' => 0.1, 'lang' => 'nb_NO', 'name' => 'Norwegian (bokmal)', 'direction' => 'ltr'),
'nl' => array('q' => 0.5, 'lang' => 'nl_NL', 'name' => 'Dutch', 'direction' => 'ltr'),
'pl' => array('q' => 0.5, 'lang' => 'pl_PL', 'name' => 'Polish', 'direction' => 'ltr'),
# 'pt' => array('q' => 0, 'lang' => 'pt', 'name' => 'Portuguese', 'direction' => 'ltr'),
'pt-br' => array('q' => 0.7, 'lang' => 'pt_BR', 'name' => 'Portuguese Brazil', 'direction' => 'ltr'),
'ru' => array('q' => 0.1, 'lang' => 'ru_RU', 'name' => 'Russian', 'direction' => 'ltr'),
'sv' => array('q' => 0.9, 'lang' => 'sv_SE', 'name' => 'Swedish', 'direction' => 'ltr'),
'te' => array('q' => 0.3, 'lang' => 'te_IN', 'name' => 'Telugu', 'direction' => 'ltr'),
'tr' => array('q' => 0.5, 'lang' => 'tr_TR', 'name' => 'Turkish', 'direction' => 'ltr'),
'uk' => array('q' => 0.7, 'lang' => 'uk_UA', 'name' => 'Ukrainian', 'direction' => 'ltr'),
'vi' => array('q' => 0.7, 'lang' => 'vi_VN', 'name' => 'Vietnamese', 'direction' => 'ltr'),
'zh-cn' => array('q' => 0.9, 'lang' => 'zh_CN', 'name' => 'Chinese (Simplified)', 'direction' => 'ltr'),
'zh-hant' => array('q' => 0.2, 'lang' => 'zh_hant', 'name' => 'Chinese (Taiwanese)', 'direction' => 'ltr'),
);
}

View File

@ -60,23 +60,22 @@ function subs_subscribe_to($user, $other)
subs_notify($other, $user);
if (common_config('memcached', 'enabled')) {
$cache = new Memcache();
if ($cache->connect(common_config('memcached', 'server'), common_config('memcached', 'port'))) {
$cache->delete(common_cache_key('user:notices_with_friends:' . $user->id));
}
}
$cache = common_memcache();
if ($cache) {
$cache->delete(common_cache_key('user:notices_with_friends:' . $user->id));
}
if ($other->autosubscribe && !$other->isSubscribed($user) && !$user->hasBlocked($other)) {
if (!$other->subscribeTo($user)) {
return _('Could not subscribe other to you.');
}
if (common_config('memcached', 'enabled')) {
$cache = new Memcache();
if ($cache->connect(common_config('memcached', 'server'), common_config('memcached', 'port'))) {
$cache->delete(common_cache_key('user:notices_with_friends:' . $other->id));
}
}
$cache = common_memcache();
if ($cache) {
$cache->delete(common_cache_key('user:notices_with_friends:' . $other->id));
}
subs_notify($user, $other);
}
@ -134,12 +133,11 @@ function subs_unsubscribe_to($user, $other)
if (!$sub->delete())
return _('Couldn\'t delete subscription.');
if (common_config('memcached', 'enabled')) {
$cache = new Memcache();
if ($cache->connect(common_config('memcached', 'server'), common_config('memcached', 'port'))) {
$cache->delete(common_cache_key('user:notices_with_friends:' . $user->id));
}
}
$cache = common_memcache();
if ($cache) {
$cache->delete(common_cache_key('user:notices_with_friends:' . $user->id));
}
return true;
}

View File

@ -42,7 +42,7 @@ function get_twitter_data($uri, $screen_name, $password)
$errmsg = curl_error($ch);
if ($errmsg) {
common_debug("Twitter bridge - cURL error: $errmsg - trying to load: $uri with user $twit_user.",
common_debug("Twitter bridge - cURL error: $errmsg - trying to load: $uri with user $screen_name.",
__FILE__);
}

View File

@ -690,4 +690,4 @@ class TwitterapiAction extends Action
}
}
}

View File

@ -900,6 +900,8 @@ function common_fancy_url($action, $args=null)
return common_path('group/'.$args['nickname'].'/rss');
case 'groupmembers':
return common_path('group/'.$args['nickname'].'/members');
case 'grouplogo':
return common_path('group/'.$args['nickname'].'/logo');
case 'usergroups':
return common_path($args['nickname'].'/groups');
case 'groups':

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -42,68 +42,70 @@ common_log(LOG_INFO, 'Updating user inboxes.');
$ids = file($id_file);
foreach ($ids as $id) {
$user = User::staticGet('id', $id);
$user = User::staticGet('id', $id);
if (!$user) {
common_log(LOG_WARNING, 'No such user: ' . $id);
continue;
}
if ($user->inboxed) {
common_log(LOG_WARNING, 'Already inboxed: ' . $id);
continue;
}
if (!$user) {
common_log(LOG_WARNING, 'No such user: ' . $id);
continue;
}
if ($user->inboxed) {
common_log(LOG_WARNING, 'Already inboxed: ' . $id);
continue;
}
common_log(LOG_INFO, 'Updating inbox for user ' . $user->id);
$user->query('BEGIN');
$old_inbox = new Notice_inbox();
$old_inbox->user_id = $user->id;
$result = $old_inbox->delete();
if (is_null($result) || $result === false) {
common_log_db_error($old_inbox, 'DELETE', __FILE__);
continue;
}
$user->query('BEGIN');
$old_inbox = new Notice_inbox();
$old_inbox->user_id = $user->id;
$result = $old_inbox->delete();
if (is_null($result) || $result === false) {
common_log_db_error($old_inbox, 'DELETE', __FILE__);
continue;
}
$old_inbox->free();
$inbox = new Notice_inbox();
$result = $inbox->query('INSERT INTO notice_inbox (user_id, notice_id, created) ' .
'SELECT ' . $user->id . ', notice.id, notice.created ' .
'FROM subscription JOIN notice ON subscription.subscribed = notice.profile_id ' .
'WHERE subscription.subscriber = ' . $user->id . ' ' .
'AND notice.created >= subscription.created ' .
'AND now() - notice.created < ' . (7 * 24 * 3600) . ' ' .
'AND NOT EXISTS (SELECT user_id, notice_id ' .
'FROM notice_inbox ' .
'WHERE user_id = ' . $user->id . ' ' .
'AND notice_id = notice.id)');
if (is_null($result) || $result === false) {
common_log_db_error($inbox, 'INSERT', __FILE__);
continue;
}
$orig = clone($user);
$user->inboxed = 1;
$result = $user->update($orig);
if (!$result) {
common_log_db_error($user, 'UPDATE', __FILE__);
continue;
}
$user->query('COMMIT');
$inbox->free();
unset($inbox);
if ($cache) {
$cache->delete(common_cache_key('user:notices_with_friends:' . $user->id));
}
$old_inbox->free();
$inbox = new Notice_inbox();
$result = $inbox->query('INSERT INTO notice_inbox (user_id, notice_id, created) ' .
'SELECT ' . $user->id . ', notice.id, notice.created ' .
'FROM subscription JOIN notice ON subscription.subscribed = notice.profile_id ' .
'WHERE subscription.subscriber = ' . $user->id . ' ' .
'AND notice.created >= subscription.created ' .
'AND NOT EXISTS (SELECT user_id, notice_id ' .
'FROM notice_inbox ' .
'WHERE user_id = ' . $user->id . ' ' .
'AND notice_id = notice.id) ' .
'ORDER BY notice.created DESC ' .
'LIMIT 0, 1000');
if (is_null($result) || $result === false) {
common_log_db_error($inbox, 'INSERT', __FILE__);
continue;
}
$orig = clone($user);
$user->inboxed = 1;
$result = $user->update($orig);
if (!$result) {
common_log_db_error($user, 'UPDATE', __FILE__);
continue;
}
$user->query('COMMIT');
$inbox->free();
unset($inbox);
if ($cache) {
$cache->delete(common_cache_key('user:notices_with_friends:' . $user->id));
$cache->delete(common_cache_key('user:notices_with_friends:' . $user->id . ';last'));
}
}

0
scripts/sitemap.php Normal file → Executable file
View File

59
scripts/uncache_users.php Normal file
View File

@ -0,0 +1,59 @@
#!/usr/bin/env php
<?php
/*
* Laconica - a distributed open-source microblogging tool
* Copyright (C) 2008, Controlez-Vous, 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/>.
*/
# Abort if called from a web server
if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
print "This script must be run from the command line\n";
exit();
}
ini_set("max_execution_time", "0");
ini_set("max_input_time", "0");
set_time_limit(0);
mb_internal_encoding('UTF-8');
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
define('LACONICA', true);
require_once(INSTALLDIR . '/lib/common.php');
$id_file = ($argc > 1) ? $argv[1] : 'ids.txt';
common_log(LOG_INFO, 'Updating user inboxes.');
$ids = file($id_file);
foreach ($ids as $id) {
$user = User::staticGet('id', $id);
if (!$user) {
common_log(LOG_WARNING, 'No such user: ' . $id);
continue;
}
$user->decache();
$memc = common_memcache();
$memc->delete(common_cache_key('user:notices_with_friends:'. $user->id));
$memc->delete(common_cache_key('user:notices_with_friends:'. $user->id . ';last'));
}

0
scripts/update_pot.sh Normal file → Executable file
View File

98
scripts/update_translations.php Normal file → Executable file
View File

@ -5,62 +5,62 @@ chdir(dirname(__FILE__) . '/..');
/* Languages to pull */
$languages = array(
'da_DK' => 'http://laconi.ca/translate/download.php?file_id=23',
'nl_NL' => 'http://laconi.ca/translate/download.php?file_id=39',
'en_NZ' => 'http://laconi.ca/translate/download.php?file_id=15',
'eo' => 'http://laconi.ca/translate/download.php?file_id=10',
'fr_FR' => 'http://laconi.ca/translate/download.php?file_id=19',
'de_DE' => 'http://laconi.ca/translate/download.php?file_id=18',
'it_IT' => 'http://laconi.ca/translate/download.php?file_id=21',
'ko' => 'http://laconi.ca/translate/download.php?file_id=33',
'no_NB' => 'http://laconi.ca/translate/download.php?file_id=31',
'pt' => 'http://laconi.ca/translate/download.php?file_id=8',
'pt_BR' => 'http://laconi.ca/translate/download.php?file_id=72',
'ru_RU' => 'http://laconi.ca/translate/download.php?file_id=26',
'es' => 'http://laconi.ca/translate/download.php?file_id=9',
'tr_TR' => 'http://laconi.ca/translate/download.php?file_id=37',
'uk_UA' => 'http://laconi.ca/translate/download.php?file_id=44',
'he_IL' => 'http://laconi.ca/translate/download.php?file_id=71',
'mk_MK' => 'http://laconi.ca/translate/download.php?file_id=67',
'ja_JP' => 'http://laconi.ca/translate/download.php?file_id=43',
'cs_CZ' => 'http://laconi.ca/translate/download.php?file_id=63',
'ca_ES' => 'http://laconi.ca/translate/download.php?file_id=49',
'pl_PL' => 'http://laconi.ca/translate/download.php?file_id=51',
'sv_SE' => 'http://laconi.ca/translate/download.php?file_id=55'
'da_DK' => 'http://laconi.ca/translate/download.php?file_id=93',
'nl_NL' => 'http://laconi.ca/translate/download.php?file_id=97',
'en_NZ' => 'http://laconi.ca/translate/download.php?file_id=87',
'eo' => 'http://laconi.ca/translate/download.php?file_id=88',
'fr_FR' => 'http://laconi.ca/translate/download.php?file_id=99',
'de_DE' => 'http://laconi.ca/translate/download.php?file_id=100',
'it_IT' => 'http://laconi.ca/translate/download.php?file_id=101',
'ko' => 'http://laconi.ca/translate/download.php?file_id=102',
'no_NB' => 'http://laconi.ca/translate/download.php?file_id=104',
'pt' => 'http://laconi.ca/translate/download.php?file_id=106',
'pt_BR' => 'http://laconi.ca/translate/download.php?file_id=107',
'ru_RU' => 'http://laconi.ca/translate/download.php?file_id=109',
'es' => 'http://laconi.ca/translate/download.php?file_id=110',
'tr_TR' => 'http://laconi.ca/translate/download.php?file_id=114',
'uk_UA' => 'http://laconi.ca/translate/download.php?file_id=115',
'he_IL' => 'http://laconi.ca/translate/download.php?file_id=116',
'mk_MK' => 'http://laconi.ca/translate/download.php?file_id=103',
'ja_JP' => 'http://laconi.ca/translate/download.php?file_id=117',
'cs_CZ' => 'http://laconi.ca/translate/download.php?file_id=96',
'ca_ES' => 'http://laconi.ca/translate/download.php?file_id=95',
'pl_PL' => 'http://laconi.ca/translate/download.php?file_id=105',
'sv_SE' => 'http://laconi.ca/translate/download.php?file_id=128'
);
/* Update the languages */
foreach ($languages as $code => $file) {
$lcdir='locale/'.$code;
$msgdir=$lcdir.'/LC_MESSAGES';
$pofile=$msgdir.'/laconica.po';
$mofile=$msgdir.'/laconica.mo';
$lcdir='locale/'.$code;
$msgdir=$lcdir.'/LC_MESSAGES';
$pofile=$msgdir.'/laconica.po';
$mofile=$msgdir.'/laconica.mo';
/* Check for an existing */
if (!is_dir($msgdir)) {
mkdir($lcdir);
mkdir($msgdir);
$existingSHA1 = '';
} else {
$existingSHA1 = file_exists($pofile) ? sha1_file($pofile) : '';
}
/* Check for an existing */
if (!is_dir($msgdir)) {
mkdir($lcdir);
mkdir($msgdir);
$existingSHA1 = '';
} else {
$existingSHA1 = file_exists($pofile) ? sha1_file($pofile) : '';
}
/* Get the remote one */
$newFile = file_get_contents($file);
/* Get the remote one */
$newFile = file_get_contents($file);
// Update if the local .po file is different to the one downloaded, or
// if the .mo file is not present.
if(sha1($newFile)!=$existingSHA1 || !file_exists($mofile)) {
echo "Updating ".$code."\n";
file_put_contents($pofile, $newFile);
$prevdir = getcwd();
chdir($msgdir);
system('msgmerge -U laconica.po ../../laconica.pot');
system('msgfmt -f -o laconica.mo laconica.po');
chdir($prevdir);
} else {
echo "Unchanged - ".$code."\n";
}
// Update if the local .po file is different to the one downloaded, or
// if the .mo file is not present.
if(sha1($newFile)!=$existingSHA1 || !file_exists($mofile)) {
echo "Updating ".$code."\n";
file_put_contents($pofile, $newFile);
$prevdir = getcwd();
chdir($msgdir);
system('msgmerge -U laconica.po ../../laconica.pot');
system('msgfmt -f -o laconica.mo laconica.po');
chdir($prevdir);
} else {
echo "Unchanged - ".$code."\n";
}
}
echo "Finished\n";

View File

@ -209,6 +209,7 @@ margin-bottom:29px;
float:right;
margin-right:18px;
margin-bottom:11px;
margin-left:18px;
}
#site_nav_global_primary ul li {
display:inline;