forked from GNUsocial/gnu-social
Merge branch '0.8.x' of git://gitorious.org/laconica/dev into 0.8.x
Conflicts: lib/util.php
This commit is contained in:
commit
bab3e1b858
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,11 +1,15 @@
|
||||
avatar/*
|
||||
files/*
|
||||
_darcs/*
|
||||
logs/*
|
||||
config.php
|
||||
.htaccess
|
||||
httpd.conf
|
||||
*.tmproj
|
||||
dataobject.ini
|
||||
*~
|
||||
*.bak
|
||||
*.orig
|
||||
*.rej
|
||||
.#*
|
||||
*.swp
|
||||
|
69
EVENTS.txt
69
EVENTS.txt
@ -15,6 +15,24 @@ StartSecondaryNav: Showing the secondary nav menu
|
||||
EndSecondaryNav: At the end of the secondary nav menu
|
||||
- $action: the current action
|
||||
|
||||
StartShowStyles: Showing Style links; good place to add UA style resets
|
||||
- $action: the current action
|
||||
|
||||
EndShowStyles: End showing Style links; good place to add custom styles
|
||||
- $action: the current action
|
||||
|
||||
StartShowLaconicaStyles: Showing Laconica Style links
|
||||
- $action: the current action
|
||||
|
||||
EndShowLaconicaStyles: End showing Laconica Style links; good place to add handheld or JavaScript dependant styles
|
||||
- $action: the current action
|
||||
|
||||
StartShowUAStyles: Showing custom UA Style links
|
||||
- $action: the current action
|
||||
|
||||
EndShowUAStyles: End showing custom UA Style links; good place to add user-agent (e.g., filter, -webkit, -moz) specific styles
|
||||
- $action: the current action
|
||||
|
||||
StartShowScripts: Showing JavaScript links
|
||||
- $action: the current action
|
||||
|
||||
@ -34,3 +52,54 @@ StartShowLaconicaScripts: Showing Laconica script links (use this to link to a C
|
||||
EndShowLaconicaScripts: End showing Laconica script links
|
||||
- $action: the current action
|
||||
|
||||
StartShowSections: Start the list of sections in the sidebar
|
||||
- $action: the current action
|
||||
|
||||
EndShowSections: End the list of sections in the sidebar
|
||||
- $action: the current action
|
||||
|
||||
StartShowHeader: Showing before the header container
|
||||
- $action: the current action
|
||||
|
||||
EndShowHeader: Showing after the header container
|
||||
- $action: the current action
|
||||
|
||||
StartShowFooter: Showing before the footer container
|
||||
- $action: the current action
|
||||
|
||||
EndShowFooter: Showing after the footer container
|
||||
- $action: the current action
|
||||
|
||||
StartShowContentBlock: Showing before the content container
|
||||
- $action: the current action
|
||||
|
||||
EndShowContentBlock: Showing after the content container
|
||||
- $action: the current action
|
||||
|
||||
StartNoticeSave: before inserting a notice (good place for content filters)
|
||||
- $notice: notice being saved (no ID or URI)
|
||||
|
||||
EndNoticeSave: after inserting a notice and related code
|
||||
- $notice: notice that was saved (with ID and URI)
|
||||
|
||||
StartShowLocalNavBlock: Showing the local nav menu
|
||||
- $action: the current action
|
||||
|
||||
EndShowLocalNavBlock: At the end of the local nav menu
|
||||
- $action: the current action
|
||||
|
||||
StartShowHTML: Chance to set document headers (e.g., content type, charset, language), DOCTYPE and html element properties
|
||||
- $action: the current action
|
||||
|
||||
EndShowHTML: Showing after the html element
|
||||
- $action: the current action
|
||||
|
||||
StartPublicGroupNav: Showing the public group nav menu
|
||||
- $action: the current action
|
||||
|
||||
EndPublicGroupNav: At the end of the public group nav menu
|
||||
- $action: the current action
|
||||
|
||||
RouterInitialized: After the router instance has been initialized
|
||||
- $m: the Net_URL_Mapper that has just been set up
|
||||
|
||||
|
146
README
146
README
@ -240,21 +240,28 @@ especially if you've previously installed PHP/MySQL packages.
|
||||
configure virtual hosts on your web server, you can try setting up
|
||||
"http://micro.example.net/" or the like.
|
||||
|
||||
3. You should also take this moment to make your avatar subdirectory
|
||||
3. Make your target directory writeable by the Web server.
|
||||
|
||||
chmod a+w /var/www/mublog/
|
||||
|
||||
On some systems, this will probably work:
|
||||
|
||||
chgrp www-data /var/www/mublog/
|
||||
chmod g+w /var/www/mublog/
|
||||
|
||||
If your Web server runs as another user besides "www-data", try
|
||||
that user's default group instead. As a last resort, you can create
|
||||
a new group like "mublog" and add the Web server's user to the group.
|
||||
|
||||
4. You should also take this moment to make your avatar subdirectory
|
||||
writeable by the Web server. An insecure way to do this is:
|
||||
|
||||
chmod a+w /var/www/mublog/avatar
|
||||
|
||||
On some systems, this will probably work:
|
||||
You can also make the avatar directory writeable by the Web server
|
||||
group, as noted above.
|
||||
|
||||
chgrp www-data /var/www/mublog/avatar
|
||||
chmod g+w /var/www/mublog/avatar
|
||||
|
||||
If your Web server runs as another user besides "www-data", try
|
||||
that user's default group instead. As a last resort, you can create
|
||||
a new group like "avatar" and add the Web server's user to the group.
|
||||
|
||||
4. Create a database to hold your microblog data. Something like this
|
||||
5. Create a database to hold your microblog data. Something like this
|
||||
should work:
|
||||
|
||||
mysqladmin -u "username" --password="password" create laconica
|
||||
@ -267,63 +274,55 @@ especially if you've previously installed PHP/MySQL packages.
|
||||
a tool like PHPAdmin to create a database. Check your hosting
|
||||
service's documentation for how to create a new MySQL database.)
|
||||
|
||||
5. Run the laconica.sql SQL script in the db subdirectory to create
|
||||
the database tables in the database. A typical system would work
|
||||
like this:
|
||||
|
||||
mysql -u "username" --password="password" laconica < /var/www/mublog/db/laconica.sql
|
||||
|
||||
You may want to test by logging into the database and checking that
|
||||
the tables were created. Here's an example:
|
||||
|
||||
SHOW TABLES;
|
||||
|
||||
6. Create a new database account that Laconica will use to access the
|
||||
database. If you have shell access, this will probably work from the
|
||||
MySQL shell:
|
||||
|
||||
GRANT SELECT,INSERT,DELETE,UPDATE on laconica.*
|
||||
GRANT ALL on laconica.*
|
||||
TO 'lacuser'@'localhost'
|
||||
IDENTIFIED BY 'lacpassword';
|
||||
|
||||
You should change 'lacuser' and 'lacpassword' to your preferred new
|
||||
username and password. You may want to test logging in as this new
|
||||
user and testing that you can SELECT from some of the tables in the
|
||||
DB (use SHOW TABLES to see which ones are there).
|
||||
username and password. You may want to test logging in to MySQL as
|
||||
this new user.
|
||||
|
||||
7. Copy the config.php.sample in the Laconica directory to config.php.
|
||||
7. In a browser, navigate to the Laconica install script; something like:
|
||||
|
||||
8. Edit config.php to set the basic configuration for your system.
|
||||
(See descriptions below for basic config options.) Note that there
|
||||
are lots of options and if you try to do them all at once, you will
|
||||
have a hard time making sure what's working and what's not. So,
|
||||
stick with the basics at first. In particular, customizing the
|
||||
'site' and 'db' settings will almost definitely be needed.
|
||||
http://yourserver.example.com/mublog/install.php
|
||||
|
||||
9. At this point, you should be able to navigate in a browser to your
|
||||
microblog's main directory and see the "Public Timeline", which
|
||||
will be empty. If not, magic has happened! You can now register a
|
||||
new user, post some notices, edit your profile, etc. However, you
|
||||
may want to wait to do that stuff if you think you can set up
|
||||
"fancy URLs" (see below), since some URLs are stored in the database.
|
||||
Enter the database connection information and your site name. The
|
||||
install program will configure your site and install the initial,
|
||||
almost-empty database.
|
||||
|
||||
8. You should now be able to navigate to your microblog's main directory
|
||||
and see the "Public Timeline", which will be empty. If not, magic
|
||||
has happened! You can now register a new user, post some notices,
|
||||
edit your profile, etc. However, you may want to wait to do that stuff
|
||||
if you think you can set up "fancy URLs" (see below), since some
|
||||
URLs are stored in the database.
|
||||
|
||||
Fancy URLs
|
||||
----------
|
||||
|
||||
By default, Laconica will have big long sloppy URLs that are hard for
|
||||
people to remember or use. For example, a user's home profile might be
|
||||
By default, Laconica will use URLs that include the main PHP program's
|
||||
name in them. For example, a user's home profile might be
|
||||
found at:
|
||||
|
||||
http://example.org/mublog/index.php?action=showstream&nickname=fred
|
||||
http://example.org/mublog/index.php/mublog/fred
|
||||
|
||||
On certain systems that don't support this kind of syntax, they'll
|
||||
look like this:
|
||||
|
||||
http://example.org/mublog/index.php?p=mublog/fred
|
||||
|
||||
It's possible to configure the software so it looks like this instead:
|
||||
|
||||
http://example.org/mublog/fred
|
||||
|
||||
These "fancy URLs" are more readable and memorable for users. To use
|
||||
fancy URLs, you must either have Apache 2.2.x with .htaccess enabled
|
||||
and mod_redirect enabled, -OR- know how to configure "url redirection"
|
||||
in your server.
|
||||
fancy URLs, you must either have Apache 2.x with .htaccess enabled and
|
||||
mod_redirect enabled, -OR- know how to configure "url redirection" in
|
||||
your server.
|
||||
|
||||
1. Copy the htaccess.sample file to .htaccess in your Laconica
|
||||
directory. Note: if you have control of your server's httpd.conf or
|
||||
@ -348,10 +347,6 @@ like:
|
||||
If you changed your HTTP server configuration, you may need to restart
|
||||
the server first.
|
||||
|
||||
If you have problems with the .htaccess file on versions of Apache
|
||||
earlier than 2.2.x, try changing the regular expressions in the
|
||||
htaccess.sample file that use "\w" to just use ".".
|
||||
|
||||
Sphinx
|
||||
------
|
||||
|
||||
@ -511,7 +506,7 @@ server is probably a good idea for high-volume sites.
|
||||
needs as a parameter the install path; if you run it from the
|
||||
Laconica dir, "." should suffice.
|
||||
|
||||
This will run six (for now) queue handlers:
|
||||
This will run eight (for now) queue handlers:
|
||||
|
||||
* xmppdaemon.php - listens for new XMPP messages from users and stores
|
||||
them as notices in the database.
|
||||
@ -525,6 +520,10 @@ This will run six (for now) queue handlers:
|
||||
of registered users.
|
||||
* xmppconfirmhandler.php - sends confirmation messages to registered
|
||||
users.
|
||||
* twitterqueuehandler.php - sends queued notices to Twitter for user
|
||||
who have opted to set up Twitter bridging.
|
||||
* facebookqueuehandler.php - sends queued notices to Facebook for users
|
||||
of the built-in Facebook application.
|
||||
|
||||
Note that these queue daemons are pretty raw, and need your care. In
|
||||
particular, they leak memory, and you may want to restart them on a
|
||||
@ -557,6 +556,53 @@ Sample cron job:
|
||||
# Update Twitter friends subscriptions every half hour
|
||||
0,30 * * * * /path/to/php /path/to/laconica/scripts/synctwitterfriends.php>&/dev/null
|
||||
|
||||
Built-in Facebook Application
|
||||
-----------------------------
|
||||
|
||||
Laconica's Facebook application allows your users to automatically
|
||||
update their Facebook statuses with their latest notices, invite
|
||||
their friends to use the app (and thus your site), view their notice
|
||||
timelines, and post notices -- all from within Facebook. The application
|
||||
is built into Laconica and runs on your host. For automatic Facebook
|
||||
status updating to work you will need to enable queuing and run the
|
||||
facebookqueuehandler.php daemon (see the "Queues and daemons" section
|
||||
above).
|
||||
|
||||
Quick setup instructions*:
|
||||
|
||||
Install the Facebook Developer application on Facebook:
|
||||
|
||||
http://www.facebook.com/developers/
|
||||
|
||||
Use it to create a new application and generate an API key and secret.
|
||||
Uncomment the Facebook app section of your config.php and copy in the
|
||||
key and secret, e.g.:
|
||||
|
||||
# Config section for the built-in Facebook application
|
||||
$config['facebook']['apikey'] = 'APIKEY';
|
||||
$config['facebook']['secret'] = 'SECRET';
|
||||
|
||||
In Facebook's application editor, specify the following URLs for your app:
|
||||
|
||||
- Callback URL: http://example.net/mublog/facebook/
|
||||
- Post-Remove URL: http://example.net/mublog/facebook/remove
|
||||
- Post-Add Redirect URL: http://apps.facebook.com/yourapp/
|
||||
- Canvas URL: http://apps.facebook.com/yourapp/
|
||||
|
||||
(Replace 'example.net' with your host's URL, 'mublog' with the path
|
||||
to your Laconica installation, and 'yourapp' with the name of the
|
||||
Facebook application you created.)
|
||||
|
||||
Additionally, Choose "Web" for Application type in the Advanced tab.
|
||||
In the "Canvas setting" section, choose the "FBML" for Render Method,
|
||||
"Smart Size" for IFrame size, and "Full width (760px)" for Canvas Width.
|
||||
Everything else can be left with default values.
|
||||
|
||||
*For more detailed instructions please see the installation guide on the
|
||||
Laconica wiki:
|
||||
|
||||
http://laconi.ca/trac/wiki/FacebookApplication
|
||||
|
||||
Sitemaps
|
||||
--------
|
||||
|
||||
@ -597,7 +643,7 @@ to these resources.
|
||||
Themes
|
||||
------
|
||||
|
||||
There are two themes shipped with this version of Laconica: "stoica",
|
||||
There are two themes shipped with this version of Laconica: "identica",
|
||||
which is what the Identi.ca site uses, and "default", which is a good
|
||||
basis for other sites.
|
||||
|
||||
|
@ -42,9 +42,9 @@ class AllAction extends Action
|
||||
if (!$this->page) {
|
||||
$this->page = 1;
|
||||
}
|
||||
|
||||
|
||||
common_set_returnto($this->selfUrl());
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -69,13 +69,22 @@ class AllAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
function showFeeds()
|
||||
function getFeeds()
|
||||
{
|
||||
$this->element('link', array('rel' => 'alternate',
|
||||
'href' => common_local_url('allrss', array('nickname' =>
|
||||
$this->user->nickname)),
|
||||
'type' => 'application/rss+xml',
|
||||
'title' => sprintf(_('Feed for friends of %s'), $this->user->nickname)));
|
||||
return array(new Feed(Feed::RSS1,
|
||||
common_local_url('allrss', array('nickname' =>
|
||||
$this->user->nickname)),
|
||||
sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->user->nickname)),
|
||||
new Feed(Feed::RSS2,
|
||||
common_local_url('api', array('apiaction' => 'statuses',
|
||||
'method' => 'friends',
|
||||
'argument' => $this->user->nickname.'.rss')),
|
||||
sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->user->nickname)),
|
||||
new Feed(Feed::ATOM,
|
||||
common_local_url('api', array('apiaction' => 'statuses',
|
||||
'method' => 'friends',
|
||||
'argument' => $this->user->nickname.'.atom')),
|
||||
sprintf(_('Feed for friends of %s (Atom)'), $this->user->nickname)));
|
||||
}
|
||||
|
||||
function showLocalNav()
|
||||
@ -84,15 +93,6 @@ class AllAction extends Action
|
||||
$nav->show();
|
||||
}
|
||||
|
||||
function showExportData()
|
||||
{
|
||||
$fl = new FeedList($this);
|
||||
$fl->show(array(0=>array('href'=>common_local_url('allrss', array('nickname' => $this->user->nickname)),
|
||||
'type' => 'rss',
|
||||
'version' => 'RSS 1.0',
|
||||
'item' => 'allrss')));
|
||||
}
|
||||
|
||||
function showContent()
|
||||
{
|
||||
$notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
|
||||
@ -110,7 +110,7 @@ class AllAction extends Action
|
||||
$user =& common_current_user();
|
||||
if ($user && ($user->id == $this->user->id)) {
|
||||
$this->element('h1', NULL, _("You and friends"));
|
||||
} else {
|
||||
} else {
|
||||
$this->element('h1', NULL, sprintf(_('%s and friends'), $this->user->nickname));
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,9 @@ class AllrssAction extends Rss10Action
|
||||
|
||||
/**
|
||||
* Initialization.
|
||||
*
|
||||
*
|
||||
* @param array $args Web and URL arguments
|
||||
*
|
||||
* @return boolean false if user doesn't exist
|
||||
*/
|
||||
function prepare($args)
|
||||
@ -81,7 +83,7 @@ class AllrssAction extends Rss10Action
|
||||
{
|
||||
$user = $this->user;
|
||||
$notice = $user->noticesWithFriends(0, $limit);
|
||||
|
||||
|
||||
while ($notice->fetch()) {
|
||||
$notices[] = clone($notice);
|
||||
}
|
||||
@ -104,7 +106,8 @@ class AllrssAction extends Rss10Action
|
||||
'link' => common_local_url('all',
|
||||
array('nickname' =>
|
||||
$user->nickname)),
|
||||
'description' => sprintf(_('Feed for friends of %s'), $user->nickname));
|
||||
'description' => sprintf(_('Feed for friends of %s'),
|
||||
$user->nickname));
|
||||
return $c;
|
||||
}
|
||||
|
||||
@ -123,10 +126,5 @@ class AllrssAction extends Rss10Action
|
||||
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||
return $avatar ? $avatar->url : null;
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,13 +131,13 @@ class ApiAction extends Action
|
||||
'statuses/followers',
|
||||
'favorites/favorites');
|
||||
|
||||
# If the site is "private", all API methods need authentication
|
||||
|
||||
if (common_config('site', 'private')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$fullname = "$this->api_action/$this->api_method";
|
||||
|
||||
// If the site is "private", all API methods except laconica/config
|
||||
// need authentication
|
||||
if (common_config('site', 'private')) {
|
||||
return $fullname != 'laconica/config' || false;
|
||||
}
|
||||
|
||||
if (in_array($fullname, $bareauth)) {
|
||||
# bareauth: only needs auth if without an argument
|
||||
|
@ -145,6 +145,7 @@ class AvatarsettingsAction extends AccountSettingsAction
|
||||
'height' => AVATAR_PROFILE_SIZE,
|
||||
'alt' => $user->nickname));
|
||||
$this->elementEnd('div');
|
||||
$this->submit('delete', _('Delete'));
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
|
||||
@ -256,6 +257,8 @@ class AvatarsettingsAction extends AccountSettingsAction
|
||||
$this->uploadAvatar();
|
||||
} else if ($this->arg('crop')) {
|
||||
$this->cropAvatar();
|
||||
} else if ($this->arg('delete')) {
|
||||
$this->deleteAvatar();
|
||||
} else {
|
||||
$this->showForm(_('Unexpected form submission.'));
|
||||
}
|
||||
@ -321,13 +324,14 @@ class AvatarsettingsAction extends AccountSettingsAction
|
||||
return;
|
||||
}
|
||||
|
||||
// If image is not being cropped assume pos & dimentions of original
|
||||
$file_d = ($filedata['width'] > $filedata['height'])
|
||||
? $filedata['height'] : $filedata['width'];
|
||||
|
||||
$dest_x = $this->arg('avatar_crop_x') ? $this->arg('avatar_crop_x'):0;
|
||||
$dest_y = $this->arg('avatar_crop_y') ? $this->arg('avatar_crop_y'):0;
|
||||
$dest_w = $this->arg('avatar_crop_w') ? $this->arg('avatar_crop_w'):$filedata['width'];
|
||||
$dest_h = $this->arg('avatar_crop_h') ? $this->arg('avatar_crop_h'):$filedata['height'];
|
||||
$size = min($dest_w, $dest_h);
|
||||
$size = ($size > MAX_ORIGINAL) ? MAX_ORIGINAL:$size;
|
||||
$dest_w = $this->arg('avatar_crop_w') ? $this->arg('avatar_crop_w'):$file_d;
|
||||
$dest_h = $this->arg('avatar_crop_h') ? $this->arg('avatar_crop_h'):$file_d;
|
||||
$size = min($dest_w, $dest_h, MAX_ORIGINAL);
|
||||
|
||||
$user = common_current_user();
|
||||
$profile = $user->getProfile();
|
||||
@ -340,10 +344,34 @@ class AvatarsettingsAction extends AccountSettingsAction
|
||||
unset($_SESSION['FILEDATA']);
|
||||
$this->mode = 'upload';
|
||||
$this->showForm(_('Avatar updated.'), true);
|
||||
common_broadcast_profile($profile);
|
||||
} else {
|
||||
$this->showForm(_('Failed updating avatar.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rid of the current avatar.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function deleteAvatar()
|
||||
{
|
||||
$user = common_current_user();
|
||||
$profile = $user->getProfile();
|
||||
|
||||
$avatar = $profile->getOriginalAvatar();
|
||||
$avatar->delete();
|
||||
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||
$avatar->delete();
|
||||
$avatar = $profile->getAvatar(AVATAR_STREAM_SIZE);
|
||||
$avatar->delete();
|
||||
$avatar = $profile->getAvatar(AVATAR_MINI_SIZE);
|
||||
$avatar->delete();
|
||||
|
||||
$this->showForm(_('Avatar deleted.'), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the jCrop stylesheet
|
||||
|
123
actions/conversation.php
Normal file
123
actions/conversation.php
Normal file
@ -0,0 +1,123 @@
|
||||
<?php
|
||||
/**
|
||||
* Display a conversation in the browser
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Action
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://laconi.ca/
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Conversation tree in the browser
|
||||
*
|
||||
* @category Action
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
class ConversationAction extends Action
|
||||
{
|
||||
var $id = null;
|
||||
var $notices = null;
|
||||
var $page = null;
|
||||
|
||||
/**
|
||||
* Initialization.
|
||||
*
|
||||
* @param array $args Web and URL arguments
|
||||
*
|
||||
* @return boolean false if id not passed in
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
$this->id = $this->trimmed('id');
|
||||
if (!$this->id) {
|
||||
return false;
|
||||
}
|
||||
$this->notices = $this->getNotices();
|
||||
$this->page = $this->trimmed('page');
|
||||
if (empty($this->page)) {
|
||||
$this->page = 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get notices
|
||||
*
|
||||
* @param integer $limit max number of notices to return
|
||||
*
|
||||
* @return array notices
|
||||
*/
|
||||
|
||||
function getNotices($limit=0)
|
||||
{
|
||||
$qry = 'SELECT notice.*, '.
|
||||
'FROM notice WHERE conversation = %d '.
|
||||
'ORDER BY created ';
|
||||
|
||||
$offset = 0;
|
||||
$limit = NOTICES_PER_PAGE + 1;
|
||||
|
||||
if (common_config('db', 'type') == 'pgsql') {
|
||||
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
|
||||
} else {
|
||||
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
|
||||
}
|
||||
|
||||
return Notice::getStream(sprintf($qry, $this->id),
|
||||
'notice:conversation:'.$this->id,
|
||||
$offset, $limit);
|
||||
}
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
return _("Conversation");
|
||||
}
|
||||
|
||||
function showContent()
|
||||
{
|
||||
// FIXME this needs to be a tree, not a list
|
||||
|
||||
$nl = new NoticeList($this->notices, $this);
|
||||
|
||||
$cnt = $nl->show();
|
||||
|
||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$this->page, 'conversation', array('id' => $this->id));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ class DocAction extends Action
|
||||
|
||||
/**
|
||||
* Class handler.
|
||||
*
|
||||
*
|
||||
* @param array $args array of arguments
|
||||
*
|
||||
* @return nothing
|
||||
@ -59,7 +59,7 @@ class DocAction extends Action
|
||||
{
|
||||
parent::handle($args);
|
||||
$this->title = $this->trimmed('title');
|
||||
$this->filename = INSTALLDIR.'/doc/'.$this->title;
|
||||
$this->filename = INSTALLDIR.'/doc-src/'.$this->title;
|
||||
if (!file_exists($this->filename)) {
|
||||
$this->clientError(_('No such document.'));
|
||||
return;
|
||||
@ -71,14 +71,14 @@ class DocAction extends Action
|
||||
function showPageTitle() {
|
||||
$this->element('h1', array('class' => 'entry-title'), $this->title());
|
||||
}
|
||||
|
||||
|
||||
// overrided to add hentry, and content-inner classes
|
||||
function showContentBlock()
|
||||
{
|
||||
$this->elementStart('div', array('id' => 'content', 'class' => 'hentry'));
|
||||
$this->showPageTitle();
|
||||
$this->showPageNoticeBlock();
|
||||
$this->elementStart('div', array('id' => 'content_inner',
|
||||
$this->elementStart('div', array('id' => 'content_inner',
|
||||
'class' => 'entry-content'));
|
||||
// show the actual content (forms, lists, whatever)
|
||||
$this->showContent();
|
||||
@ -88,7 +88,7 @@ class DocAction extends Action
|
||||
|
||||
/**
|
||||
* Display content.
|
||||
*
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
function showContent()
|
||||
@ -100,7 +100,7 @@ class DocAction extends Action
|
||||
|
||||
/**
|
||||
* Page title.
|
||||
*
|
||||
*
|
||||
* @return page title
|
||||
*/
|
||||
function title()
|
||||
|
@ -164,6 +164,11 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
$user->emailnotifymsg);
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('emailnotifyattn',
|
||||
_('Send me email when someone sends me an "@-reply".'),
|
||||
$user->emailnotifyattn);
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('emailnotifynudge',
|
||||
_('Allow friends to nudge me and send me an email.'),
|
||||
$user->emailnotifynudge);
|
||||
@ -255,6 +260,7 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
$emailnotifyfav = $this->boolean('emailnotifyfav');
|
||||
$emailnotifymsg = $this->boolean('emailnotifymsg');
|
||||
$emailnotifynudge = $this->boolean('emailnotifynudge');
|
||||
$emailnotifyattn = $this->boolean('emailnotifyattn');
|
||||
$emailmicroid = $this->boolean('emailmicroid');
|
||||
$emailpost = $this->boolean('emailpost');
|
||||
|
||||
@ -270,6 +276,7 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
$user->emailnotifyfav = $emailnotifyfav;
|
||||
$user->emailnotifymsg = $emailnotifymsg;
|
||||
$user->emailnotifynudge = $emailnotifynudge;
|
||||
$user->emailnotifyattn = $emailnotifyattn;
|
||||
$user->emailmicroid = $emailmicroid;
|
||||
$user->emailpost = $emailpost;
|
||||
|
||||
|
@ -169,8 +169,14 @@ class FavoritedAction extends Action
|
||||
|
||||
function showContent()
|
||||
{
|
||||
if (common_config('db', 'type') == 'pgsql') {
|
||||
$weightexpr='sum(exp(-extract(epoch from (now() - fave.modified)) / %s))';
|
||||
} else {
|
||||
$weightexpr='sum(exp(-(now() - fave.modified) / %s))';
|
||||
}
|
||||
|
||||
$qry = 'SELECT notice.*, '.
|
||||
'sum(exp(-(now() - fave.modified) / %s)) as weight ' .
|
||||
$weightexpr . ' as weight ' .
|
||||
'FROM notice JOIN fave ON notice.id = fave.notice_id ' .
|
||||
'GROUP BY fave.notice_id ' .
|
||||
'ORDER BY weight DESC';
|
||||
|
@ -83,7 +83,7 @@ class FinishopenidloginAction extends Action
|
||||
|
||||
function showContent()
|
||||
{
|
||||
if ($this->message_text) {
|
||||
if (!empty($this->message_text)) {
|
||||
$this->element('p', null, $this->message);
|
||||
return;
|
||||
}
|
||||
@ -232,7 +232,8 @@ class FinishopenidloginAction extends Action
|
||||
return;
|
||||
}
|
||||
|
||||
if ($sreg['country']) {
|
||||
$location = '';
|
||||
if (!empty($sreg['country'])) {
|
||||
if ($sreg['postcode']) {
|
||||
# XXX: use postcode to get city and region
|
||||
# XXX: also, store postcode somewhere -- it's valuable!
|
||||
@ -242,12 +243,16 @@ class FinishopenidloginAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
if ($sreg['fullname'] && mb_strlen($sreg['fullname']) <= 255) {
|
||||
if (!empty($sreg['fullname']) && mb_strlen($sreg['fullname']) <= 255) {
|
||||
$fullname = $sreg['fullname'];
|
||||
} else {
|
||||
$fullname = '';
|
||||
}
|
||||
|
||||
if ($sreg['email'] && Validate::email($sreg['email'], true)) {
|
||||
if (!empty($sreg['email']) && Validate::email($sreg['email'], true)) {
|
||||
$email = $sreg['email'];
|
||||
} else {
|
||||
$email = '';
|
||||
}
|
||||
|
||||
# XXX: add language
|
||||
@ -328,7 +333,7 @@ class FinishopenidloginAction extends Action
|
||||
|
||||
# Try the passed-in nickname
|
||||
|
||||
if ($sreg['nickname']) {
|
||||
if (!empty($sreg['nickname'])) {
|
||||
$nickname = $this->nicknamize($sreg['nickname']);
|
||||
if ($this->isNewNickname($nickname)) {
|
||||
return $nickname;
|
||||
@ -337,7 +342,7 @@ class FinishopenidloginAction extends Action
|
||||
|
||||
# Try the full name
|
||||
|
||||
if ($sreg['fullname']) {
|
||||
if (!empty($sreg['fullname'])) {
|
||||
$fullname = $this->nicknamize($sreg['fullname']);
|
||||
if ($this->isNewNickname($fullname)) {
|
||||
return $fullname;
|
||||
|
@ -237,7 +237,13 @@ class FinishremotesubscribeAction extends Action
|
||||
{
|
||||
$temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
|
||||
copy($url, $temp_filename);
|
||||
return $profile->setOriginal($temp_filename);
|
||||
$imagefile = new ImageFile($profile->id, $temp_filename);
|
||||
$filename = Avatar::filename($profile->id,
|
||||
image_type_to_extension($imagefile->type),
|
||||
null,
|
||||
common_timestamp());
|
||||
rename($temp_filename, Avatar::path($filename));
|
||||
return $profile->setOriginal($filename);
|
||||
}
|
||||
|
||||
function access_token($omb)
|
||||
@ -277,7 +283,7 @@ class FinishremotesubscribeAction extends Action
|
||||
$fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
|
||||
$result = $fetcher->post($req->get_normalized_http_url(),
|
||||
$req->to_postdata(),
|
||||
array('User-Agent' => 'Laconica/' . LACONICA_VERSION));
|
||||
array('User-Agent: Laconica/' . LACONICA_VERSION));
|
||||
|
||||
common_debug('got result: "'.print_r($result,true).'"', __FILE__);
|
||||
|
||||
|
@ -111,13 +111,13 @@ class groupRssAction extends Rss10Action
|
||||
{
|
||||
|
||||
$group = $this->group;
|
||||
|
||||
|
||||
if (is_null($group)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
$notice = $group->getNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit);
|
||||
|
||||
|
||||
while ($notice->fetch()) {
|
||||
$notices[] = clone($notice);
|
||||
}
|
||||
@ -141,13 +141,4 @@ class groupRssAction extends Rss10Action
|
||||
{
|
||||
return $this->group->homepage_logo;
|
||||
}
|
||||
|
||||
# override parent to add X-SUP-ID URL
|
||||
|
||||
function initRss($limit=0)
|
||||
{
|
||||
$url = common_local_url('sup', null, $this->group->id);
|
||||
header('X-SUP-ID: '.$url);
|
||||
parent::initRss($limit);
|
||||
}
|
||||
}
|
||||
|
@ -108,13 +108,15 @@ class LoginAction extends Action
|
||||
$nickname = common_canonical_nickname($this->trimmed('nickname'));
|
||||
$password = $this->arg('password');
|
||||
|
||||
if (!common_check_user($nickname, $password)) {
|
||||
$user = common_check_user($nickname, $password);
|
||||
|
||||
if (!$user) {
|
||||
$this->showForm(_('Incorrect username or password.'));
|
||||
return;
|
||||
}
|
||||
|
||||
// success!
|
||||
if (!common_set_user($nickname)) {
|
||||
if (!common_set_user($user)) {
|
||||
$this->serverError(_('Error setting user.'));
|
||||
return;
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ class NewmessageAction extends Action
|
||||
|
||||
function showNoticeForm()
|
||||
{
|
||||
$message_form = new MessageForm($this, $this->to, $this->content);
|
||||
$message_form = new MessageForm($this, $this->other, $this->content);
|
||||
$message_form->show();
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,12 @@ class NewnoticeAction extends Action
|
||||
return;
|
||||
}
|
||||
|
||||
$this->saveNewNotice();
|
||||
try {
|
||||
$this->saveNewNotice();
|
||||
} catch (Exception $e) {
|
||||
$this->showForm($e->getMessage());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$this->showForm();
|
||||
}
|
||||
@ -123,15 +128,13 @@ class NewnoticeAction extends Action
|
||||
$content = $this->trimmed('status_textarea');
|
||||
|
||||
if (!$content) {
|
||||
$this->showForm(_('No content!'));
|
||||
return;
|
||||
$this->clientError(_('No content!'));
|
||||
} else {
|
||||
$content_shortened = common_shorten_links($content);
|
||||
|
||||
if (mb_strlen($content_shortened) > 140) {
|
||||
$this->showForm(_('That\'s too long. '.
|
||||
'Max notice size is 140 chars.'));
|
||||
return;
|
||||
$this->clientError(_('That\'s too long. '.
|
||||
'Max notice size is 140 chars.'));
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,12 +152,17 @@ class NewnoticeAction extends Action
|
||||
}
|
||||
|
||||
$replyto = $this->trimmed('inreplyto');
|
||||
#If an ID of 0 is wrongly passed here, it will cause a database error,
|
||||
#so override it...
|
||||
if ($replyto == 0) {
|
||||
$replyto = 'false';
|
||||
}
|
||||
|
||||
$notice = Notice::saveNew($user->id, $content, 'web', 1,
|
||||
($replyto == 'false') ? null : $replyto);
|
||||
|
||||
if (is_string($notice)) {
|
||||
$this->showForm($notice);
|
||||
$this->clientError($notice);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -250,7 +258,7 @@ class NewnoticeAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
$notice_form = new NoticeForm($this, $content);
|
||||
$notice_form = new NoticeForm($this, '', $content);
|
||||
$notice_form->show();
|
||||
}
|
||||
|
||||
|
@ -57,11 +57,11 @@ class NoticesearchAction extends SearchAction
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get instructions
|
||||
*
|
||||
* @return string instruction text
|
||||
*
|
||||
* @return string instruction text
|
||||
*/
|
||||
function getInstructions()
|
||||
{
|
||||
@ -70,7 +70,7 @@ class NoticesearchAction extends SearchAction
|
||||
|
||||
/**
|
||||
* Get title
|
||||
*
|
||||
*
|
||||
* @return string title
|
||||
*/
|
||||
function title()
|
||||
@ -78,6 +78,20 @@ class NoticesearchAction extends SearchAction
|
||||
return _('Text search');
|
||||
}
|
||||
|
||||
function getFeeds()
|
||||
{
|
||||
$q = $this->trimmed('q');
|
||||
|
||||
if (!$q) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return array(new Feed(Feed::RSS1, common_local_url('noticesearchrss',
|
||||
array('q' => $q)),
|
||||
sprintf(_('Search results for "%s" on %s'),
|
||||
$q, common_config('site', 'name'))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show results
|
||||
*
|
||||
@ -99,143 +113,58 @@ class NoticesearchAction extends SearchAction
|
||||
} else {
|
||||
$cnt = $notice->find();
|
||||
}
|
||||
if ($cnt > 0) {
|
||||
$terms = preg_split('/[\s,]+/', $q);
|
||||
$this->elementStart('ul', array('class' => 'notices'));
|
||||
for ($i = 0; $i < min($cnt, NOTICES_PER_PAGE); $i++) {
|
||||
if ($notice->fetch()) {
|
||||
$this->showNotice($notice, $terms);
|
||||
} else {
|
||||
// shouldn't happen!
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->elementEnd('ul');
|
||||
} else {
|
||||
if ($cnt === 0) {
|
||||
$this->element('p', 'error', _('No results'));
|
||||
}
|
||||
|
||||
$this->pagination($page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$page, 'noticesearch', array('q' => $q));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show header
|
||||
*
|
||||
* @param array $arr array containing the query
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function extraHead()
|
||||
{
|
||||
$q = $this->trimmed('q');
|
||||
if ($q) {
|
||||
$this->element('link', array('rel' => 'alternate',
|
||||
'href' => common_local_url('noticesearchrss',
|
||||
array('q' => $q)),
|
||||
'type' => 'application/rss+xml',
|
||||
'title' => _('Search Stream Feed')));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show notice
|
||||
*
|
||||
* @param class $notice notice
|
||||
* @param array $terms terms to highlight
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @todo refactor and combine with StreamAction::showNotice()
|
||||
*/
|
||||
function showNotice($notice, $terms)
|
||||
{
|
||||
$profile = $notice->getProfile();
|
||||
if (!$profile) {
|
||||
common_log_db_error($notice, 'SELECT', __FILE__);
|
||||
$this->serverError(_('Notice without matching profile'));
|
||||
return;
|
||||
}
|
||||
// XXX: RDFa
|
||||
$this->elementStart('li', array('class' => 'hentry notice',
|
||||
'id' => 'notice-' . $notice->id));
|
||||
$terms = preg_split('/[\s,]+/', $q);
|
||||
$nl = new SearchNoticeList($notice, $this, $terms);
|
||||
|
||||
$this->elementStart('div', 'entry-title');
|
||||
$this->elementStart('span', 'vcard author');
|
||||
$avatar = $profile->getAvatar(AVATAR_STREAM_SIZE);
|
||||
$this->elementStart('a', array('href' => $profile->profileurl,
|
||||
'class' => 'url'));
|
||||
$this->element('img', array('src' => ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_STREAM_SIZE),
|
||||
'class' => 'avatar photo',
|
||||
'width' => AVATAR_STREAM_SIZE,
|
||||
'height' => AVATAR_STREAM_SIZE,
|
||||
'alt' =>
|
||||
($profile->fullname) ? $profile->fullname :
|
||||
$profile->nickname));
|
||||
$this->element('span', 'nickname fn', $profile->nickname);
|
||||
$this->elementEnd('a');
|
||||
$this->elementEnd('span');
|
||||
$cnt = $nl->show();
|
||||
|
||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$this->page, 'noticesearch', array('q' => $q));
|
||||
}
|
||||
function isReadOnly()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class SearchNoticeList extends NoticeList {
|
||||
function __construct($notice, $out=null, $terms)
|
||||
{
|
||||
parent::__construct($notice, $out);
|
||||
$this->terms = $terms;
|
||||
}
|
||||
|
||||
function newListItem($notice)
|
||||
{
|
||||
return new SearchNoticeListItem($notice, $this->out, $this->terms);
|
||||
}
|
||||
}
|
||||
|
||||
class SearchNoticeListItem extends NoticeListItem {
|
||||
function __construct($notice, $out=null, $terms)
|
||||
{
|
||||
parent::__construct($notice, $out);
|
||||
$this->terms = $terms;
|
||||
}
|
||||
|
||||
function showContent()
|
||||
{
|
||||
// FIXME: URL, image, video, audio
|
||||
$this->elementStart('p', array('class' => 'entry-content'));
|
||||
if ($notice->rendered) {
|
||||
$this->raw($this->highlight($notice->rendered, $terms));
|
||||
$this->out->elementStart('p', array('class' => 'entry-content'));
|
||||
if ($this->notice->rendered) {
|
||||
$this->out->raw($this->highlight($this->notice->rendered, $this->terms));
|
||||
} else {
|
||||
// XXX: may be some uncooked notices in the DB,
|
||||
// we cook them right now. This should probably disappear in future
|
||||
// versions (>> 0.4.x)
|
||||
$this->raw($this->highlight(common_render_content($notice->content, $notice), $terms));
|
||||
$this->out->raw($this->highlight(common_render_content($this->notice->content, $this->notice), $this->terms));
|
||||
}
|
||||
$this->elementEnd('p');
|
||||
$this->elementEnd('div');
|
||||
$this->out->elementEnd('p');
|
||||
|
||||
$noticeurl = common_local_url('shownotice', array('notice' => $notice->id));
|
||||
$this->elementStart('div', 'entry-content');
|
||||
$this->elementStart('dl', 'timestamp');
|
||||
$this->element('dt', null, _('Published'));
|
||||
$this->elementStart('dd', null);
|
||||
$this->elementStart('a', array('rel' => 'bookmark',
|
||||
'href' => $noticeurl));
|
||||
$dt = common_date_iso8601($notice->created);
|
||||
$this->element('abbr', array('class' => 'published',
|
||||
'title' => $dt),
|
||||
common_date_string($notice->created));
|
||||
$this->elementEnd('a');
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
|
||||
if ($notice->reply_to) {
|
||||
$replyurl = common_local_url('shownotice',
|
||||
array('notice' => $this->notice->reply_to));
|
||||
$this->elementStart('dl', 'response');
|
||||
$this->element('dt', null, _('To'));
|
||||
$this->elementStart('dd');
|
||||
$this->element('a', array('href' => $replyurl,
|
||||
'rel' => 'in-reply-to'),
|
||||
_('in reply to'));
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
}
|
||||
$this->elementEnd('div');
|
||||
|
||||
$this->elementStart('div', 'notice-options');
|
||||
|
||||
$reply_url = common_local_url('newnotice',
|
||||
array('replyto' => $profile->nickname));
|
||||
|
||||
$this->elementStart('dl', 'notice_reply');
|
||||
$this->element('dt', null, _('Reply to this notice'));
|
||||
$this->elementStart('dd');
|
||||
$this->elementStart('a', array('href' => $reply_url,
|
||||
'title' => _('Reply to this notice')));
|
||||
$this->text(_('Reply'));
|
||||
$this->element('span', 'notice_id', $notice->id);
|
||||
$this->elementEnd('a');
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
$this->elementEnd('div');
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -248,7 +177,7 @@ class NoticesearchAction extends SearchAction
|
||||
*/
|
||||
function highlight($text, $terms)
|
||||
{
|
||||
/* Highligh serach terms */
|
||||
/* Highligh search terms */
|
||||
$pattern = '/('.implode('|', array_map('htmlspecialchars', $terms)).')/i';
|
||||
$result = preg_replace($pattern, '<strong>\\1</strong>', $text);
|
||||
|
||||
@ -259,10 +188,5 @@ class NoticesearchAction extends SearchAction
|
||||
} while ($count);
|
||||
return $result;
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,33 +86,9 @@ class PeoplesearchAction extends SearchAction
|
||||
}
|
||||
|
||||
$profile->free();
|
||||
|
||||
|
||||
$this->pagination($page > 1, $cnt > PROFILES_PER_PAGE,
|
||||
$page, 'peoplesearch', array('q' => $q));
|
||||
}
|
||||
}
|
||||
|
||||
class PeopleSearchResults extends ProfileList
|
||||
{
|
||||
var $terms = null;
|
||||
var $pattern = null;
|
||||
|
||||
function __construct($profile, $terms, $action)
|
||||
{
|
||||
parent::__construct($profile, $terms, $action);
|
||||
$this->terms = array_map('preg_quote',
|
||||
array_map('htmlspecialchars', $terms));
|
||||
$this->pattern = '/('.implode('|',$terms).')/i';
|
||||
}
|
||||
|
||||
function highlight($text)
|
||||
{
|
||||
return preg_replace($this->pattern, '<strong>\\1</strong>', htmlspecialchars($text));
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,9 +73,9 @@ class PublicAction extends Action
|
||||
{
|
||||
parent::prepare($args);
|
||||
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
||||
|
||||
|
||||
common_set_returnto($this->selfUrl());
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -119,12 +119,20 @@ class PublicAction extends Action
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showFeeds()
|
||||
function getFeeds()
|
||||
{
|
||||
$this->element('link', array('rel' => 'alternate',
|
||||
'href' => common_local_url('publicrss'),
|
||||
'type' => 'application/rss+xml',
|
||||
'title' => _('Public Stream Feed')));
|
||||
return array(new Feed(Feed::RSS1, common_local_url('publicrss'),
|
||||
_('Public Stream Feed (RSS 1.0)')),
|
||||
new Feed(Feed::RSS2,
|
||||
common_local_url('api',
|
||||
array('apiaction' => 'statuses',
|
||||
'method' => 'public_timeline.rss')),
|
||||
_('Public Stream Feed (RSS 2.0)')),
|
||||
new Feed(Feed::ATOM,
|
||||
common_local_url('api',
|
||||
array('apiaction' => 'statuses',
|
||||
'method' => 'public_timeline.atom')),
|
||||
_('Public Stream Feed (Atom)')));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -185,27 +193,6 @@ class PublicAction extends Action
|
||||
$this->page, 'public');
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a list of exported feeds for this page
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @todo I18N
|
||||
*/
|
||||
|
||||
function showExportData()
|
||||
{
|
||||
$fl = new FeedList($this);
|
||||
$fl->show(array(0 => array('href' => common_local_url('publicrss'),
|
||||
'type' => 'rss',
|
||||
'version' => 'RSS 1.0',
|
||||
'item' => 'publicrss'),
|
||||
1 => array('href' => common_local_url('publicatom'),
|
||||
'type' => 'atom',
|
||||
'version' => 'Atom 1.0',
|
||||
'item' => 'publicatom')));
|
||||
}
|
||||
|
||||
function showSections()
|
||||
{
|
||||
// $top = new TopPostersSection($this);
|
||||
|
@ -131,11 +131,13 @@ class RegisterAction extends Action
|
||||
|
||||
$code = $this->trimmed('code');
|
||||
|
||||
$invite = null;
|
||||
|
||||
if ($code) {
|
||||
$invite = Invitation::staticGet($code);
|
||||
}
|
||||
|
||||
if (common_config('site', 'inviteonly') && !($code && $invite)) {
|
||||
if (common_config('site', 'inviteonly') && !($code && !empty($invite))) {
|
||||
$this->clientError(_('Sorry, only invited people can register.'));
|
||||
return;
|
||||
}
|
||||
@ -341,6 +343,8 @@ class RegisterAction extends Action
|
||||
{
|
||||
$code = $this->trimmed('code');
|
||||
|
||||
$invite = null;
|
||||
|
||||
if ($code) {
|
||||
$invite = Invitation::staticGet($code);
|
||||
}
|
||||
@ -377,7 +381,7 @@ class RegisterAction extends Action
|
||||
_('Same as password above. Required.'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li');
|
||||
if ($invite && $invite->address_type == 'email') {
|
||||
if (!empty($invite) && $invite->address_type == 'email') {
|
||||
$this->input('email', _('Email'), $invite->address,
|
||||
_('Used only for updates, announcements, '.
|
||||
'and password recovery'));
|
||||
|
@ -321,8 +321,7 @@ class RemotesubscribeAction extends Action
|
||||
|
||||
$result = $fetcher->post($req->get_normalized_http_url(),
|
||||
$req->to_postdata(),
|
||||
array('User-Agent' => 'Laconica/' . LACONICA_VERSION));
|
||||
|
||||
array('User-Agent: Laconica/' . LACONICA_VERSION));
|
||||
if ($result->status != 200) {
|
||||
return null;
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ class RepliesAction extends Action
|
||||
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
||||
|
||||
common_set_returnto($this->selfUrl());
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -129,16 +129,13 @@ class RepliesAction extends Action
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showFeeds()
|
||||
function getFeeds()
|
||||
{
|
||||
$rssurl = common_local_url('repliesrss',
|
||||
array('nickname' => $this->user->nickname));
|
||||
$rsstitle = sprintf(_('Feed for replies to %s'), $this->user->nickname);
|
||||
|
||||
$this->element('link', array('rel' => 'alternate',
|
||||
'href' => $rssurl,
|
||||
'type' => 'application/rss+xml',
|
||||
'title' => $rsstitle));
|
||||
return array(new Feed(Feed::RSS1, $rssurl, $rsstitle));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -153,25 +150,6 @@ class RepliesAction extends Action
|
||||
$nav->show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the replies feed links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showExportData()
|
||||
{
|
||||
$fl = new FeedList($this);
|
||||
|
||||
$rssurl = common_local_url('repliesrss',
|
||||
array('nickname' => $this->user->nickname));
|
||||
|
||||
$fl->show(array(0=>array('href'=> $rssurl,
|
||||
'type' => 'rss',
|
||||
'version' => 'RSS 1.0',
|
||||
'item' => 'repliesrss')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the content
|
||||
*
|
||||
|
@ -113,7 +113,7 @@ class ShowfavoritesAction extends Action
|
||||
}
|
||||
|
||||
common_set_returnto($this->selfUrl());
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -136,10 +136,10 @@ class ShowfavoritesAction extends Action
|
||||
/**
|
||||
* Feeds for the <head> section
|
||||
*
|
||||
* @return void
|
||||
* @return array Feed objects to show
|
||||
*/
|
||||
|
||||
function showFeeds()
|
||||
function getFeeds()
|
||||
{
|
||||
$feedurl = common_local_url('favoritesrss',
|
||||
array('nickname' =>
|
||||
@ -147,10 +147,7 @@ class ShowfavoritesAction extends Action
|
||||
$feedtitle = sprintf(_('Feed for favorites of %s'),
|
||||
$this->user->nickname);
|
||||
|
||||
$this->element('link', array('rel' => 'alternate',
|
||||
'href' => $feedurl,
|
||||
'type' => 'application/rss+xml',
|
||||
'title' => $feedtitle));
|
||||
return array(new Feed(Feed::RSS1, $feedurl, $feedtitle));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -165,28 +162,6 @@ class ShowfavoritesAction extends Action
|
||||
$nav->show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the replies feed links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showExportData()
|
||||
{
|
||||
$feedurl = common_local_url('favoritesrss',
|
||||
array('nickname' =>
|
||||
$this->user->nickname));
|
||||
|
||||
$fl = new FeedList($this);
|
||||
|
||||
// XXX: I18N
|
||||
|
||||
$fl->show(array(0=>array('href'=> $feedurl,
|
||||
'type' => 'rss',
|
||||
'version' => 'RSS 1.0',
|
||||
'item' => 'Favorites')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the content
|
||||
*
|
||||
|
@ -244,7 +244,7 @@ class ShowgroupAction extends Action
|
||||
if ($this->group->location) {
|
||||
$this->elementStart('dl', 'entity_location');
|
||||
$this->element('dt', null, _('Location'));
|
||||
$this->element('dd', 'location', $this->group->location);
|
||||
$this->element('dd', 'label', $this->group->location);
|
||||
$this->elementEnd('dl');
|
||||
}
|
||||
|
||||
@ -292,37 +292,18 @@ class ShowgroupAction extends Action
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of links to feeds this page produces
|
||||
* Get a list of the feeds for this page
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showExportData()
|
||||
{
|
||||
$fl = new FeedList($this);
|
||||
$fl->show(array(0=>array('href'=>common_local_url('grouprss',
|
||||
array('nickname' => $this->group->nickname)),
|
||||
'type' => 'rss',
|
||||
'version' => 'RSS 1.0',
|
||||
'item' => 'notices')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of links to feeds this page produces
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showFeeds()
|
||||
function getFeeds()
|
||||
{
|
||||
$url =
|
||||
common_local_url('grouprss',
|
||||
array('nickname' => $this->group->nickname));
|
||||
|
||||
$this->element('link', array('rel' => 'alternate',
|
||||
'href' => $url,
|
||||
'type' => 'application/rss+xml',
|
||||
'title' => sprintf(_('Notice feed for %s group'),
|
||||
return array(new Feed(Feed::RSS1, $url, sprintf(_('Notice feed for %s group'),
|
||||
$this->group->nickname)));
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ class ShowstreamAction extends Action
|
||||
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
||||
|
||||
common_set_returnto($this->selfUrl());
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -155,58 +155,39 @@ class ShowstreamAction extends Action
|
||||
return;
|
||||
}
|
||||
|
||||
function showExportData()
|
||||
function getFeeds()
|
||||
{
|
||||
$fl = new FeedList($this);
|
||||
$fl->show(array(0=>array('href'=>common_local_url('userrss',
|
||||
array('nickname' => $this->user->nickname)),
|
||||
'type' => 'rss',
|
||||
'version' => 'RSS 1.0',
|
||||
'item' => 'notices'),
|
||||
1=>array('href'=>common_local_url('usertimeline',
|
||||
array('nickname' => $this->user->nickname)),
|
||||
'type' => 'atom',
|
||||
'version' => 'Atom 1.0',
|
||||
'item' => 'usertimeline'),
|
||||
2=>array('href'=>common_local_url('foaf',
|
||||
array('nickname' => $this->user->nickname)),
|
||||
'type' => 'rdf',
|
||||
'version' => 'FOAF',
|
||||
'item' => 'foaf')));
|
||||
}
|
||||
|
||||
function showFeeds()
|
||||
{
|
||||
$this->element('link', array('rel' => 'alternate',
|
||||
'type' => 'application/rss+xml',
|
||||
'href' => common_local_url('userrss',
|
||||
array('nickname' => $this->user->nickname)),
|
||||
'title' => sprintf(_('Notice feed for %s (RSS)'),
|
||||
$this->user->nickname)));
|
||||
|
||||
$this->element('link',
|
||||
array('rel' => 'alternate',
|
||||
'href' => common_local_url('api',
|
||||
array('apiaction' => 'statuses',
|
||||
'method' => 'user_timeline.atom',
|
||||
'argument' => $this->user->nickname)),
|
||||
'type' => 'application/atom+xml',
|
||||
'title' => sprintf(_('Notice feed for %s (Atom)'),
|
||||
$this->user->nickname)));
|
||||
return array(new Feed(Feed::RSS1,
|
||||
common_local_url('userrss',
|
||||
array('nickname' => $this->user->nickname)),
|
||||
sprintf(_('Notice feed for %s (RSS 1.0)'),
|
||||
$this->user->nickname)),
|
||||
new Feed(Feed::RSS2,
|
||||
common_local_url('api',
|
||||
array('apiaction' => 'statuses',
|
||||
'method' => 'user_timeline',
|
||||
'argument' => $this->user->nickname.'.rss')),
|
||||
sprintf(_('Notice feed for %s (RSS 2.0)'),
|
||||
$this->user->nickname)),
|
||||
new Feed(Feed::ATOM,
|
||||
common_local_url('api',
|
||||
array('apiaction' => 'statuses',
|
||||
'method' => 'user_timeline',
|
||||
'argument' => $this->user->nickname.'.atom')),
|
||||
sprintf(_('Notice feed for %s (Atom)'),
|
||||
$this->user->nickname)),
|
||||
new Feed(Feed::FOAF,
|
||||
common_local_url('foaf', array('nickname' =>
|
||||
$this->user->nickname)),
|
||||
sprintf(_('FOAF for %s'), $this->user->nickname)));
|
||||
}
|
||||
|
||||
function extraHead()
|
||||
{
|
||||
// FOAF
|
||||
$this->element('link', array('rel' => 'meta',
|
||||
'href' => common_local_url('foaf', array('nickname' =>
|
||||
$this->user->nickname)),
|
||||
'type' => 'application/rdf+xml',
|
||||
'title' => 'FOAF'));
|
||||
// for remote subscriptions etc.
|
||||
$this->element('meta', array('http-equiv' => 'X-XRDS-Location',
|
||||
'content' => common_local_url('xrds', array('nickname' =>
|
||||
$this->user->nickname))));
|
||||
$this->user->nickname))));
|
||||
|
||||
if ($this->profile->bio) {
|
||||
$this->element('meta', array('name' => 'description',
|
||||
@ -248,6 +229,15 @@ class ShowstreamAction extends Action
|
||||
'height' => AVATAR_PROFILE_SIZE,
|
||||
'alt' => $this->profile->nickname));
|
||||
$this->elementEnd('dd');
|
||||
|
||||
$user = User::staticGet('id', $this->profile->id);
|
||||
$cur = common_current_user();
|
||||
if ($cur && $cur->id == $user->id) {
|
||||
$this->elementStart('dd');
|
||||
$this->element('a', array('href' => common_local_url('avatarsettings')), _('Edit Avatar'));
|
||||
$this->elementEnd('dd');
|
||||
}
|
||||
|
||||
$this->elementEnd('dl');
|
||||
|
||||
$this->elementStart('dl', 'entity_nickname');
|
||||
@ -256,7 +246,7 @@ class ShowstreamAction extends Action
|
||||
$hasFN = ($this->profile->fullname) ? 'nickname url uid' : 'fn nickname url uid';
|
||||
$this->element('a', array('href' => $this->profile->profileurl,
|
||||
'rel' => 'me', 'class' => $hasFN),
|
||||
$this->profile->nickname);
|
||||
$this->profile->nickname);
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
|
||||
@ -272,7 +262,7 @@ class ShowstreamAction extends Action
|
||||
if ($this->profile->location) {
|
||||
$this->elementStart('dl', 'entity_location');
|
||||
$this->element('dt', null, _('Location'));
|
||||
$this->element('dd', 'location', $this->profile->location);
|
||||
$this->element('dd', 'label', $this->profile->location);
|
||||
$this->elementEnd('dl');
|
||||
}
|
||||
|
||||
@ -302,11 +292,11 @@ class ShowstreamAction extends Action
|
||||
$this->elementStart('ul', 'tags xoxo');
|
||||
foreach ($tags as $tag) {
|
||||
$this->elementStart('li');
|
||||
$this->element('span', 'mark_hash', '#');
|
||||
$this->element('a', array('rel' => 'tag',
|
||||
'href' => common_local_url('peopletag',
|
||||
array('tag' => $tag))),
|
||||
$tag);
|
||||
// Avoid space by using raw output.
|
||||
$pt = '<span class="mark_hash">#</span><a rel="tag" href="' .
|
||||
common_local_url('peopletag', array('tag' => $tag)) .
|
||||
'">' . $tag . '</a>';
|
||||
$this->raw($pt);
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
$this->elementEnd('ul');
|
||||
@ -324,7 +314,7 @@ class ShowstreamAction extends Action
|
||||
$this->elementStart('li', 'entity_edit');
|
||||
$this->element('a', array('href' => common_local_url('profilesettings'),
|
||||
'title' => _('Edit profile settings')),
|
||||
_('Edit'));
|
||||
_('Edit'));
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
|
||||
@ -346,9 +336,8 @@ class ShowstreamAction extends Action
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
|
||||
$user = User::staticGet('id', $this->profile->id);
|
||||
if ($cur && $cur->id != $user->id && $cur->mutuallySubscribed($user)) {
|
||||
$this->elementStart('li', 'entity_send-a-message');
|
||||
$this->elementStart('li', 'entity_send-a-message');
|
||||
$this->element('a', array('href' => common_local_url('newmessage', array('to' => $user->id)),
|
||||
'title' => _('Send a direct message to this user')),
|
||||
_('Message'));
|
||||
@ -490,7 +479,7 @@ class ShowstreamAction extends Action
|
||||
$this->elementStart('dl', 'entity_member-since');
|
||||
$this->element('dt', null, _('Member since'));
|
||||
$this->element('dd', null, date('j M Y',
|
||||
strtotime($this->profile->created)));
|
||||
strtotime($this->profile->created)));
|
||||
$this->elementEnd('dl');
|
||||
|
||||
$this->elementStart('dl', 'entity_subscriptions');
|
||||
|
@ -37,9 +37,9 @@ class TagAction extends Action
|
||||
}
|
||||
|
||||
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
||||
|
||||
|
||||
common_set_returnto($this->selfUrl());
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -61,12 +61,11 @@ class TagAction extends Action
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function showFeeds()
|
||||
function getFeeds()
|
||||
{
|
||||
$this->element('link', array('rel' => 'alternate',
|
||||
'href' => common_local_url('tagrss', array('tag' => $this->tag)),
|
||||
'type' => 'application/rss+xml',
|
||||
'title' => sprintf(_('Feed for tag %s'), $this->tag)));
|
||||
return array(new Feed(Feed::RSS1,
|
||||
common_local_url('tagrss', array('tag' => $this->tag)),
|
||||
sprintf(_('Feed for tag %s'), $this->tag)));
|
||||
}
|
||||
|
||||
function showPageNotice()
|
||||
@ -74,15 +73,6 @@ class TagAction extends Action
|
||||
return sprintf(_('Messages tagged "%s", most recent first'), $this->tag);
|
||||
}
|
||||
|
||||
function showExportData()
|
||||
{
|
||||
$fl = new FeedList($this);
|
||||
$fl->show(array(0=>array('href'=>common_local_url('tagrss', array('tag' => $this->tag)),
|
||||
'type' => 'rss',
|
||||
'version' => 'RSS 1.0',
|
||||
'item' => 'tagrss')));
|
||||
}
|
||||
|
||||
function showContent()
|
||||
{
|
||||
$notice = Notice_tag::getStream($this->tag, (($this->page-1)*NOTICES_PER_PAGE), NOTICES_PER_PAGE + 1);
|
||||
|
@ -110,7 +110,7 @@ class TagotherAction extends Action
|
||||
if ($this->profile->location) {
|
||||
$this->elementStart('dl', 'entity_location');
|
||||
$this->element('dt', null, _('Location'));
|
||||
$this->element('dd', 'location', $this->profile->location);
|
||||
$this->element('dd', 'label', $this->profile->location);
|
||||
$this->elementEnd('dl');
|
||||
}
|
||||
if ($this->profile->homepage) {
|
||||
@ -135,7 +135,8 @@ class TagotherAction extends Action
|
||||
'id' => 'form_tag_user',
|
||||
'class' => 'form_settings',
|
||||
'name' => 'tagother',
|
||||
'action' => $this->selfUrl()));
|
||||
'action' => common_local_url('tagother', array('id' => $this->profile->id))));
|
||||
|
||||
$this->elementStart('fieldset');
|
||||
$this->element('legend', null, _('Tag user'));
|
||||
$this->hidden('token', common_session_token());
|
||||
|
@ -23,23 +23,24 @@ require_once(INSTALLDIR.'/lib/twitterapi.php');
|
||||
|
||||
class TwitapiaccountAction extends TwitterapiAction
|
||||
{
|
||||
|
||||
function verify_credentials($args, $apidata)
|
||||
function verify_credentials($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
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);
|
||||
}
|
||||
switch ($apidata['content-type']) {
|
||||
case 'xml':
|
||||
case 'json':
|
||||
$action_obj = new TwitapiusersAction();
|
||||
$action_obj->prepare($args);
|
||||
call_user_func(array($action_obj, 'show'), $args, $apidata);
|
||||
break;
|
||||
default:
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
print 'Authorized';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function end_session($args, $apidata)
|
||||
function end_session($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
$this->serverError(_('API method under construction.'), $code=501);
|
||||
|
149
actions/twitapisearchjson.php
Normal file
149
actions/twitapisearchjson.php
Normal file
@ -0,0 +1,149 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* List of replies
|
||||
*
|
||||
* 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 Search
|
||||
* @package Laconica
|
||||
* @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/twitterapi.php';
|
||||
require_once INSTALLDIR.'/lib/jsonsearchresultslist.php';
|
||||
|
||||
/**
|
||||
* Action handler for Twitter-compatible API search
|
||||
*
|
||||
* @category Search
|
||||
* @package Laconica
|
||||
* @author Zach Copley <zach@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/
|
||||
* @see TwitterapiAction
|
||||
*/
|
||||
|
||||
class TwitapisearchjsonAction extends TwitterapiAction
|
||||
{
|
||||
var $query;
|
||||
var $lang;
|
||||
var $rpp;
|
||||
var $page;
|
||||
var $since_id;
|
||||
var $limit;
|
||||
var $geocode;
|
||||
|
||||
/**
|
||||
* Initialization.
|
||||
*
|
||||
* @param array $args Web and URL arguments
|
||||
*
|
||||
* @return boolean true if nothing goes wrong
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->query = $this->trimmed('q');
|
||||
$this->lang = $this->trimmed('lang');
|
||||
$this->rpp = $this->trimmed('rpp');
|
||||
|
||||
if (!$this->rpp) {
|
||||
$this->rpp = 15;
|
||||
}
|
||||
|
||||
if ($this->rpp > 100) {
|
||||
$this->rpp = 100;
|
||||
}
|
||||
|
||||
$this->page = $this->trimmed('page');
|
||||
|
||||
if (!$this->page) {
|
||||
$this->page = 1;
|
||||
}
|
||||
|
||||
$this->since_id = $this->trimmed('since_id');
|
||||
$this->geocode = $this->trimmed('geocode');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request
|
||||
*
|
||||
* @param array $args Arguments from $_REQUEST
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
$this->showResults();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show search results
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showResults()
|
||||
{
|
||||
|
||||
// TODO: Support search operators like from: and to:
|
||||
|
||||
$notice = new Notice();
|
||||
|
||||
// lcase it for comparison
|
||||
$q = strtolower($this->query);
|
||||
|
||||
$search_engine = $notice->getSearchEngine('identica_notices');
|
||||
$search_engine->set_sort_mode('chron');
|
||||
$search_engine->limit(($this->page - 1) * $this->rpp, $this->rpp + 1, true);
|
||||
$search_engine->query($q);
|
||||
$cnt = $notice->find();
|
||||
|
||||
// TODO: since_id, lang, geocode
|
||||
|
||||
$results = new JSONSearchResultsList($notice, $q, $this->rpp, $this->page);
|
||||
|
||||
$this->init_document('json');
|
||||
$results->show();
|
||||
$this->end_document('json');
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a read-only action
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
|
||||
function isReadOnly()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
@ -204,7 +204,7 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
# FriendFeed's SUP protocol
|
||||
# Also added RSS and Atom feeds
|
||||
|
||||
$suplink = common_local_url('sup', null, $user->id);
|
||||
$suplink = common_local_url('sup', null, null, $user->id);
|
||||
header('X-SUP-ID: '.$suplink);
|
||||
|
||||
# XXX: since
|
||||
@ -470,19 +470,28 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
return $this->subscriptions($apidata, 'subscribed', 'subscriber');
|
||||
}
|
||||
|
||||
function friendsIDs($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
return $this->subscriptions($apidata, 'subscribed', 'subscriber', true);
|
||||
}
|
||||
|
||||
function followers($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
return $this->subscriptions($apidata, 'subscriber', 'subscribed');
|
||||
}
|
||||
|
||||
function subscriptions($apidata, $other_attr, $user_attr)
|
||||
function followersIDs($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
return $this->subscriptions($apidata, 'subscriber', 'subscribed', true);
|
||||
}
|
||||
|
||||
function subscriptions($apidata, $other_attr, $user_attr, $onlyIDs=false)
|
||||
{
|
||||
|
||||
# XXX: lite
|
||||
|
||||
$this->auth_user = $apidate['user'];
|
||||
$this->auth_user = $apidata['user'];
|
||||
$user = $this->get_user($apidata['api_arg'], $apidata);
|
||||
|
||||
if (!$user) {
|
||||
@ -514,7 +523,10 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
}
|
||||
|
||||
$sub->orderBy('created DESC');
|
||||
$sub->limit(($page-1)*100, 100);
|
||||
|
||||
if (!$onlyIDs) {
|
||||
$sub->limit(($page-1)*100, 100);
|
||||
}
|
||||
|
||||
$others = array();
|
||||
|
||||
@ -529,7 +541,13 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$type = $apidata['content-type'];
|
||||
|
||||
$this->init_document($type);
|
||||
$this->show_profiles($others, $type);
|
||||
|
||||
if ($onlyIDs) {
|
||||
$this->showIDs($others, $type);
|
||||
} else {
|
||||
$this->show_profiles($others, $type);
|
||||
}
|
||||
|
||||
$this->end_document($type);
|
||||
}
|
||||
|
||||
@ -555,6 +573,28 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
}
|
||||
}
|
||||
|
||||
function showIDs($profiles, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'xml':
|
||||
$this->elementStart('ids');
|
||||
foreach ($profiles as $profile) {
|
||||
$this->element('id', null, $profile->id);
|
||||
}
|
||||
$this->elementEnd('ids');
|
||||
break;
|
||||
case 'json':
|
||||
$ids = array();
|
||||
foreach ($profiles as $profile) {
|
||||
$ids[] = (int)$profile->id;
|
||||
}
|
||||
print json_encode($ids);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(_('unsupported file type'));
|
||||
}
|
||||
}
|
||||
|
||||
function featured($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
90
actions/twitapitrends.php
Normal file
90
actions/twitapitrends.php
Normal file
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* List of replies
|
||||
*
|
||||
* 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 Search
|
||||
* @package Laconica
|
||||
* @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/twitterapi.php';
|
||||
|
||||
/**
|
||||
* Returns the top ten queries that are currently trending
|
||||
*
|
||||
* @category Search
|
||||
* @package Laconica
|
||||
* @author Zach Copley <zach@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/
|
||||
*
|
||||
* @see TwitterapiAction
|
||||
*/
|
||||
|
||||
class TwitapitrendsAction extends TwitterapiAction
|
||||
{
|
||||
|
||||
var $callback;
|
||||
|
||||
/**
|
||||
* Initialization.
|
||||
*
|
||||
* @param array $args Web and URL arguments
|
||||
*
|
||||
* @return boolean false if user doesn't exist
|
||||
*/
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request
|
||||
*
|
||||
* @param array $args Arguments from $_REQUEST
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
$this->showTrends();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the trends
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showTrends()
|
||||
{
|
||||
$this->serverError(_('API method under construction.'), $code = 501);
|
||||
}
|
||||
|
||||
}
|
@ -25,25 +25,29 @@ class TwitapiusersAction extends TwitterapiAction
|
||||
{
|
||||
|
||||
function show($args, $apidata)
|
||||
{
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
|
||||
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
|
||||
$this->clientError(_('API method not found!'), $code = 404);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->auth_user = $apidata['user'];
|
||||
|
||||
$user = null;
|
||||
$email = $this->arg('email');
|
||||
$user_id = $this->arg('user_id');
|
||||
|
||||
if ($email) {
|
||||
$user = User::staticGet('email', $email);
|
||||
} elseif ($user_id) {
|
||||
$user = $this->get_user($user_id);
|
||||
} elseif (isset($apidata['api_arg'])) {
|
||||
$user = $this->get_user($apidata['api_arg']);
|
||||
}
|
||||
|
||||
if (!$user) {
|
||||
} elseif (isset($apidata['user'])) {
|
||||
$user = $apidata['user'];
|
||||
}
|
||||
|
||||
if (!$user) {
|
||||
// XXX: Twitter returns a random(?) user instead of throwing and err! -- Zach
|
||||
$this->client_error(_('Not found.'), 404, $apidata['content-type']);
|
||||
return;
|
||||
@ -74,9 +78,12 @@ class TwitapiusersAction extends TwitterapiAction
|
||||
|
||||
// Other fields Twitter sends...
|
||||
$twitter_user['profile_background_color'] = '';
|
||||
$twitter_user['profile_background_image_url'] = '';
|
||||
$twitter_user['profile_text_color'] = '';
|
||||
$twitter_user['profile_link_color'] = '';
|
||||
$twitter_user['profile_sidebar_fill_color'] = '';
|
||||
$twitter_user['profile_sidebar_border_color'] = '';
|
||||
$twitter_user['profile_background_tile'] = 'false';
|
||||
|
||||
$faves = DB_DataObject::factory('fave');
|
||||
$faves->user_id = $user->id;
|
||||
@ -94,18 +101,27 @@ class TwitapiusersAction extends TwitterapiAction
|
||||
$twitter_user['utc_offset'] = $t->format('Z');
|
||||
$twitter_user['time_zone'] = $timezone;
|
||||
|
||||
if (isset($this->auth_user)) {
|
||||
if (isset($apidata['user'])) {
|
||||
|
||||
if ($this->auth_user->isSubscribed($profile)) {
|
||||
if ($apidata['user']->isSubscribed($profile)) {
|
||||
$twitter_user['following'] = 'true';
|
||||
} else {
|
||||
$twitter_user['following'] = 'false';
|
||||
}
|
||||
|
||||
// Not implemented yet
|
||||
$twitter_user['notifications'] = 'false';
|
||||
}
|
||||
|
||||
|
||||
// Notifications on?
|
||||
$sub = Subscription::pkeyGet(array('subscriber' =>
|
||||
$apidata['user']->id, 'subscribed' => $profile->id));
|
||||
|
||||
if ($sub) {
|
||||
if ($sub->jabber || $sub->sms) {
|
||||
$twitter_user['notifications'] = 'true';
|
||||
} else {
|
||||
$twitter_user['notifications'] = 'false';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($apidata['content-type'] == 'xml') {
|
||||
$this->init_document('xml');
|
||||
$this->show_twitter_xml_user($twitter_user);
|
||||
@ -114,7 +130,13 @@ class TwitapiusersAction extends TwitterapiAction
|
||||
$this->init_document('json');
|
||||
$this->show_json_objects($twitter_user);
|
||||
$this->end_document('json');
|
||||
}
|
||||
} else {
|
||||
|
||||
// This is in case 'show' was called via /account/verify_credentials
|
||||
// without a format (xml or json).
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
print 'Authorized';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ if (!defined('LACONICA')) {
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/connectsettingsaction.php';
|
||||
require_once INSTALLDIR.'/lib/twitter.php';
|
||||
|
||||
define('SUBSCRIPTIONS', 80);
|
||||
|
||||
@ -90,7 +91,7 @@ class TwittersettingsAction extends ConnectSettingsAction
|
||||
|
||||
$fuser = null;
|
||||
|
||||
$flink = Foreign_link::getByUserID($user->id, 1); // 1 == Twitter
|
||||
$flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE);
|
||||
|
||||
if ($flink) {
|
||||
$fuser = $flink->getForeignUser();
|
||||
@ -358,7 +359,7 @@ class TwittersettingsAction extends ConnectSettingsAction
|
||||
|
||||
$flink->user_id = $user->id;
|
||||
$flink->foreign_id = $twit_user->id;
|
||||
$flink->service = 1; // Twitter
|
||||
$flink->service = TWITTER_SERVICE;
|
||||
$flink->credentials = $password;
|
||||
$flink->created = common_sql_now();
|
||||
|
||||
|
@ -162,7 +162,13 @@ class UpdateprofileAction extends Action
|
||||
if ($avatar) {
|
||||
$temp_filename = tempnam(sys_get_temp_dir(), 'listenee_avatar');
|
||||
copy($avatar, $temp_filename);
|
||||
if (!$profile->setOriginal($temp_filename)) {
|
||||
$imagefile = new ImageFile($profile->id, $temp_filename);
|
||||
$filename = Avatar::filename($profile->id,
|
||||
image_type_to_extension($imagefile->type),
|
||||
null,
|
||||
common_timestamp());
|
||||
rename($temp_filename, Avatar::path($filename));
|
||||
if (!$profile->setOriginal($filename)) {
|
||||
$this->serverError(_('Could not save avatar info'), 500);
|
||||
return false;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ class UserauthorizationAction extends Action
|
||||
$this->elementStart('div', 'profile');
|
||||
if ($avatar) {
|
||||
$this->element('img', array('src' => $avatar,
|
||||
'class' => 'avatar profile',
|
||||
'class' => 'avatar',
|
||||
'width' => AVATAR_PROFILE_SIZE,
|
||||
'height' => AVATAR_PROFILE_SIZE,
|
||||
'alt' => $nickname));
|
||||
@ -330,7 +330,13 @@ class UserauthorizationAction extends Action
|
||||
{
|
||||
$temp_filename = tempnam(sys_get_temp_dir(), 'listenee_avatar');
|
||||
copy($url, $temp_filename);
|
||||
return $profile->setOriginal($temp_filename);
|
||||
$imagefile = new ImageFile($profile->id, $temp_filename);
|
||||
$filename = Avatar::filename($profile->id,
|
||||
image_type_to_extension($imagefile->type),
|
||||
null,
|
||||
common_timestamp());
|
||||
rename($temp_filename, Avatar::path($filename));
|
||||
return $profile->setOriginal($filename);
|
||||
}
|
||||
|
||||
function showAcceptMessage($tok)
|
||||
|
@ -46,13 +46,13 @@ class UserrssAction extends Rss10Action
|
||||
{
|
||||
|
||||
$user = $this->user;
|
||||
|
||||
|
||||
if (is_null($user)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
$notice = $user->getNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit);
|
||||
|
||||
|
||||
while ($notice->fetch()) {
|
||||
$notices[] = clone($notice);
|
||||
}
|
||||
@ -87,10 +87,10 @@ class UserrssAction extends Rss10Action
|
||||
}
|
||||
|
||||
# override parent to add X-SUP-ID URL
|
||||
|
||||
|
||||
function initRss($limit=0)
|
||||
{
|
||||
$url = common_local_url('sup', null, $this->user->id);
|
||||
$url = common_local_url('sup', null, null, $this->user->id);
|
||||
header('X-SUP-ID: '.$url);
|
||||
parent::initRss($limit);
|
||||
}
|
||||
@ -100,4 +100,3 @@ class UserrssAction extends Rss10Action
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
BIN
bin/flowplayer-3.0.5.swf
Normal file
BIN
bin/flowplayer-3.0.5.swf
Normal file
Binary file not shown.
BIN
bin/flowplayer.audio-3.0.3.swf
Normal file
BIN
bin/flowplayer.audio-3.0.3.swf
Normal file
Binary file not shown.
BIN
bin/flowplayer.controls-3.0.3.swf
Normal file
BIN
bin/flowplayer.controls-3.0.3.swf
Normal file
Binary file not shown.
@ -34,22 +34,24 @@ class Notice extends Memcached_DataObject
|
||||
###START_AUTOCODE
|
||||
/* the code below is auto generated do not remove the above tag */
|
||||
|
||||
public $__table = 'notice'; // table name
|
||||
public $id; // int(4) primary_key not_null
|
||||
public $profile_id; // int(4) not_null
|
||||
public $__table = 'notice'; // table name
|
||||
public $id; // int(4) primary_key not_null
|
||||
public $profile_id; // int(4) not_null
|
||||
public $uri; // varchar(255) unique_key
|
||||
public $content; // varchar(140)
|
||||
public $rendered; // text()
|
||||
public $rendered; // text()
|
||||
public $url; // varchar(255)
|
||||
public $created; // datetime() not_null
|
||||
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
|
||||
public $reply_to; // int(4)
|
||||
public $is_local; // tinyint(1)
|
||||
public $source; // varchar(32)
|
||||
public $created; // datetime() not_null
|
||||
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
|
||||
public $reply_to; // int(4)
|
||||
public $is_local; // tinyint(1)
|
||||
public $source; // varchar(32)
|
||||
public $conversation; // int(4)
|
||||
|
||||
/* Static get */
|
||||
function staticGet($k,$v=null)
|
||||
{ return Memcached_DataObject::staticGet('Notice',$k,$v); }
|
||||
function staticGet($k,$v=NULL) {
|
||||
return Memcached_DataObject::staticGet('Notice',$k,$v);
|
||||
}
|
||||
|
||||
/* the code above is auto generated do not remove the tag below */
|
||||
###END_AUTOCODE
|
||||
@ -94,23 +96,28 @@ class Notice extends Memcached_DataObject
|
||||
/* Add them to the database */
|
||||
foreach(array_unique($match[1]) as $hashtag) {
|
||||
/* elide characters we don't want in the tag */
|
||||
$hashtag = common_canonical_tag($hashtag);
|
||||
|
||||
$tag = DB_DataObject::factory('Notice_tag');
|
||||
$tag->notice_id = $this->id;
|
||||
$tag->tag = $hashtag;
|
||||
$tag->created = $this->created;
|
||||
$id = $tag->insert();
|
||||
if (!$id) {
|
||||
$last_error = PEAR::getStaticProperty('DB_DataObject','lastError');
|
||||
common_log(LOG_ERR, 'DB error inserting hashtag: ' . $last_error->message);
|
||||
common_server_error(sprintf(_('DB error inserting hashtag: %s'), $last_error->message));
|
||||
return;
|
||||
}
|
||||
$this->saveTag($hashtag);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function saveTag($hashtag)
|
||||
{
|
||||
$hashtag = common_canonical_tag($hashtag);
|
||||
|
||||
$tag = new Notice_tag();
|
||||
$tag->notice_id = $this->id;
|
||||
$tag->tag = $hashtag;
|
||||
$tag->created = $this->created;
|
||||
$id = $tag->insert();
|
||||
|
||||
if (!$id) {
|
||||
throw new ServerException(sprintf(_('DB error inserting hashtag: %s'),
|
||||
$last_error->message));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static function saveNew($profile_id, $content, $source=null, $is_local=1, $reply_to=null, $uri=null) {
|
||||
|
||||
$profile = Profile::staticGet($profile_id);
|
||||
@ -136,10 +143,12 @@ class Notice extends Memcached_DataObject
|
||||
$notice->profile_id = $profile_id;
|
||||
|
||||
$blacklist = common_config('public', 'blacklist');
|
||||
$autosource = common_config('public', 'autosource');
|
||||
|
||||
# Blacklisted are non-false, but not 1, either
|
||||
|
||||
if ($blacklist && in_array($profile_id, $blacklist)) {
|
||||
if (($blacklist && in_array($profile_id, $blacklist)) ||
|
||||
($source && $autosource && in_array($source, $autosource))) {
|
||||
$notice->is_local = -1;
|
||||
} else {
|
||||
$notice->is_local = $is_local;
|
||||
@ -147,39 +156,51 @@ class Notice extends Memcached_DataObject
|
||||
|
||||
$notice->query('BEGIN');
|
||||
|
||||
$notice->reply_to = $reply_to;
|
||||
$notice->created = common_sql_now();
|
||||
$notice->content = common_shorten_links($content);
|
||||
$notice->rendered = common_render_content($notice->content, $notice);
|
||||
$notice->source = $source;
|
||||
$notice->uri = $uri;
|
||||
|
||||
$id = $notice->insert();
|
||||
|
||||
if (!$id) {
|
||||
common_log_db_error($notice, 'INSERT', __FILE__);
|
||||
return _('Problem saving notice.');
|
||||
}
|
||||
|
||||
# Update the URI after the notice is in the database
|
||||
if (!$uri) {
|
||||
$orig = clone($notice);
|
||||
$notice->uri = common_notice_uri($notice);
|
||||
|
||||
if (!$notice->update($orig)) {
|
||||
common_log_db_error($notice, 'UPDATE', __FILE__);
|
||||
return _('Problem saving notice.');
|
||||
if (!empty($reply_to)) {
|
||||
$reply_notice = Notice::staticGet('id', $reply_to);
|
||||
if (!empty($reply_notice)) {
|
||||
$notice->reply_to = $reply_to;
|
||||
$notice->conversation = $reply_notice->conversation;
|
||||
}
|
||||
}
|
||||
|
||||
# XXX: do we need to change this for remote users?
|
||||
if (Event::handle('StartNoticeSave', array(&$notice))) {
|
||||
|
||||
$notice->saveReplies();
|
||||
$notice->saveTags();
|
||||
$notice->saveGroups();
|
||||
$id = $notice->insert();
|
||||
|
||||
$notice->addToInboxes();
|
||||
$notice->query('COMMIT');
|
||||
if (!$id) {
|
||||
common_log_db_error($notice, 'INSERT', __FILE__);
|
||||
return _('Problem saving notice.');
|
||||
}
|
||||
|
||||
# Update the URI after the notice is in the database
|
||||
if (!$uri) {
|
||||
$orig = clone($notice);
|
||||
$notice->uri = common_notice_uri($notice);
|
||||
|
||||
if (!$notice->update($orig)) {
|
||||
common_log_db_error($notice, 'UPDATE', __FILE__);
|
||||
return _('Problem saving notice.');
|
||||
}
|
||||
}
|
||||
|
||||
# XXX: do we need to change this for remote users?
|
||||
|
||||
$notice->saveReplies();
|
||||
$notice->saveTags();
|
||||
$notice->saveGroups();
|
||||
|
||||
$notice->addToInboxes();
|
||||
$notice->query('COMMIT');
|
||||
|
||||
Event::handle('EndNoticeSave', array($notice));
|
||||
}
|
||||
|
||||
# Clear the cache for subscribed users, so they'll update at next request
|
||||
# XXX: someone clever could prepend instead of clearing the cache
|
||||
@ -572,7 +593,7 @@ class Notice extends Memcached_DataObject
|
||||
$inbox = new Notice_inbox();
|
||||
$UT = common_config('db','type')=='pgsql'?'"user"':'user';
|
||||
$qry = 'INSERT INTO notice_inbox (user_id, notice_id, created) ' .
|
||||
"SELECT $UT.id, " . $this->id . ', "' . $this->created . '" ' .
|
||||
"SELECT $UT.id, " . $this->id . ", '" . $this->created . "' " .
|
||||
"FROM $UT JOIN subscription ON $UT.id = subscription.subscriber " .
|
||||
'WHERE subscription.subscribed = ' . $this->profile_id . ' ' .
|
||||
'AND NOT EXISTS (SELECT user_id, notice_id ' .
|
||||
@ -614,6 +635,15 @@ class Notice extends Memcached_DataObject
|
||||
continue;
|
||||
}
|
||||
|
||||
// we automatically add a tag for every group name, too
|
||||
|
||||
$tag = Notice_tag::pkeyGet(array('tag' => common_canonical_tag($nickname),
|
||||
'notice_id' => $this->id));
|
||||
|
||||
if (is_null($tag)) {
|
||||
$this->saveTag($nickname);
|
||||
}
|
||||
|
||||
if ($profile->isMember($group)) {
|
||||
|
||||
$gi = new Group_inbox();
|
||||
@ -633,7 +663,7 @@ class Notice extends Memcached_DataObject
|
||||
$inbox = new Notice_inbox();
|
||||
$UT = common_config('db','type')=='pgsql'?'"user"':'user';
|
||||
$qry = 'INSERT INTO notice_inbox (user_id, notice_id, created, source) ' .
|
||||
"SELECT $UT.id, " . $this->id . ', "' . $this->created . '", 2 ' .
|
||||
"SELECT $UT.id, " . $this->id . ", '" . $this->created . "', 2 " .
|
||||
"FROM $UT JOIN group_member ON $UT.id = group_member.profile_id " .
|
||||
'WHERE group_member.group_id = ' . $group->id . ' ' .
|
||||
'AND NOT EXISTS (SELECT user_id, notice_id ' .
|
||||
@ -684,6 +714,7 @@ class Notice extends Memcached_DataObject
|
||||
if ($recipient_notice) {
|
||||
$orig = clone($this);
|
||||
$this->reply_to = $recipient_notice->id;
|
||||
$this->conversation = $recipient_notice->conversation;
|
||||
$this->update($orig);
|
||||
}
|
||||
}
|
||||
@ -725,10 +756,27 @@ class Notice extends Memcached_DataObject
|
||||
if (!$id) {
|
||||
common_log_db_error($reply, 'INSERT', __FILE__);
|
||||
return;
|
||||
} else {
|
||||
$replied[$recipient->id] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If it's not a reply, make it the root of a new conversation
|
||||
|
||||
if (empty($this->conversation)) {
|
||||
$orig = clone($this);
|
||||
$this->conversation = $this->id;
|
||||
$this->update($orig);
|
||||
}
|
||||
|
||||
foreach (array_keys($replied) as $recipient) {
|
||||
$user = User::staticGet('id', $recipient);
|
||||
if ($user) {
|
||||
mail_notify_attn($user, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
|
||||
|
||||
class Notice_tag extends Memcached_DataObject
|
||||
class Notice_tag extends Memcached_DataObject
|
||||
{
|
||||
###START_AUTOCODE
|
||||
/* the code below is auto generated do not remove the above tag */
|
||||
@ -35,18 +35,18 @@ class Notice_tag extends Memcached_DataObject
|
||||
|
||||
/* the code above is auto generated do not remove the tag below */
|
||||
###END_AUTOCODE
|
||||
|
||||
|
||||
static function getStream($tag, $offset=0, $limit=20) {
|
||||
$qry =
|
||||
$qry =
|
||||
'SELECT notice.* ' .
|
||||
'FROM notice JOIN notice_tag ON notice.id = notice_tag.notice_id ' .
|
||||
'WHERE notice_tag.tag = "%s" ';
|
||||
"WHERE notice_tag.tag = '%s' ";
|
||||
|
||||
return Notice::getStream(sprintf($qry, $tag),
|
||||
'notice_tag:notice_stream:' . common_keyize($tag),
|
||||
$offset, $limit);
|
||||
}
|
||||
|
||||
|
||||
function blowCache()
|
||||
{
|
||||
$cache = common_memcache();
|
||||
@ -54,4 +54,9 @@ class Notice_tag extends Memcached_DataObject
|
||||
$cache->delete(common_cache_key('notice_tag:notice_stream:' . $this->tag));
|
||||
}
|
||||
}
|
||||
|
||||
function &pkeyGet($kv)
|
||||
{
|
||||
return Memcached_DataObject::pkeyGet('Notice_tag', $kv);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
|
||||
|
||||
class Profile_tag extends Memcached_DataObject
|
||||
class Profile_tag extends Memcached_DataObject
|
||||
{
|
||||
###START_AUTOCODE
|
||||
/* the code below is auto generated do not remove the above tag */
|
||||
@ -23,45 +23,46 @@ class Profile_tag extends Memcached_DataObject
|
||||
###END_AUTOCODE
|
||||
|
||||
static function getTags($tagger, $tagged) {
|
||||
|
||||
|
||||
$tags = array();
|
||||
|
||||
# XXX: store this in memcached
|
||||
|
||||
|
||||
$profile_tag = new Profile_tag();
|
||||
$profile_tag->tagger = $tagger;
|
||||
$profile_tag->tagged = $tagged;
|
||||
|
||||
|
||||
$profile_tag->find();
|
||||
|
||||
|
||||
while ($profile_tag->fetch()) {
|
||||
$tags[] = $profile_tag->tag;
|
||||
}
|
||||
|
||||
|
||||
$profile_tag->free();
|
||||
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
|
||||
static function setTags($tagger, $tagged, $newtags) {
|
||||
|
||||
|
||||
$newtags = array_unique($newtags);
|
||||
$oldtags = Profile_tag::getTags($tagger, $tagged);
|
||||
|
||||
|
||||
# Delete stuff that's old that not in new
|
||||
|
||||
|
||||
$to_delete = array_diff($oldtags, $newtags);
|
||||
|
||||
|
||||
# Insert stuff that's in new and not in old
|
||||
|
||||
|
||||
$to_insert = array_diff($newtags, $oldtags);
|
||||
|
||||
|
||||
$profile_tag = new Profile_tag();
|
||||
|
||||
|
||||
$profile_tag->tagger = $tagger;
|
||||
$profile_tag->tagged = $tagged;
|
||||
|
||||
|
||||
$profile_tag->query('BEGIN');
|
||||
|
||||
|
||||
foreach ($to_delete as $deltag) {
|
||||
$profile_tag->tag = $deltag;
|
||||
$result = $profile_tag->delete();
|
||||
@ -70,7 +71,7 @@ class Profile_tag extends Memcached_DataObject
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach ($to_insert as $instag) {
|
||||
$profile_tag->tag = $instag;
|
||||
$result = $profile_tag->insert();
|
||||
@ -79,12 +80,12 @@ class Profile_tag extends Memcached_DataObject
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$profile_tag->query('COMMIT');
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
# Return profiles with a given tag
|
||||
static function getTagged($tagger, $tag) {
|
||||
$profile = new Profile();
|
||||
|
@ -40,6 +40,7 @@ class User extends Memcached_DataObject
|
||||
public $emailnotifyfav; // tinyint(1) default_1
|
||||
public $emailnotifynudge; // tinyint(1) default_1
|
||||
public $emailnotifymsg; // tinyint(1) default_1
|
||||
public $emailnotifyattn; // tinyint(1) default_1
|
||||
public $emailmicroid; // tinyint(1) default_1
|
||||
public $language; // varchar(50)
|
||||
public $timezone; // varchar(50)
|
||||
@ -62,8 +63,10 @@ class User extends Memcached_DataObject
|
||||
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
|
||||
|
||||
/* Static get */
|
||||
function staticGet($k,$v=null)
|
||||
{ return Memcached_DataObject::staticGet('User',$k,$v); }
|
||||
function staticGet($k,$v=NULL)
|
||||
{
|
||||
return Memcached_DataObject::staticGet('User',$k,$v);
|
||||
}
|
||||
|
||||
/* the code above is auto generated do not remove the tag below */
|
||||
###END_AUTOCODE
|
||||
@ -180,16 +183,16 @@ class User extends Memcached_DataObject
|
||||
$profile->nickname = $nickname;
|
||||
$profile->profileurl = common_profile_url($nickname);
|
||||
|
||||
if ($fullname) {
|
||||
if (!empty($fullname)) {
|
||||
$profile->fullname = $fullname;
|
||||
}
|
||||
if ($homepage) {
|
||||
if (!empty($homepage)) {
|
||||
$profile->homepage = $homepage;
|
||||
}
|
||||
if ($bio) {
|
||||
if (!empty($bio)) {
|
||||
$profile->bio = $bio;
|
||||
}
|
||||
if ($location) {
|
||||
if (!empty($location)) {
|
||||
$profile->location = $location;
|
||||
}
|
||||
|
||||
@ -197,7 +200,7 @@ class User extends Memcached_DataObject
|
||||
|
||||
$id = $profile->insert();
|
||||
|
||||
if (!$id) {
|
||||
if (empty($id)) {
|
||||
common_log_db_error($profile, 'INSERT', __FILE__);
|
||||
return false;
|
||||
}
|
||||
@ -207,13 +210,13 @@ class User extends Memcached_DataObject
|
||||
$user->id = $id;
|
||||
$user->nickname = $nickname;
|
||||
|
||||
if ($password) { # may not have a password for OpenID users
|
||||
if (!empty($password)) { # may not have a password for OpenID users
|
||||
$user->password = common_munge_password($password, $id);
|
||||
}
|
||||
|
||||
# Users who respond to invite email have proven their ownership of that address
|
||||
|
||||
if ($code) {
|
||||
if (!empty($code)) {
|
||||
$invite = Invitation::staticGet($code);
|
||||
if ($invite && $invite->address && $invite->address_type == 'email' && $invite->address == $email) {
|
||||
$user->email = $invite->address;
|
||||
@ -250,7 +253,7 @@ class User extends Memcached_DataObject
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($email && !$user->email) {
|
||||
if (!empty($email) && !$user->email) {
|
||||
|
||||
$confirm = new Confirm_address();
|
||||
$confirm->code = common_confirmation_code(128);
|
||||
@ -265,7 +268,7 @@ class User extends Memcached_DataObject
|
||||
}
|
||||
}
|
||||
|
||||
if ($code && $user->email) {
|
||||
if (!empty($code) && $user->email) {
|
||||
$user->emailChanged();
|
||||
}
|
||||
|
||||
@ -586,7 +589,7 @@ class User extends Memcached_DataObject
|
||||
'JOIN profile_tag ON (profile_tag.tagged = subscription.subscriber ' .
|
||||
'AND profile_tag.tagger = subscription.subscribed) ' .
|
||||
'WHERE subscription.subscribed = %d ' .
|
||||
'AND profile_tag.tag = "%s" ' .
|
||||
"AND profile_tag.tag = '%s' " .
|
||||
'AND subscription.subscribed != subscription.subscriber ' .
|
||||
'ORDER BY subscription.created DESC ';
|
||||
|
||||
@ -614,7 +617,7 @@ class User extends Memcached_DataObject
|
||||
'JOIN profile_tag on (profile_tag.tagged = subscription.subscribed ' .
|
||||
'AND profile_tag.tagger = subscription.subscriber) ' .
|
||||
'WHERE subscription.subscriber = %d ' .
|
||||
'AND profile_tag.tag = "%s" ' .
|
||||
"AND profile_tag.tag = '%s' " .
|
||||
'AND subscription.subscribed != subscription.subscriber ' .
|
||||
'ORDER BY subscription.created DESC ';
|
||||
|
||||
|
@ -168,6 +168,7 @@ modified = 384
|
||||
reply_to = 1
|
||||
is_local = 17
|
||||
source = 2
|
||||
conversation = 1
|
||||
|
||||
[notice__keys]
|
||||
id = N
|
||||
@ -292,7 +293,8 @@ created = 142
|
||||
modified = 384
|
||||
|
||||
[sms_carrier__keys]
|
||||
id = N
|
||||
id = K
|
||||
name = U
|
||||
|
||||
[subscription]
|
||||
subscriber = 129
|
||||
@ -331,6 +333,7 @@ emailnotifysub = 17
|
||||
emailnotifyfav = 17
|
||||
emailnotifynudge = 17
|
||||
emailnotifymsg = 17
|
||||
emailnotifyattn = 17
|
||||
emailmicroid = 17
|
||||
language = 2
|
||||
timezone = 2
|
||||
|
@ -18,6 +18,8 @@ $config['site']['server'] = 'localhost';
|
||||
$config['site']['path'] = 'laconica';
|
||||
#$config['site']['fancy'] = false;
|
||||
#$config['site']['theme'] = 'default';
|
||||
#To enable the built-in mobile style sheet, defaults to false.
|
||||
#$config['site']['mobile'] = true;
|
||||
#For contact email, defaults to $_SERVER["SERVER_ADMIN"]
|
||||
#$config['site']['email'] = 'admin@example.net';
|
||||
#Brought by...
|
||||
@ -32,6 +34,9 @@ $config['site']['path'] = 'laconica';
|
||||
# If you want logging sent to a file instead of syslog
|
||||
#$config['site']['logfile'] = '/tmp/laconica.log';
|
||||
|
||||
# Enables extra log information, for example full details of PEAR DB errors
|
||||
#$config['site']['logdebug'] = true;
|
||||
|
||||
# This is a PEAR DB DSN, see http://pear.php.net/manual/en/package.database.db.intro-dsn.php
|
||||
# Set it to match your actual database
|
||||
|
||||
@ -107,6 +112,14 @@ $config['sphinx']['port'] = 3312;
|
||||
#$config['public']['blacklist'][] = 123;
|
||||
#$config['public']['blacklist'][] = 2307;
|
||||
|
||||
#Mark certain notice sources as automatic and thus not
|
||||
#appropriate for public feed
|
||||
#$config['public]['autosource'][] = 'twitterfeed';
|
||||
#$config['public]['autosource'][] = 'rssdent';
|
||||
#$config['public]['autosource'][] = 'Ping.Fm';
|
||||
#$config['public]['autosource'][] = 'HelloTxt';
|
||||
#$config['public]['autosource'][] = 'Updating.Me';
|
||||
|
||||
#Do notice broadcasts offline
|
||||
#If you use this, you must run the six offline daemons in the
|
||||
#background. See the README for details.
|
||||
@ -147,7 +160,7 @@ $config['sphinx']['port'] = 3312;
|
||||
#$config['profile']['banned'][] = 'hacker';
|
||||
#$config['profile']['banned'][] = 12345;
|
||||
|
||||
# config section for the built-in Facebook application
|
||||
# Config section for the built-in Facebook application
|
||||
#$config['facebook']['apikey'] = 'APIKEY';
|
||||
#$config['facebook']['secret'] = 'SECRET';
|
||||
|
||||
|
@ -1,61 +0,0 @@
|
||||
insert into sms_carrier
|
||||
(name, email_pattern, created)
|
||||
values
|
||||
('3 River Wireless', '%s@sms.3rivers.net', now()),
|
||||
('7-11 Speakout', '%s@cingularme.com', now()),
|
||||
('Airtel (Karnataka, India)', '%s@airtelkk.com', now()),
|
||||
('Alaska Communications Systems', '%s@msg.acsalaska.com', now()),
|
||||
('Alltel Wireless', '%s@message.alltel.com', now()),
|
||||
('AT&T Wireless', '%s@txt.att.net', now()),
|
||||
('Bell Mobility (Canada)', '%s@txt.bell.ca', now()),
|
||||
('Boost Mobile', '%s@myboostmobile.com', now()),
|
||||
('Cellular One (Dobson)', '%s@mobile.celloneusa.com', now()),
|
||||
('Cincinnati Bell Wireless', '%s@gocbw.com', now()),
|
||||
('Cingular (Postpaid)', '%s@cingularme.com', now()),
|
||||
('Centennial Wireless', '%s@cwemail.com', now()),
|
||||
('Cingular (GoPhone prepaid)', '%s@cingularme.com', now()),
|
||||
('Claro (Nicaragua)', '%s@ideasclaro-ca.com', now()),
|
||||
('Comcel', '%s@comcel.com.co', now()),
|
||||
('Cricket', '%s@sms.mycricket.com', now()),
|
||||
('CTI', '%s@sms.ctimovil.com.ar', now()),
|
||||
('Emtel (Mauritius)', '%s@emtelworld.net', now()),
|
||||
('Fido (Canada)', '%s@fido.ca', now()),
|
||||
('General Communications Inc.', '%s@msg.gci.net', now()),
|
||||
('Globalstar', '%s@msg.globalstarusa.com', now()),
|
||||
('Helio', '%s@myhelio.com', now()),
|
||||
('Illinois Valley Cellular', '%s@ivctext.com', now()),
|
||||
('i wireless', '%s.iws@iwspcs.net', now()),
|
||||
('Meteor (Ireland)', '%s@sms.mymeteor.ie', now()),
|
||||
('Mero Mobile (Nepal)', '%s@sms.spicenepal.com', now()),
|
||||
('MetroPCS', '%s@mymetropcs.com', now()),
|
||||
('Movicom', '%s@movimensaje.com.ar', now()),
|
||||
('Mobitel (Sri Lanka)', '%s@sms.mobitel.lk', now()),
|
||||
('Movistar (Colombia)', '%s@movistar.com.co', now()),
|
||||
('MTN (South Africa)', '%s@sms.co.za', now()),
|
||||
('MTS (Canada)', '%s@text.mtsmobility.com', now()),
|
||||
('Nextel (Argentina)', '%s@nextel.net.ar', now()),
|
||||
('Orange (Poland)', '%s@orange.pl', now()),
|
||||
('Orange (UK)', '%s@orange.net', now()),
|
||||
('Personal (Argentina)', '%s@personal-net.com.ar', now()),
|
||||
('Plus GSM (Poland)', '%s@text.plusgsm.pl', now()),
|
||||
('President''s Choice (Canada)', '%s@txt.bell.ca', now()),
|
||||
('Qwest', '%s@qwestmp.com', now()),
|
||||
('Rogers (Canada)', '%s@pcs.rogers.com', now()),
|
||||
('Sasktel (Canada)', '%s@sms.sasktel.com', now()),
|
||||
('Setar Mobile email (Aruba)', '%s@mas.aw', now()),
|
||||
('Solo Mobile', '%s@txt.bell.ca', now()),
|
||||
('Sprint (PCS)', '%s@messaging.sprintpcs.com', now()),
|
||||
('Sprint (Nextel)', '%s@page.nextel.com', now()),
|
||||
('Suncom', '%s@tms.suncom.com', now()),
|
||||
('T-Mobile', '%s@tmomail.net', now()),
|
||||
('T-Mobile (Austria)', '%s@sms.t-mobile.at', now()),
|
||||
('Telus Mobility (Canada)', '%s@msg.telus.com', now()),
|
||||
('Thumb Cellular', '%s@sms.thumbcellular.com', now()),
|
||||
('Tigo (Formerly Ola)', '%s@sms.tigo.com.co', now()),
|
||||
('Unicel', '%s@utext.com', now()),
|
||||
('US Cellular', '%s@email.uscc.net', now()),
|
||||
('Verizon', '%s@vtext.com', now()),
|
||||
('Virgin Mobile (Canada)', '%s@vmobile.ca', now()),
|
||||
('Virgin Mobile (USA)', '%s@vmobl.com', now()),
|
||||
('Vodafone NZ (txt ''R'' to 901 to enable first)', '%s@sms.vodafone.net.nz', now()),
|
||||
('YCC', '%s@sms.ycc.ru', now());
|
@ -1,8 +1,5 @@
|
||||
insert into foreign_service
|
||||
(id, name, description, created)
|
||||
values
|
||||
('1','Twitter', 'Twitter Micro-blogging service', now());
|
||||
insert into foreign_service
|
||||
(id, name, description, created)
|
||||
values
|
||||
('2','Facebook', 'Facebook', now());
|
||||
('1','Twitter', 'Twitter Micro-blogging service', now()),
|
||||
('2','Facebook', 'Facebook', now());
|
||||
|
@ -31,7 +31,7 @@ create table avatar (
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table sms_carrier (
|
||||
id integer auto_increment primary key comment 'primary key for SMS carrier',
|
||||
id integer primary key comment 'primary key for SMS carrier',
|
||||
name varchar(64) unique key comment 'name of the carrier',
|
||||
email_pattern varchar(255) not null comment 'sprintf pattern for making an email address from a phone number',
|
||||
created datetime not null comment 'date this record was created',
|
||||
@ -50,6 +50,7 @@ create table user (
|
||||
emailnotifyfav tinyint default 1 comment 'Notify by email of favorites',
|
||||
emailnotifynudge tinyint default 1 comment 'Notify by email of nudges',
|
||||
emailnotifymsg tinyint default 1 comment 'Notify by email of direct messages',
|
||||
emailnotifyattn tinyint default 1 comment 'Notify by email of @-replies',
|
||||
emailmicroid tinyint default 1 comment 'whether to publish email microid',
|
||||
language varchar(50) comment 'preferred language',
|
||||
timezone varchar(50) comment 'timezone',
|
||||
@ -114,8 +115,10 @@ create table notice (
|
||||
reply_to integer comment 'notice replied to (usually a guess)' references notice (id),
|
||||
is_local tinyint default 0 comment 'notice was generated by a user',
|
||||
source varchar(32) comment 'source of comment, like "web", "im", or "clientname"',
|
||||
conversation integer comment 'id of root notice in this conversation' references notice (id),
|
||||
|
||||
index notice_profile_id_idx (profile_id),
|
||||
index notice_conversation_idx (conversation),
|
||||
index notice_created_idx (created),
|
||||
FULLTEXT(content)
|
||||
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
@ -170,7 +173,7 @@ create table token (
|
||||
tok char(32) not null comment 'identifying value',
|
||||
secret char(32) not null comment 'secret value',
|
||||
type tinyint not null default 0 comment 'request or access',
|
||||
state tinyint default 0 comment 'for requests; 0 = initial, 1 = authorized, 2 = used',
|
||||
state tinyint default 0 comment 'for requests, 0 = initial, 1 = authorized, 2 = used',
|
||||
|
||||
created datetime not null comment 'date this record was created',
|
||||
modified timestamp comment 'date this record was modified',
|
||||
@ -258,7 +261,8 @@ create table notice_tag (
|
||||
created datetime not null comment 'date this record was created',
|
||||
|
||||
constraint primary key (tag, notice_id),
|
||||
index notice_tag_created_idx (created)
|
||||
index notice_tag_created_idx (created),
|
||||
index notice_tag_notice_id_idx (notice_id)
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
/* Synching with foreign services */
|
||||
@ -342,7 +346,7 @@ 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 tinyint default 1 comment 'reason it is in the inbox; 1=subscription',
|
||||
source tinyint default 1 comment 'reason it is in the inbox, 1=subscription',
|
||||
|
||||
constraint primary key (user_id, notice_id),
|
||||
index notice_inbox_notice_id_idx (notice_id)
|
||||
@ -356,7 +360,8 @@ create table profile_tag (
|
||||
|
||||
constraint primary key (tagger, tagged, tag),
|
||||
index profile_tag_modified_idx (modified),
|
||||
index profile_tag_tagger_tag_idx (tagger, tag)
|
||||
index profile_tag_tagger_tag_idx (tagger, tag),
|
||||
index profile_tag_tagged_idx (tagged)
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table profile_block (
|
||||
@ -400,7 +405,9 @@ create table group_member (
|
||||
created datetime not null comment 'date this record was created',
|
||||
modified timestamp comment 'date this record was modified',
|
||||
|
||||
constraint primary key (group_id, profile_id)
|
||||
constraint primary key (group_id, profile_id),
|
||||
index group_member_profile_id_idx (profile_id),
|
||||
index group_member_created_idx (created)
|
||||
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
|
@ -8,7 +8,7 @@ create table profile (
|
||||
homepage varchar(255) /* comment 'identifying URL' */,
|
||||
bio varchar(140) /* comment 'descriptive biography' */,
|
||||
location varchar(255) /* comment 'physical location' */,
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */,
|
||||
|
||||
textsearch tsvector
|
||||
@ -23,7 +23,7 @@ create table avatar (
|
||||
mediatype varchar(32) not null /* comment 'file type' */,
|
||||
filename varchar(255) null /* comment 'local filename, if local' */,
|
||||
url varchar(255) unique /* comment 'avatar location' */,
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */,
|
||||
|
||||
primary key(profile_id, width, height)
|
||||
@ -34,7 +34,7 @@ create table sms_carrier (
|
||||
id serial primary key /* comment 'primary key for SMS carrier' */,
|
||||
name varchar(64) unique /* comment 'name of the carrier' */,
|
||||
email_pattern varchar(255) not null /* comment 'sprintf pattern for making an email address from a phone number' */,
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified ' */
|
||||
);
|
||||
|
||||
@ -50,6 +50,7 @@ create table "user" (
|
||||
emailnotifyfav integer default 1 /* comment 'Notify by email of favorites' */,
|
||||
emailnotifynudge integer default 1 /* comment 'Notify by email of nudges' */,
|
||||
emailnotifymsg integer default 1 /* comment 'Notify by email of direct messages' */,
|
||||
emailnotifyattn integer default 1 /* command 'Notify by email of @-replies' */,
|
||||
emailmicroid integer default 1 /* comment 'whether to publish email microid' */,
|
||||
language varchar(50) /* comment 'preferred language' */,
|
||||
timezone varchar(50) /* comment 'timezone' */,
|
||||
@ -68,7 +69,7 @@ create table "user" (
|
||||
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' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */
|
||||
|
||||
);
|
||||
@ -81,7 +82,7 @@ create table remote_profile (
|
||||
uri varchar(255) unique /* comment 'universally unique identifier, usually a tag URI' */,
|
||||
postnoticeurl varchar(255) /* comment 'URL we use for posting notices' */,
|
||||
updateprofileurl varchar(255) /* comment 'URL we use for updates to this profile' */,
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */
|
||||
);
|
||||
|
||||
@ -92,7 +93,7 @@ create table subscription (
|
||||
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' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */,
|
||||
|
||||
primary key (subscriber, subscribed)
|
||||
@ -108,7 +109,7 @@ create table notice (
|
||||
content varchar(140) /* comment 'update content' */,
|
||||
rendered text /* comment 'HTML version of the content' */,
|
||||
url varchar(255) /* comment 'URL of any attachment (image, video, bookmark, whatever)' */,
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */,
|
||||
reply_to integer /* comment 'notice replied to (usually a guess)' */ references notice (id) ,
|
||||
is_local integer default 0 /* comment 'notice was generated by a user' */,
|
||||
@ -123,7 +124,7 @@ create table notice_source (
|
||||
code varchar(32) primary key not null /* comment 'source code' */,
|
||||
name varchar(255) not null /* comment 'name of the source' */,
|
||||
url varchar(255) not null /* comment 'url to link to' */,
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */
|
||||
);
|
||||
|
||||
@ -131,7 +132,7 @@ create table reply (
|
||||
|
||||
notice_id integer not null /* comment 'notice that is the reply' */ references notice (id) ,
|
||||
profile_id integer not null /* comment 'profile replied to' */ references profile (id) ,
|
||||
modified timestamp not null default 'now' /* comment 'date this record was modified' */,
|
||||
modified timestamp /* comment 'date this record was modified' */,
|
||||
replied_id integer /* comment 'notice replied to (not used, see notice.reply_to)' */,
|
||||
|
||||
primary key (notice_id, profile_id)
|
||||
@ -145,7 +146,7 @@ create table fave (
|
||||
|
||||
notice_id integer not null /* comment 'notice that is the favorite' */ references notice (id),
|
||||
user_id integer not null /* comment 'user who likes this notice' */ references "user" (id) ,
|
||||
modified timestamp not null /* comment 'date this record was modified' */,
|
||||
modified timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was modified' */,
|
||||
primary key (notice_id, user_id)
|
||||
|
||||
);
|
||||
@ -159,7 +160,7 @@ create table consumer (
|
||||
consumer_key varchar(255) primary key /* comment 'unique identifier, root URL' */,
|
||||
seed char(32) not null /* comment 'seed for new tokens by this consumer' */,
|
||||
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */
|
||||
);
|
||||
|
||||
@ -170,7 +171,7 @@ create table token (
|
||||
type integer not null default 0 /* comment 'request or access' */,
|
||||
state integer default 0 /* comment 'for requests; 0 = initial, 1 = authorized, 2 = used' */,
|
||||
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */,
|
||||
|
||||
primary key (consumer_key, tok)
|
||||
@ -180,9 +181,9 @@ create table nonce (
|
||||
consumer_key varchar(255) not null /* comment 'unique identifier, root URL' */,
|
||||
tok char(32) not null /* comment 'identifying value' */,
|
||||
nonce char(32) not null /* comment 'nonce' */,
|
||||
ts timestamp not null /* comment 'timestamp sent' */,
|
||||
ts integer not null /* comment 'timestamp sent' values are epoch, and only used internally */,
|
||||
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */,
|
||||
|
||||
primary key (consumer_key, tok, nonce),
|
||||
@ -195,7 +196,7 @@ create table user_openid (
|
||||
canonical varchar(255) primary key /* comment 'Canonical true URL' */,
|
||||
display varchar(255) not null unique /* comment 'URL for viewing, may be different from canonical' */,
|
||||
user_id integer not null /* comment 'user owning this URL' */ references "user" (id) ,
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */
|
||||
|
||||
);
|
||||
@ -241,7 +242,7 @@ create table queue_item (
|
||||
|
||||
notice_id integer not null /* comment 'notice queued' */ references notice (id) ,
|
||||
transport varchar(8) not null /* comment 'queue for what? "email", "jabber", "sms", "irc", ...' */,
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
claimed timestamp /* comment 'date this item was claimed' */,
|
||||
|
||||
primary key (notice_id, transport)
|
||||
@ -253,7 +254,7 @@ create index queue_item_created_idx on queue_item using btree(created);
|
||||
create table notice_tag (
|
||||
tag varchar( 64 ) not null /* comment 'hash tag associated with this notice' */,
|
||||
notice_id integer not null /* comment 'notice tagged' */ references notice (id) ,
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
|
||||
primary key (tag, notice_id)
|
||||
);
|
||||
@ -265,7 +266,7 @@ create table foreign_service (
|
||||
id int not null primary key /* comment 'numeric key for service' */,
|
||||
name varchar(32) not null unique /* comment 'name of the service' */,
|
||||
description varchar(255) /* comment 'description' */,
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */
|
||||
);
|
||||
|
||||
@ -274,7 +275,7 @@ 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' */,
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */,
|
||||
|
||||
primary key (id, service)
|
||||
@ -288,8 +289,8 @@ create table foreign_link (
|
||||
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 */,
|
||||
profilesync int not null default 1 /* comment 'profile synchronization, 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' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */,
|
||||
|
||||
primary key (user_id,foreign_id,service)
|
||||
);
|
||||
@ -299,7 +300,7 @@ 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 default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
|
||||
primary key (service, subscriber, subscribed)
|
||||
);
|
||||
@ -311,7 +312,7 @@ create table invitation (
|
||||
user_id int not null /* comment 'who sent the invitation' */ references "user" (id),
|
||||
address varchar(255) not null /* comment 'invitation sent to' */,
|
||||
address_type varchar(8) not null /* comment 'address type ("email", "jabber", "sms") '*/,
|
||||
created timestamp not null /* comment 'date this record was created' */
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */
|
||||
|
||||
);
|
||||
create index invitation_address_idx on invitation using btree(address,address_type);
|
||||
@ -326,7 +327,7 @@ create table message (
|
||||
content varchar(140) /* comment 'message content' */,
|
||||
rendered text /* comment 'HTML version of the content' */,
|
||||
url varchar(255) /* comment 'URL of any attachment (image, video, bookmark, whatever)' */,
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */,
|
||||
source varchar(32) /* comment 'source of comment, like "web", "im", or "clientname"' */
|
||||
|
||||
@ -339,7 +340,7 @@ 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 timestamp not null /* comment 'date the notice was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* 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)
|
||||
@ -382,7 +383,7 @@ create table user_group (
|
||||
stream_logo varchar(255) /* comment 'stream-sized logo' */,
|
||||
mini_logo varchar(255) /* comment 'mini logo' */,
|
||||
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */
|
||||
|
||||
);
|
||||
@ -394,7 +395,7 @@ create table group_member (
|
||||
profile_id integer not null /* comment 'foreign key to profile table' */ references profile (id),
|
||||
is_admin integer default 0 /* comment 'is this user an admin?' */,
|
||||
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
modified timestamp /* comment 'date this record was modified' */,
|
||||
|
||||
primary key (group_id, profile_id)
|
||||
@ -405,7 +406,7 @@ create table related_group (
|
||||
group_id integer not null /* comment 'foreign key to user_group' */ references user_group (id) ,
|
||||
related_group_id integer not null /* comment 'foreign key to user_group' */ references user_group (id),
|
||||
|
||||
created timestamp not null /* comment 'date this record was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
|
||||
|
||||
primary key (group_id, related_group_id)
|
||||
|
||||
@ -414,7 +415,7 @@ create table related_group (
|
||||
create table group_inbox (
|
||||
group_id integer not null /* comment 'group receiving the message' references user_group (id) */,
|
||||
notice_id integer not null /* comment 'notice received' references notice (id) */,
|
||||
created timestamp not null /* comment 'date the notice was created' */,
|
||||
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date the notice was created' */,
|
||||
|
||||
primary key (group_id, notice_id)
|
||||
);
|
||||
|
46
db/notice_source.sql
Normal file
46
db/notice_source.sql
Normal file
@ -0,0 +1,46 @@
|
||||
INSERT INTO notice_source
|
||||
(code, name, url, created)
|
||||
VALUES
|
||||
('Do','Gnome Do','http://do.davebsd.com/wiki/index.php?title=Microblog_Plugin', now()),
|
||||
('Facebook','Facebook','http://apps.facebook.com/identica/', now()),
|
||||
('Gwibber','Gwibber','http://launchpad.net/gwibber', now()),
|
||||
('HelloTxt','HelloTxt','http://hellotxt.com/', now()),
|
||||
('IdentiFox','IdentiFox','http://www.bitbucket.org/uncryptic/identifox/', now()),
|
||||
('LaTwit','LaTwit','http://latwit.mac65.com/', now()),
|
||||
('Nambu','Nambu','http://www.nambu.com/', now()),
|
||||
('Pikchur','Pikchur','http://www.pikchur.com/', now()),
|
||||
('Ping.fm','Ping.fm','http://ping.fm/', now()),
|
||||
('Twidge','Twidge','http://software.complete.org/twidge', now()),
|
||||
('Updating.Me','Updating.Me','http://updating.me/', now()),
|
||||
('betwittered','BeTwittered','http://www.32hours.com/betwitteredinfo/', now()),
|
||||
('bti','bti','http://gregkh.github.com/bti/', now()),
|
||||
('deskbar','Deskbar-Applet','http://www.gnome.org/projects/deskbar-applet/', now()),
|
||||
('identicatools','Laconica Tools','http://bitbucketlabs.net/laconica-tools/', now()),
|
||||
('identichat','identichat','http://identichat.prosody.im/', now()),
|
||||
('identitwitch','IdentiTwitch','http://richfish.org/identitwitch/', now()),
|
||||
('mbpidgin','mbpidgin','http://code.google.com/p/microblog-purple/', now()),
|
||||
('moconica','Moconica','http://moconica.com/', now()),
|
||||
('pocketwit','PockeTwit','http://code.google.com/p/pocketwit/', now()),
|
||||
('posty','Posty','http://spreadingfunkyness.com/posty/', now()),
|
||||
('royalewithcheese','Royale With Cheese','http://p.hellyeah.org/', now()),
|
||||
('rssdent','rssdent','http://github.com/zcopley/rssdent/tree/master', now()),
|
||||
('rygh.no','rygh.no','http://rygh.no/', now()),
|
||||
('ryghsms','ryghsms','http://sms.rygh.no/', now()),
|
||||
('smob','SMOB','http://smob.sioc-project.org/', now()),
|
||||
('spaz','Spaz','http://funkatron.com/spaz', now()),
|
||||
('tarpipe','tarpipe','http://tarpipe.com/', now()),
|
||||
('tjunar','Tjunar','http://nederflash.nl/boek/titels/tjunar-air', now()),
|
||||
('tr.im','tr.im','http://tr.im/', now()),
|
||||
('tweenky','Tweenky','http://beta.tweenky.com/', now()),
|
||||
('twhirl','Twhirl','http://www.twhirl.org/', now()),
|
||||
('twibble','twibble','http://www.twibble.de/', now()),
|
||||
('twidge','Twidge','http://software.complete.org/twidge', now()),
|
||||
('twidroid','twidroid','http://www.twidroid.com/', now()),
|
||||
('twittelator','Twittelator','http://www.stone.com/iPhone/Twittelator/', now()),
|
||||
('twitterfeed','twitterfeed','http://twitterfeed.com/', now()),
|
||||
('twitterphoto','TwitterPhoto','http://richfish.org/twitterphoto/', now()),
|
||||
('twitterpm','Net::Twitter','http://search.cpan.org/dist/Net-Twitter/', now()),
|
||||
('twittertools','Twitter Tools','http://wordpress.org/extend/plugins/twitter-tools/', now()),
|
||||
('twitux','Twitux','http://live.gnome.org/DanielMorales/Twitux', now()),
|
||||
('twitvim','TwitVim','http://vim.sourceforge.net/scripts/script.php?script_id=2204', now()),
|
||||
('urfastr','urfastr','http://urfastr.net/', now());
|
63
db/sms_carrier.sql
Normal file
63
db/sms_carrier.sql
Normal file
@ -0,0 +1,63 @@
|
||||
INSERT INTO sms_carrier
|
||||
(id, name, email_pattern, created)
|
||||
VALUES
|
||||
(100056, '3 River Wireless', '%s@sms.3rivers.net', now()),
|
||||
(100057, '7-11 Speakout', '%s@cingularme.com', now()),
|
||||
(100058, 'Airtel (Karnataka, India)', '%s@airtelkk.com', now()),
|
||||
(100059, 'Alaska Communications Systems', '%s@msg.acsalaska.com', now()),
|
||||
(100060, 'Alltel Wireless', '%s@message.alltel.com', now()),
|
||||
(100061, 'AT&T Wireless', '%s@txt.att.net', now()),
|
||||
(100062, 'Bell Mobility (Canada)', '%s@txt.bell.ca', now()),
|
||||
(100063, 'Boost Mobile', '%s@myboostmobile.com', now()),
|
||||
(100064, 'Cellular One (Dobson)', '%s@mobile.celloneusa.com', now()),
|
||||
(100065, 'Cingular (Postpaid)', '%s@cingularme.com', now()),
|
||||
(100066, 'Centennial Wireless', '%s@cwemail.com', now()),
|
||||
(100067, 'Cingular (GoPhone prepaid)', '%s@cingularme.com', now()),
|
||||
(100068, 'Claro (Nicaragua)', '%s@ideasclaro-ca.com', now()),
|
||||
(100069, 'Comcel', '%s@comcel.com.co', now()),
|
||||
(100070, 'Cricket', '%s@sms.mycricket.com', now()),
|
||||
(100071, 'CTI', '%s@sms.ctimovil.com.ar', now()),
|
||||
(100072, 'Emtel (Mauritius)', '%s@emtelworld.net', now()),
|
||||
(100073, 'Fido (Canada)', '%s@fido.ca', now()),
|
||||
(100074, 'General Communications Inc.', '%s@msg.gci.net', now()),
|
||||
(100075, 'Globalstar', '%s@msg.globalstarusa.com', now()),
|
||||
(100076, 'Helio', '%s@myhelio.com', now()),
|
||||
(100077, 'Illinois Valley Cellular', '%s@ivctext.com', now()),
|
||||
(100078, 'i wireless', '%s.iws@iwspcs.net', now()),
|
||||
(100079, 'Meteor (Ireland)', '%s@sms.mymeteor.ie', now()),
|
||||
(100080, 'Mero Mobile (Nepal)', '%s@sms.spicenepal.com', now()),
|
||||
(100081, 'MetroPCS', '%s@mymetropcs.com', now()),
|
||||
(100082, 'Movicom', '%s@movimensaje.com.ar', now()),
|
||||
(100083, 'Mobitel (Sri Lanka)', '%s@sms.mobitel.lk', now()),
|
||||
(100084, 'Movistar (Colombia)', '%s@movistar.com.co', now()),
|
||||
(100085, 'MTN (South Africa)', '%s@sms.co.za', now()),
|
||||
(100086, 'MTS (Canada)', '%s@text.mtsmobility.com', now()),
|
||||
(100087, 'Nextel (Argentina)', '%s@nextel.net.ar', now()),
|
||||
(100088, 'Orange (Poland)', '%s@orange.pl', now()),
|
||||
(100089, 'Personal (Argentina)', '%s@personal-net.com.ar', now()),
|
||||
(100090, 'Plus GSM (Poland)', '%s@text.plusgsm.pl', now()),
|
||||
(100091, 'President\'s Choice (Canada)', '%s@txt.bell.ca', now()),
|
||||
(100092, 'Qwest', '%s@qwestmp.com', now()),
|
||||
(100093, 'Rogers (Canada)', '%s@pcs.rogers.com', now()),
|
||||
(100094, 'Sasktel (Canada)', '%s@sms.sasktel.com', now()),
|
||||
(100095, 'Setar Mobile email (Aruba)', '%s@mas.aw', now()),
|
||||
(100096, 'Solo Mobile', '%s@txt.bell.ca', now()),
|
||||
(100097, 'Sprint (PCS)', '%s@messaging.sprintpcs.com', now()),
|
||||
(100098, 'Sprint (Nextel)', '%s@page.nextel.com', now()),
|
||||
(100099, 'Suncom', '%s@tms.suncom.com', now()),
|
||||
(100100, 'T-Mobile', '%s@tmomail.net', now()),
|
||||
(100101, 'T-Mobile (Austria)', '%s@sms.t-mobile.at', now()),
|
||||
(100102, 'Telus Mobility (Canada)', '%s@msg.telus.com', now()),
|
||||
(100103, 'Thumb Cellular', '%s@sms.thumbcellular.com', now()),
|
||||
(100104, 'Tigo (Formerly Ola)', '%s@sms.tigo.com.co', now()),
|
||||
(100105, 'Unicel', '%s@utext.com', now()),
|
||||
(100106, 'US Cellular', '%s@email.uscc.net', now()),
|
||||
(100107, 'Verizon', '%s@vtext.com', now()),
|
||||
(100108, 'Virgin Mobile (Canada)', '%s@vmobile.ca', now()),
|
||||
(100109, 'Virgin Mobile (USA)', '%s@vmobl.com', now()),
|
||||
(100110, 'YCC', '%s@sms.ycc.ru', now()),
|
||||
(100111, 'Orange (UK)', '%s@orange.net', now()),
|
||||
(100112, 'Cincinnati Bell Wireless', '%s@gocbw.com', now()),
|
||||
(100113, 'T-Mobile Germany', '%s@t-mobile-sms.de', now()),
|
||||
(100114, 'Vodafone Germany', '%s@vodafone-sms.de', now()),
|
||||
(100115, 'E-Plus', '%s@smsmail.eplus.de', now());
|
65
doc-src/badge
Normal file
65
doc-src/badge
Normal file
@ -0,0 +1,65 @@
|
||||
Install the %%site.name%% badge on you blog or web site to show the latest updates
|
||||
from you and your friends!
|
||||
|
||||
<MTMarkdownOptions output='raw'>
|
||||
<script type="text/javascript" src="http://identi.ca/js/identica-badge.js">
|
||||
{
|
||||
"user":"kentbrew",
|
||||
"server":"identi.ca",
|
||||
"headerText":" and friends"
|
||||
}
|
||||
</script>
|
||||
</MTMarkdownOptions>
|
||||
|
||||
Things to try
|
||||
--------------
|
||||
|
||||
* Click an avatar and the badge will refresh with that user's timeline
|
||||
* Click a nickname to open a user's profile in your browser
|
||||
* Click a notice's timestamp to view the notice in your browser
|
||||
* @-replies and #tags are live links
|
||||
|
||||
## Installation instructions
|
||||
|
||||
Copy and paste the following JavaScript into an HTML page where
|
||||
you want the badge to show up. Substitute your own ID in the user
|
||||
parameter.
|
||||
|
||||
<pre>
|
||||
<script type="text/javascript" src="http://identi.ca/js/identica-badge.js">
|
||||
{
|
||||
"user":"kentbrew",
|
||||
"server":"identi.ca",
|
||||
"headerText":" and friends"
|
||||
}
|
||||
</script>
|
||||
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
Valid parameters for the badge:
|
||||
-------------------------------
|
||||
|
||||
* user : defaults to 7000 (@kentbrew)
|
||||
* headerText : defaults to empty
|
||||
* height : defaults to 350px
|
||||
* width : defaults to 300px
|
||||
* background : defaults to #193441. If you set evenBackground, oddBackground,
|
||||
and headerBackground, you won't see it at all.
|
||||
* border : defaults to 1px solid black
|
||||
* userColor : defaults to whatever link color is set to on your page
|
||||
* headerBackground : defaults to transparent
|
||||
* headerColor : defaults to white
|
||||
* evenBackground : defaults to #fff
|
||||
* oddBackground : defaults to #eee
|
||||
* thumbnailBorder : 1px solid black
|
||||
* thumbnailSize : defaults to 24px
|
||||
* padding : defaults to 3px
|
||||
* server : defaults to identi.ca
|
||||
|
||||
Licence
|
||||
-------
|
||||
|
||||
Identi.ca badge by [Kent Brewster](http://kentbrewster.com/identica-badge/).
|
||||
Licenced under [CC-BY-SA-3](http://kentbrewster.com/rights-and-permissions/).
|
485
extlib/Net/URL.php
Normal file
485
extlib/Net/URL.php
Normal file
@ -0,0 +1,485 @@
|
||||
<?php
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | Copyright (c) 2002-2004, Richard Heyes |
|
||||
// | All rights reserved. |
|
||||
// | |
|
||||
// | Redistribution and use in source and binary forms, with or without |
|
||||
// | modification, are permitted provided that the following conditions |
|
||||
// | are met: |
|
||||
// | |
|
||||
// | o Redistributions of source code must retain the above copyright |
|
||||
// | notice, this list of conditions and the following disclaimer. |
|
||||
// | o Redistributions in binary form must reproduce the above copyright |
|
||||
// | notice, this list of conditions and the following disclaimer in the |
|
||||
// | documentation and/or other materials provided with the distribution.|
|
||||
// | o The names of the authors may not be used to endorse or promote |
|
||||
// | products derived from this software without specific prior written |
|
||||
// | permission. |
|
||||
// | |
|
||||
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
||||
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
||||
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
||||
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
||||
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
||||
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
||||
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
||||
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
||||
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
||||
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
||||
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
||||
// | |
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | Author: Richard Heyes <richard at php net> |
|
||||
// +-----------------------------------------------------------------------+
|
||||
//
|
||||
// $Id: URL.php,v 1.49 2007/06/28 14:43:07 davidc Exp $
|
||||
//
|
||||
// Net_URL Class
|
||||
|
||||
|
||||
class Net_URL
|
||||
{
|
||||
var $options = array('encode_query_keys' => false);
|
||||
/**
|
||||
* Full url
|
||||
* @var string
|
||||
*/
|
||||
var $url;
|
||||
|
||||
/**
|
||||
* Protocol
|
||||
* @var string
|
||||
*/
|
||||
var $protocol;
|
||||
|
||||
/**
|
||||
* Username
|
||||
* @var string
|
||||
*/
|
||||
var $username;
|
||||
|
||||
/**
|
||||
* Password
|
||||
* @var string
|
||||
*/
|
||||
var $password;
|
||||
|
||||
/**
|
||||
* Host
|
||||
* @var string
|
||||
*/
|
||||
var $host;
|
||||
|
||||
/**
|
||||
* Port
|
||||
* @var integer
|
||||
*/
|
||||
var $port;
|
||||
|
||||
/**
|
||||
* Path
|
||||
* @var string
|
||||
*/
|
||||
var $path;
|
||||
|
||||
/**
|
||||
* Query string
|
||||
* @var array
|
||||
*/
|
||||
var $querystring;
|
||||
|
||||
/**
|
||||
* Anchor
|
||||
* @var string
|
||||
*/
|
||||
var $anchor;
|
||||
|
||||
/**
|
||||
* Whether to use []
|
||||
* @var bool
|
||||
*/
|
||||
var $useBrackets;
|
||||
|
||||
/**
|
||||
* PHP4 Constructor
|
||||
*
|
||||
* @see __construct()
|
||||
*/
|
||||
function Net_URL($url = null, $useBrackets = true)
|
||||
{
|
||||
$this->__construct($url, $useBrackets);
|
||||
}
|
||||
|
||||
/**
|
||||
* PHP5 Constructor
|
||||
*
|
||||
* Parses the given url and stores the various parts
|
||||
* Defaults are used in certain cases
|
||||
*
|
||||
* @param string $url Optional URL
|
||||
* @param bool $useBrackets Whether to use square brackets when
|
||||
* multiple querystrings with the same name
|
||||
* exist
|
||||
*/
|
||||
function __construct($url = null, $useBrackets = true)
|
||||
{
|
||||
$this->url = $url;
|
||||
$this->useBrackets = $useBrackets;
|
||||
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
function initialize()
|
||||
{
|
||||
$HTTP_SERVER_VARS = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
|
||||
|
||||
$this->user = '';
|
||||
$this->pass = '';
|
||||
$this->host = '';
|
||||
$this->port = 80;
|
||||
$this->path = '';
|
||||
$this->querystring = array();
|
||||
$this->anchor = '';
|
||||
|
||||
// Only use defaults if not an absolute URL given
|
||||
if (!preg_match('/^[a-z0-9]+:\/\//i', $this->url)) {
|
||||
$this->protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 'https' : 'http');
|
||||
|
||||
/**
|
||||
* Figure out host/port
|
||||
*/
|
||||
if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) &&
|
||||
preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches))
|
||||
{
|
||||
$host = $matches[1];
|
||||
if (!empty($matches[3])) {
|
||||
$port = $matches[3];
|
||||
} else {
|
||||
$port = $this->getStandardPort($this->protocol);
|
||||
}
|
||||
}
|
||||
|
||||
$this->user = '';
|
||||
$this->pass = '';
|
||||
$this->host = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost');
|
||||
$this->port = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol));
|
||||
$this->path = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/';
|
||||
$this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null;
|
||||
$this->anchor = '';
|
||||
}
|
||||
|
||||
// Parse the url and store the various parts
|
||||
if (!empty($this->url)) {
|
||||
$urlinfo = parse_url($this->url);
|
||||
|
||||
// Default querystring
|
||||
$this->querystring = array();
|
||||
|
||||
foreach ($urlinfo as $key => $value) {
|
||||
switch ($key) {
|
||||
case 'scheme':
|
||||
$this->protocol = $value;
|
||||
$this->port = $this->getStandardPort($value);
|
||||
break;
|
||||
|
||||
case 'user':
|
||||
case 'pass':
|
||||
case 'host':
|
||||
case 'port':
|
||||
$this->$key = $value;
|
||||
break;
|
||||
|
||||
case 'path':
|
||||
if ($value{0} == '/') {
|
||||
$this->path = $value;
|
||||
} else {
|
||||
$path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path);
|
||||
$this->path = sprintf('%s/%s', $path, $value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'query':
|
||||
$this->querystring = $this->_parseRawQueryString($value);
|
||||
break;
|
||||
|
||||
case 'fragment':
|
||||
$this->anchor = $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns full url
|
||||
*
|
||||
* @return string Full url
|
||||
* @access public
|
||||
*/
|
||||
function getURL()
|
||||
{
|
||||
$querystring = $this->getQueryString();
|
||||
|
||||
$this->url = $this->protocol . '://'
|
||||
. $this->user . (!empty($this->pass) ? ':' : '')
|
||||
. $this->pass . (!empty($this->user) ? '@' : '')
|
||||
. $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port)
|
||||
. $this->path
|
||||
. (!empty($querystring) ? '?' . $querystring : '')
|
||||
. (!empty($this->anchor) ? '#' . $this->anchor : '');
|
||||
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds or updates a querystring item (URL parameter).
|
||||
* Automatically encodes parameters with rawurlencode() if $preencoded
|
||||
* is false.
|
||||
* You can pass an array to $value, it gets mapped via [] in the URL if
|
||||
* $this->useBrackets is activated.
|
||||
*
|
||||
* @param string $name Name of item
|
||||
* @param string $value Value of item
|
||||
* @param bool $preencoded Whether value is urlencoded or not, default = not
|
||||
* @access public
|
||||
*/
|
||||
function addQueryString($name, $value, $preencoded = false)
|
||||
{
|
||||
if ($this->getOption('encode_query_keys')) {
|
||||
$name = rawurlencode($name);
|
||||
}
|
||||
|
||||
if ($preencoded) {
|
||||
$this->querystring[$name] = $value;
|
||||
} else {
|
||||
$this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a querystring item
|
||||
*
|
||||
* @param string $name Name of item
|
||||
* @access public
|
||||
*/
|
||||
function removeQueryString($name)
|
||||
{
|
||||
if ($this->getOption('encode_query_keys')) {
|
||||
$name = rawurlencode($name);
|
||||
}
|
||||
|
||||
if (isset($this->querystring[$name])) {
|
||||
unset($this->querystring[$name]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the querystring to literally what you supply
|
||||
*
|
||||
* @param string $querystring The querystring data. Should be of the format foo=bar&x=y etc
|
||||
* @access public
|
||||
*/
|
||||
function addRawQueryString($querystring)
|
||||
{
|
||||
$this->querystring = $this->_parseRawQueryString($querystring);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns flat querystring
|
||||
*
|
||||
* @return string Querystring
|
||||
* @access public
|
||||
*/
|
||||
function getQueryString()
|
||||
{
|
||||
if (!empty($this->querystring)) {
|
||||
foreach ($this->querystring as $name => $value) {
|
||||
// Encode var name
|
||||
$name = rawurlencode($name);
|
||||
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $k => $v) {
|
||||
$querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v);
|
||||
}
|
||||
} elseif (!is_null($value)) {
|
||||
$querystring[] = $name . '=' . $value;
|
||||
} else {
|
||||
$querystring[] = $name;
|
||||
}
|
||||
}
|
||||
$querystring = implode(ini_get('arg_separator.output'), $querystring);
|
||||
} else {
|
||||
$querystring = '';
|
||||
}
|
||||
|
||||
return $querystring;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses raw querystring and returns an array of it
|
||||
*
|
||||
* @param string $querystring The querystring to parse
|
||||
* @return array An array of the querystring data
|
||||
* @access private
|
||||
*/
|
||||
function _parseRawQuerystring($querystring)
|
||||
{
|
||||
$parts = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY);
|
||||
$return = array();
|
||||
|
||||
foreach ($parts as $part) {
|
||||
if (strpos($part, '=') !== false) {
|
||||
$value = substr($part, strpos($part, '=') + 1);
|
||||
$key = substr($part, 0, strpos($part, '='));
|
||||
} else {
|
||||
$value = null;
|
||||
$key = $part;
|
||||
}
|
||||
|
||||
if (!$this->getOption('encode_query_keys')) {
|
||||
$key = rawurldecode($key);
|
||||
}
|
||||
|
||||
if (preg_match('#^(.*)\[([0-9a-z_-]*)\]#i', $key, $matches)) {
|
||||
$key = $matches[1];
|
||||
$idx = $matches[2];
|
||||
|
||||
// Ensure is an array
|
||||
if (empty($return[$key]) || !is_array($return[$key])) {
|
||||
$return[$key] = array();
|
||||
}
|
||||
|
||||
// Add data
|
||||
if ($idx === '') {
|
||||
$return[$key][] = $value;
|
||||
} else {
|
||||
$return[$key][$idx] = $value;
|
||||
}
|
||||
} elseif (!$this->useBrackets AND !empty($return[$key])) {
|
||||
$return[$key] = (array)$return[$key];
|
||||
$return[$key][] = $value;
|
||||
} else {
|
||||
$return[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves //, ../ and ./ from a path and returns
|
||||
* the result. Eg:
|
||||
*
|
||||
* /foo/bar/../boo.php => /foo/boo.php
|
||||
* /foo/bar/../../boo.php => /boo.php
|
||||
* /foo/bar/.././/boo.php => /foo/boo.php
|
||||
*
|
||||
* This method can also be called statically.
|
||||
*
|
||||
* @param string $path URL path to resolve
|
||||
* @return string The result
|
||||
*/
|
||||
function resolvePath($path)
|
||||
{
|
||||
$path = explode('/', str_replace('//', '/', $path));
|
||||
|
||||
for ($i=0; $i<count($path); $i++) {
|
||||
if ($path[$i] == '.') {
|
||||
unset($path[$i]);
|
||||
$path = array_values($path);
|
||||
$i--;
|
||||
|
||||
} elseif ($path[$i] == '..' AND ($i > 1 OR ($i == 1 AND $path[0] != '') ) ) {
|
||||
unset($path[$i]);
|
||||
unset($path[$i-1]);
|
||||
$path = array_values($path);
|
||||
$i -= 2;
|
||||
|
||||
} elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') {
|
||||
unset($path[$i]);
|
||||
$path = array_values($path);
|
||||
$i--;
|
||||
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return implode('/', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the standard port number for a protocol
|
||||
*
|
||||
* @param string $scheme The protocol to lookup
|
||||
* @return integer Port number or NULL if no scheme matches
|
||||
*
|
||||
* @author Philippe Jausions <Philippe.Jausions@11abacus.com>
|
||||
*/
|
||||
function getStandardPort($scheme)
|
||||
{
|
||||
switch (strtolower($scheme)) {
|
||||
case 'http': return 80;
|
||||
case 'https': return 443;
|
||||
case 'ftp': return 21;
|
||||
case 'imap': return 143;
|
||||
case 'imaps': return 993;
|
||||
case 'pop3': return 110;
|
||||
case 'pop3s': return 995;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the URL to a particular protocol
|
||||
*
|
||||
* @param string $protocol Protocol to force the URL to
|
||||
* @param integer $port Optional port (standard port is used by default)
|
||||
*/
|
||||
function setProtocol($protocol, $port = null)
|
||||
{
|
||||
$this->protocol = $protocol;
|
||||
$this->port = is_null($port) ? $this->getStandardPort($protocol) : $port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an option
|
||||
*
|
||||
* This function set an option
|
||||
* to be used thorough the script.
|
||||
*
|
||||
* @access public
|
||||
* @param string $optionName The optionname to set
|
||||
* @param string $value The value of this option.
|
||||
*/
|
||||
function setOption($optionName, $value)
|
||||
{
|
||||
if (!array_key_exists($optionName, $this->options)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->options[$optionName] = $value;
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an option
|
||||
*
|
||||
* This function gets an option
|
||||
* from the $this->options array
|
||||
* and return it's value.
|
||||
*
|
||||
* @access public
|
||||
* @param string $opionName The name of the option to retrieve
|
||||
* @see $this->options
|
||||
*/
|
||||
function getOption($optionName)
|
||||
{
|
||||
if (!isset($this->options[$optionName])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->options[$optionName];
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
324
extlib/Net/URL/Mapper.php
Normal file
324
extlib/Net/URL/Mapper.php
Normal file
@ -0,0 +1,324 @@
|
||||
<?php
|
||||
/**
|
||||
* URL parser and mapper
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * The names of the authors may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @category Net
|
||||
* @package Net_URL_Mapper
|
||||
* @author Bertrand Mansion <golgote@mamasam.com>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version CVS: $Id: Mapper.php,v 1.1 2007/03/28 10:23:04 mansion Exp $
|
||||
* @link http://pear.php.net/package/Net_URL_Mapper
|
||||
*/
|
||||
|
||||
require_once 'Net/URL/Mapper/Path.php';
|
||||
require_once 'Net/URL/Mapper/Exception.php';
|
||||
|
||||
/**
|
||||
* URL parser and mapper class
|
||||
*
|
||||
* This class takes an URL and a configuration and returns formatted data
|
||||
* about the request according to a configuration parameter
|
||||
*
|
||||
* @category Net
|
||||
* @package Net_URL_Mapper
|
||||
* @author Bertrand Mansion <golgote@mamasam.com>
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class Net_URL_Mapper
|
||||
{
|
||||
/**
|
||||
* Array of Net_URL_Mapper instances
|
||||
* @var array
|
||||
*/
|
||||
private static $instances = array();
|
||||
|
||||
/**
|
||||
* Mapped paths collection
|
||||
* @var array
|
||||
*/
|
||||
protected $paths = array();
|
||||
|
||||
/**
|
||||
* Prefix used for url mapping
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix = '';
|
||||
|
||||
/**
|
||||
* Optional scriptname if mod_rewrite is not available
|
||||
* @var string
|
||||
*/
|
||||
protected $scriptname = '';
|
||||
|
||||
/**
|
||||
* Mapper instance id
|
||||
* @var string
|
||||
*/
|
||||
protected $id = '__default__';
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
* Constructor is private, you should use getInstance() instead.
|
||||
*/
|
||||
private function __construct() { }
|
||||
|
||||
/**
|
||||
* Returns a singleton object corresponding to the requested instance id
|
||||
* @param string Requested instance name
|
||||
* @return Object Net_URL_Mapper Singleton
|
||||
*/
|
||||
public static function getInstance($id = '__default__')
|
||||
{
|
||||
if (!isset(self::$instances[$id])) {
|
||||
$m = new Net_URL_Mapper();
|
||||
$m->id = $id;
|
||||
self::$instances[$id] = $m;
|
||||
}
|
||||
return self::$instances[$id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the instance id
|
||||
* @return string Mapper instance id
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a path and creates a connection
|
||||
* @param string The path to connect
|
||||
* @param array Default values for path parts
|
||||
* @param array Regular expressions for path parts
|
||||
* @return object Net_URL_Mapper_Path
|
||||
*/
|
||||
public function connect($path, $defaults = array(), $rules = array())
|
||||
{
|
||||
$pathObj = new Net_URL_Mapper_Path($path, $defaults, $rules);
|
||||
$this->addPath($pathObj);
|
||||
return $pathObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the url prefix if needed
|
||||
*
|
||||
* Example: using the prefix to differenciate mapper instances
|
||||
* <code>
|
||||
* $fr = Net_URL_Mapper::getInstance('fr');
|
||||
* $fr->setPrefix('/fr');
|
||||
* $en = Net_URL_Mapper::getInstance('en');
|
||||
* $en->setPrefix('/en');
|
||||
* </code>
|
||||
*
|
||||
* @param string URL prefix
|
||||
*/
|
||||
public function setPrefix($prefix)
|
||||
{
|
||||
$this->prefix = '/'.trim($prefix, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scriptname if mod_rewrite not available
|
||||
*
|
||||
* Example: will match and generate url like
|
||||
* - index.php/view/product/1
|
||||
* <code>
|
||||
* $m = Net_URL_Mapper::getInstance();
|
||||
* $m->setScriptname('index.php');
|
||||
* </code>
|
||||
* @param string URL prefix
|
||||
*/
|
||||
public function setScriptname($scriptname)
|
||||
{
|
||||
$this->scriptname = $scriptname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will attempt to match an url with a defined path
|
||||
*
|
||||
* If an url corresponds to a path, the resulting values are returned
|
||||
* in an array. If none is found, null is returned. In case an url is
|
||||
* matched but its content doesn't validate the path rules, an exception is
|
||||
* thrown.
|
||||
*
|
||||
* @param string URL
|
||||
* @return array|null array if match found, null otherwise
|
||||
* @throws Net_URL_Mapper_InvalidException
|
||||
*/
|
||||
public function match($url)
|
||||
{
|
||||
$nurl = '/'.trim($url, '/');
|
||||
|
||||
// Remove scriptname if needed
|
||||
|
||||
if (!empty($this->scriptname) &&
|
||||
strpos($nurl, $this->scriptname) === 0) {
|
||||
$nurl = substr($nurl, strlen($this->scriptname));
|
||||
if (empty($nurl)) {
|
||||
$nurl = '/';
|
||||
}
|
||||
}
|
||||
|
||||
// Remove prefix
|
||||
|
||||
if (!empty($this->prefix)) {
|
||||
if (strpos($nurl, $this->prefix) !== 0) {
|
||||
return null;
|
||||
}
|
||||
$nurl = substr($nurl, strlen($this->prefix));
|
||||
if (empty($nurl)) {
|
||||
$nurl = '/';
|
||||
}
|
||||
}
|
||||
|
||||
// Remove query string
|
||||
|
||||
if (($pos = strpos($nurl, '?')) !== false) {
|
||||
$nurl = substr($nurl, 0, $pos);
|
||||
}
|
||||
|
||||
$paths = array();
|
||||
$values = null;
|
||||
|
||||
// Make a list of paths that conform to route format
|
||||
|
||||
foreach ($this->paths as $path) {
|
||||
$regex = $path->getFormat();
|
||||
if (preg_match($regex, $nurl)) {
|
||||
$paths[] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure one of the paths found is valid
|
||||
|
||||
foreach ($paths as $path) {
|
||||
$regex = $path->getRule();
|
||||
if (preg_match($regex, $nurl, $matches)) {
|
||||
$values = $path->getDefaults();
|
||||
array_shift($matches);
|
||||
$clean = array();
|
||||
foreach ($matches as $k => $v) {
|
||||
$v = trim($v, '/');
|
||||
if (!is_int($k) && $v !== '') {
|
||||
$values[$k] = $v;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// A path conforms but does not validate
|
||||
|
||||
if (is_null($values) && !empty($paths)) {
|
||||
$e = new Net_URL_Mapper_InvalidException('A path was found but is invalid.');
|
||||
$e->setPath($paths[0]);
|
||||
$e->setUrl($url);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an url based on given parameters
|
||||
*
|
||||
* Will attempt to find a path definition that matches the given parameters and
|
||||
* will generate an url based on this path.
|
||||
*
|
||||
* @param array Values to be used for the url generation
|
||||
* @param array Key/value pairs for query string if needed
|
||||
* @param string Anchor (fragment) if needed
|
||||
* @return string|false String if a rule was found, false otherwise
|
||||
*/
|
||||
public function generate($values = array(), $qstring = array(), $anchor = '')
|
||||
{
|
||||
// Use root path if any
|
||||
|
||||
if (empty($values) && isset($this->paths['/'])) {
|
||||
return $this->scriptname.$this->prefix.$this->paths['/']->generate($values, $qstring, $anchor);
|
||||
}
|
||||
|
||||
foreach ($this->paths as $path) {
|
||||
$set = array();
|
||||
foreach ($values as $k => $v) {
|
||||
if ($path->hasKey($k, $v)) {
|
||||
$set[$k] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($set) == count($values) &&
|
||||
count($set) <= $path->getMaxKeys()) {
|
||||
|
||||
$req = $path->getRequired();
|
||||
if (count(array_intersect(array_keys($set), $req)) != count($req)) {
|
||||
continue;
|
||||
}
|
||||
$gen = $path->generate($set, $qstring, $anchor);
|
||||
return $this->scriptname.$this->prefix.$gen;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns defined paths
|
||||
* @return array Array of paths
|
||||
*/
|
||||
public function getPaths()
|
||||
{
|
||||
return $this->paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all paths
|
||||
* This is probably only useful for testing
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->paths = array();
|
||||
$this->prefix = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new path to the mapper
|
||||
* @param object Net_URL_Mapper_Path object
|
||||
*/
|
||||
public function addPath(Net_URL_Mapper_Path $path)
|
||||
{
|
||||
$this->paths[$path->getPath()] = $path;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
104
extlib/Net/URL/Mapper/Exception.php
Normal file
104
extlib/Net/URL/Mapper/Exception.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/**
|
||||
* Exception classes for Net_URL_Mapper
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * The names of the authors may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @category Net
|
||||
* @package Net_URL_Mapper
|
||||
* @author Bertrand Mansion <golgote@mamasam.com>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version CVS: $Id: Exception.php,v 1.1 2007/03/28 10:23:04 mansion Exp $
|
||||
* @link http://pear.php.net/package/Net_URL_Mapper
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base class for exceptions in PEAR
|
||||
*/
|
||||
require_once 'PEAR/Exception.php';
|
||||
|
||||
/**
|
||||
* Base class for exceptions in Net_URL_Mapper package
|
||||
*
|
||||
* Such a base class is required by the Exception RFC:
|
||||
* http://pear.php.net/pepr/pepr-proposal-show.php?id=132
|
||||
* It will rarely be thrown directly, its specialized subclasses will be
|
||||
* thrown most of the time.
|
||||
*
|
||||
* @category Net
|
||||
* @package Net_URL_Mapper
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class Net_URL_Mapper_Exception extends PEAR_Exception
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when a path is invalid
|
||||
*
|
||||
* A path can conform to a given structure, but contain invalid parameters.
|
||||
* <code>
|
||||
* $m = Net_URL_Mapper::getInstance();
|
||||
* $m->connect('hi/:name', null, array('name'=>'[a-z]+'));
|
||||
* $m->match('/hi/FOXY'); // Will throw the exception
|
||||
* </code>
|
||||
*
|
||||
* @category Net
|
||||
* @package Net_URL_Mapper
|
||||
* @version Release: @package_version@
|
||||
*/
|
||||
class Net_URL_Mapper_InvalidException extends Net_URL_Mapper_Exception
|
||||
{
|
||||
protected $path;
|
||||
protected $url;
|
||||
|
||||
public function setPath($path)
|
||||
{
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
public function getPath()
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
public function setUrl($url)
|
||||
{
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
public function getUrl()
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
}
|
||||
?>
|
142
extlib/Net/URL/Mapper/Part.php
Normal file
142
extlib/Net/URL/Mapper/Part.php
Normal file
@ -0,0 +1,142 @@
|
||||
<?php
|
||||
/**
|
||||
* URL parser and mapper
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * The names of the authors may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @category Net
|
||||
* @package Net_URL_Mapper
|
||||
* @author Bertrand Mansion <golgote@mamasam.com>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version CVS: $Id: Part.php,v 1.1 2007/03/28 10:23:04 mansion Exp $
|
||||
* @link http://pear.php.net/package/Net_URL_Mapper
|
||||
*/
|
||||
|
||||
abstract class Net_URL_Mapper_Part
|
||||
{
|
||||
protected $defaults;
|
||||
protected $rule;
|
||||
protected $public;
|
||||
protected $type;
|
||||
protected $required = false;
|
||||
|
||||
/**
|
||||
* Part name if dynamic or content, generated from path
|
||||
* @var string
|
||||
*/
|
||||
public $content;
|
||||
|
||||
const DYNAMIC = 1;
|
||||
const WILDCARD = 2;
|
||||
const FIXED = 3;
|
||||
|
||||
public function __construct($content, $path)
|
||||
{
|
||||
$this->content = $content;
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
public function setRule($rule)
|
||||
{
|
||||
$this->rule = $rule;
|
||||
}
|
||||
|
||||
abstract public function getFormat();
|
||||
|
||||
abstract public function getRule();
|
||||
|
||||
public function addSlash($str)
|
||||
{
|
||||
$str = trim($str, '/');
|
||||
if (($pos = strpos($this->path, '/')) !== false) {
|
||||
if ($pos == 0) {
|
||||
$str = '/'.$str;
|
||||
} else {
|
||||
$str .= '/';
|
||||
}
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
public function addSlashRegex($str)
|
||||
{
|
||||
$str = trim($str, '/');
|
||||
if (($pos = strpos($this->path, '/')) !== false) {
|
||||
if ($pos == 0) {
|
||||
$str = '\/'.$str;
|
||||
} else {
|
||||
$str .= '\/';
|
||||
}
|
||||
}
|
||||
if (!$this->isRequired()) {
|
||||
$str = '('.$str.'|)';
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
public function setDefaults($defaults)
|
||||
{
|
||||
$this->defaults = (string)$defaults;
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function accept($visitor, $method = null)
|
||||
{
|
||||
$args = func_get_args();
|
||||
$visitor->$method($this, $args);
|
||||
}
|
||||
|
||||
public function setRequired($required)
|
||||
{
|
||||
$this->required = $required;
|
||||
}
|
||||
|
||||
public function isRequired()
|
||||
{
|
||||
return $this->required;
|
||||
}
|
||||
|
||||
abstract public function generate($value = null);
|
||||
|
||||
public function match($value)
|
||||
{
|
||||
$rule = $this->getRule();
|
||||
return preg_match('/^'.$rule.'$/', $this->addSlash($value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
81
extlib/Net/URL/Mapper/Part/Dynamic.php
Normal file
81
extlib/Net/URL/Mapper/Part/Dynamic.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* URL parser and mapper
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * The names of the authors may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @category Net
|
||||
* @package Net_URL_Mapper
|
||||
* @author Bertrand Mansion <golgote@mamasam.com>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version CVS: $Id: Dynamic.php,v 1.1 2007/03/28 10:23:04 mansion Exp $
|
||||
* @link http://pear.php.net/package/Net_URL_Mapper
|
||||
*/
|
||||
|
||||
require_once 'Net/URL/Mapper/Part.php';
|
||||
|
||||
class Net_URL_Mapper_Part_Dynamic extends Net_URL_Mapper_Part
|
||||
{
|
||||
|
||||
public function __construct($content, $path)
|
||||
{
|
||||
$this->type = Net_URL_Mapper_Part::DYNAMIC;
|
||||
$this->setRequired(true);
|
||||
parent::__construct($content, $path);
|
||||
}
|
||||
|
||||
public function getFormat()
|
||||
{
|
||||
return $this->addSlashRegex('[^\/]+');
|
||||
}
|
||||
|
||||
public function getRule()
|
||||
{
|
||||
if (!empty($this->rule)) {
|
||||
return '(?P<'.$this->content.'>'.$this->addSlashRegex($this->rule).')';
|
||||
}
|
||||
return '(?P<'.$this->content.'>'.$this->addSlashRegex('[^\/]+').')';
|
||||
}
|
||||
|
||||
public function generate($value = null)
|
||||
{
|
||||
if (is_array($value) && isset($value[$this->content])) {
|
||||
$val = $value[$this->content];
|
||||
} elseif (!is_array($value) && !is_null($value)) {
|
||||
$val = $value;
|
||||
} else {
|
||||
$val = $this->defaults;
|
||||
}
|
||||
return $this->addSlash(urlencode($val));
|
||||
}
|
||||
}
|
||||
?>
|
70
extlib/Net/URL/Mapper/Part/Fixed.php
Normal file
70
extlib/Net/URL/Mapper/Part/Fixed.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/**
|
||||
* URL parser and mapper
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * The names of the authors may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @category Net
|
||||
* @package Net_URL_Mapper
|
||||
* @author Bertrand Mansion <golgote@mamasam.com>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version CVS: $Id: Fixed.php,v 1.1 2007/03/28 10:23:04 mansion Exp $
|
||||
* @link http://pear.php.net/package/Net_URL_Mapper
|
||||
*/
|
||||
|
||||
require_once 'Net/URL/Mapper/Part.php';
|
||||
|
||||
class Net_URL_Mapper_Part_Fixed extends Net_URL_Mapper_Part
|
||||
{
|
||||
|
||||
public function __construct($content, $path)
|
||||
{
|
||||
$this->type = Net_URL_Mapper_Part::FIXED;
|
||||
parent::__construct($content, $path);
|
||||
}
|
||||
|
||||
public function getFormat()
|
||||
{
|
||||
return $this->getRule();
|
||||
}
|
||||
|
||||
public function getRule()
|
||||
{
|
||||
return preg_quote($this->path, '/');
|
||||
}
|
||||
|
||||
public function generate($value = null)
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
}
|
||||
?>
|
80
extlib/Net/URL/Mapper/Part/Wildcard.php
Normal file
80
extlib/Net/URL/Mapper/Part/Wildcard.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* URL parser and mapper
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * The names of the authors may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @category Net
|
||||
* @package Net_URL_Mapper
|
||||
* @author Bertrand Mansion <golgote@mamasam.com>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version CVS: $Id: Wildcard.php,v 1.1 2007/03/28 10:23:04 mansion Exp $
|
||||
* @link http://pear.php.net/package/Net_URL_Mapper
|
||||
*/
|
||||
|
||||
require_once 'Net/URL/Mapper/Part.php';
|
||||
|
||||
class Net_URL_Mapper_Part_Wildcard extends Net_URL_Mapper_Part
|
||||
{
|
||||
|
||||
public function __construct($content, $path)
|
||||
{
|
||||
$this->type = Net_URL_Mapper_Part::WILDCARD;
|
||||
$this->setRequired(true);
|
||||
parent::__construct($content, $path);
|
||||
}
|
||||
|
||||
public function getFormat()
|
||||
{
|
||||
return $this->addSlashRegex('.*');;
|
||||
}
|
||||
|
||||
public function getRule()
|
||||
{
|
||||
return '(?P<'.$this->content.'>'.$this->addSlashRegex('.*').')';
|
||||
}
|
||||
|
||||
public function generate($value = null)
|
||||
{
|
||||
if (is_array($value) && isset($value[$this->content])) {
|
||||
$val = $value[$this->content];
|
||||
} elseif (!is_array($value) && !is_null($value)) {
|
||||
$val = $value;
|
||||
} else {
|
||||
$val = $this->defaults;
|
||||
}
|
||||
return $this->addSlash(str_replace(
|
||||
array('%2F', '%23'),
|
||||
array('/', '#'), urlencode($val)));
|
||||
}
|
||||
}
|
||||
?>
|
430
extlib/Net/URL/Mapper/Path.php
Normal file
430
extlib/Net/URL/Mapper/Path.php
Normal file
@ -0,0 +1,430 @@
|
||||
<?php
|
||||
/**
|
||||
* URL parser and mapper
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE:
|
||||
*
|
||||
* Copyright (c) 2006, Bertrand Mansion <golgote@mamasam.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * The names of the authors may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @category Net
|
||||
* @package Net_URL_Mapper
|
||||
* @author Bertrand Mansion <golgote@mamasam.com>
|
||||
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
||||
* @version CVS: $Id: Path.php,v 1.1 2007/03/28 10:23:04 mansion Exp $
|
||||
* @link http://pear.php.net/package/Net_URL_Mapper
|
||||
*/
|
||||
|
||||
require_once 'Net/URL.php';
|
||||
require_once 'Net/URL/Mapper/Part/Dynamic.php';
|
||||
require_once 'Net/URL/Mapper/Part/Wildcard.php';
|
||||
require_once 'Net/URL/Mapper/Part/Fixed.php';
|
||||
|
||||
class Net_URL_Mapper_Path
|
||||
{
|
||||
private $path = '';
|
||||
private $N = 0;
|
||||
public $token;
|
||||
public $value;
|
||||
private $line = 1;
|
||||
private $state = 1;
|
||||
|
||||
|
||||
protected $alias;
|
||||
protected $rules = array();
|
||||
protected $defaults = array();
|
||||
protected $parts = array();
|
||||
protected $rule;
|
||||
protected $format;
|
||||
protected $minKeys;
|
||||
protected $maxKeys;
|
||||
protected $fixed = true;
|
||||
protected $required;
|
||||
|
||||
public function __construct($path = '', $defaults = array(), $rules = array())
|
||||
{
|
||||
$this->path = '/'.trim(Net_URL::resolvePath($path), '/');
|
||||
$this->setDefaults($defaults);
|
||||
$this->setRules($rules);
|
||||
|
||||
try {
|
||||
$this->parsePath();
|
||||
} catch (Exception $e) {
|
||||
// The path could not be parsed correctly, treat it as fixed
|
||||
$this->fixed = true;
|
||||
$part = self::createPart(Net_URL_Mapper_Part::FIXED, $this->path, $this->path);
|
||||
$this->parts = array($part);
|
||||
}
|
||||
$this->getRequired();
|
||||
}
|
||||
|
||||
public function getPath()
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
protected function parsePath()
|
||||
{
|
||||
while ($this->yylex()) { }
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path alias
|
||||
* Path aliases can be used instead of full path
|
||||
* @return null|string
|
||||
*/
|
||||
public function getAlias()
|
||||
{
|
||||
return $this->alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the path name
|
||||
* @param string Set the path name
|
||||
* @see getAlias()
|
||||
*/
|
||||
public function setAlias($alias)
|
||||
{
|
||||
$this->alias = $alias;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path parts default values
|
||||
* @return null|array
|
||||
*/
|
||||
public function getDefaults()
|
||||
{
|
||||
return $this->defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the path parts default values
|
||||
* @param array Associative array with format partname => value
|
||||
*/
|
||||
public function setDefaults($defaults)
|
||||
{
|
||||
if (is_array($defaults)) {
|
||||
$this->defaults = $defaults;
|
||||
} else {
|
||||
$this->defaults = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the path parts default values
|
||||
* @param array Associative array with format partname => value
|
||||
*/
|
||||
public function setRules($rules)
|
||||
{
|
||||
if (is_array($rules)) {
|
||||
$this->rules = $rules;
|
||||
} else {
|
||||
$this->rules = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the regular expression used to match this path
|
||||
* @return string PERL Regular expression
|
||||
*/
|
||||
public function getRule()
|
||||
{
|
||||
if (is_null($this->rule)) {
|
||||
$this->rule = '/^';
|
||||
foreach ($this->parts as $path => $part) {
|
||||
$this->rule .= $part->getRule();
|
||||
}
|
||||
$this->rule .= '$/';
|
||||
}
|
||||
return $this->rule;
|
||||
}
|
||||
|
||||
public function getFormat()
|
||||
{
|
||||
if (is_null($this->format)) {
|
||||
$this->format = '/^';
|
||||
foreach ($this->parts as $path => $part) {
|
||||
$this->format .= $part->getFormat();
|
||||
}
|
||||
$this->format .= '$/';
|
||||
}
|
||||
return $this->format;
|
||||
}
|
||||
|
||||
protected function addPart($part)
|
||||
{
|
||||
if (array_key_exists($part->content, $this->defaults)) {
|
||||
$part->setRequired(false);
|
||||
$part->setDefaults($this->defaults[$part->content]);
|
||||
}
|
||||
if (isset($this->rules[$part->content])) {
|
||||
$part->setRule($this->rules[$part->content]);
|
||||
}
|
||||
$this->rule = null;
|
||||
if ($part->getType() != Net_URL_Mapper_Part::FIXED) {
|
||||
$this->fixed = false;
|
||||
$this->parts[$part->content] = $part;
|
||||
} else {
|
||||
$this->parts[] = $part;
|
||||
}
|
||||
return $part;
|
||||
}
|
||||
|
||||
public static function createPart($type, $content, $path)
|
||||
{
|
||||
switch ($type) {
|
||||
case Net_URL_Mapper_Part::DYNAMIC:
|
||||
return new Net_URL_Mapper_Part_Dynamic($content, $path);
|
||||
break;
|
||||
case Net_URL_Mapper_Part::WILDCARD:
|
||||
return new Net_URL_Mapper_Part_Wildcard($content, $path);
|
||||
break;
|
||||
default:
|
||||
return new Net_URL_Mapper_Part_Fixed($content, $path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the path contains the given part by name
|
||||
* If value parameter is given, the part also checks if the
|
||||
* given value conforms to the part rule.
|
||||
* @param string Part name
|
||||
* @param mixed The value to check against
|
||||
*/
|
||||
public function hasKey($partName, $value = null)
|
||||
{
|
||||
if (array_key_exists($partName, $this->parts)) {
|
||||
if (!is_null($value) && $value !== false) {
|
||||
return $this->parts[$partName]->match($value);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} elseif (array_key_exists($partName, $this->defaults) &&
|
||||
$value == $this->defaults[$partName]) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function generate($values = array(), $qstring = array(), $anchor = '')
|
||||
{
|
||||
$path = '';
|
||||
foreach ($this->parts as $part) {
|
||||
$path .= $part->generate($values);
|
||||
}
|
||||
$path = '/'.trim(Net_URL::resolvePath($path), '/');
|
||||
if (!empty($qstring)) {
|
||||
$path .= '?'.http_build_query($qstring);
|
||||
}
|
||||
if (!empty($anchor)) {
|
||||
$path .= '#'.ltrim($anchor, '#');
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
public function getRequired()
|
||||
{
|
||||
if (!isset($this->required)) {
|
||||
$req = array();
|
||||
foreach ($this->parts as $part) {
|
||||
if ($part->isRequired()) {
|
||||
$req[] = $part->content;
|
||||
}
|
||||
}
|
||||
$this->required = $req;
|
||||
}
|
||||
return $this->required;
|
||||
}
|
||||
|
||||
public function getMaxKeys()
|
||||
{
|
||||
if (is_null($this->maxKeys)) {
|
||||
$this->maxKeys = count($this->required);
|
||||
$this->maxKeys += count($this->defaults);
|
||||
}
|
||||
return $this->maxKeys;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private $_yy_state = 1;
|
||||
private $_yy_stack = array();
|
||||
|
||||
function yylex()
|
||||
{
|
||||
return $this->{'yylex' . $this->_yy_state}();
|
||||
}
|
||||
|
||||
function yypushstate($state)
|
||||
{
|
||||
array_push($this->_yy_stack, $this->_yy_state);
|
||||
$this->_yy_state = $state;
|
||||
}
|
||||
|
||||
function yypopstate()
|
||||
{
|
||||
$this->_yy_state = array_pop($this->_yy_stack);
|
||||
}
|
||||
|
||||
function yybegin($state)
|
||||
{
|
||||
$this->_yy_state = $state;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function yylex1()
|
||||
{
|
||||
$tokenMap = array (
|
||||
1 => 1,
|
||||
3 => 1,
|
||||
5 => 1,
|
||||
7 => 1,
|
||||
9 => 1,
|
||||
);
|
||||
if ($this->N >= strlen($this->path)) {
|
||||
return false; // end of input
|
||||
}
|
||||
$yy_global_pattern = "/^(\/?:\/?\\(([a-zA-Z0-9_]+)\\))|^(\/?\\*\/?\\(([a-zA-Z0-9_]+)\\))|^(\/?:([a-zA-Z0-9_]+))|^(\/?\\*([a-zA-Z0-9_]+))|^(\/?([^\/:*]+))/";
|
||||
|
||||
do {
|
||||
if (preg_match($yy_global_pattern, substr($this->path, $this->N), $yymatches)) {
|
||||
$yysubmatches = $yymatches;
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
if (!count($yymatches)) {
|
||||
throw new Exception('Error: lexing failed because a rule matched' .
|
||||
'an empty string. Input "' . substr($this->path,
|
||||
$this->N, 5) . '... state START');
|
||||
}
|
||||
next($yymatches); // skip global match
|
||||
$this->token = key($yymatches); // token number
|
||||
if ($tokenMap[$this->token]) {
|
||||
// extract sub-patterns for passing to lex function
|
||||
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
|
||||
$tokenMap[$this->token]);
|
||||
} else {
|
||||
$yysubmatches = array();
|
||||
}
|
||||
$this->value = current($yymatches); // token value
|
||||
$r = $this->{'yy_r1_' . $this->token}($yysubmatches);
|
||||
if ($r === null) {
|
||||
$this->N += strlen($this->value);
|
||||
$this->line += substr_count("\n", $this->value);
|
||||
// accept this token
|
||||
return true;
|
||||
} elseif ($r === true) {
|
||||
// we have changed state
|
||||
// process this token in the new state
|
||||
return $this->yylex();
|
||||
} elseif ($r === false) {
|
||||
$this->N += strlen($this->value);
|
||||
$this->line += substr_count("\n", $this->value);
|
||||
if ($this->N >= strlen($this->path)) {
|
||||
return false; // end of input
|
||||
}
|
||||
// skip this token
|
||||
continue;
|
||||
} else { $yy_yymore_patterns = array(
|
||||
1 => "^(\/?\\*\/?\\(([a-zA-Z0-9_]+)\\))|^(\/?:([a-zA-Z0-9_]+))|^(\/?\\*([a-zA-Z0-9_]+))|^(\/?([^\/:*]+))",
|
||||
3 => "^(\/?:([a-zA-Z0-9_]+))|^(\/?\\*([a-zA-Z0-9_]+))|^(\/?([^\/:*]+))",
|
||||
5 => "^(\/?\\*([a-zA-Z0-9_]+))|^(\/?([^\/:*]+))",
|
||||
7 => "^(\/?([^\/:*]+))",
|
||||
9 => "",
|
||||
);
|
||||
|
||||
// yymore is needed
|
||||
do {
|
||||
if (!strlen($yy_yymore_patterns[$this->token])) {
|
||||
throw new Exception('cannot do yymore for the last token');
|
||||
}
|
||||
if (preg_match($yy_yymore_patterns[$this->token],
|
||||
substr($this->path, $this->N), $yymatches)) {
|
||||
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
|
||||
next($yymatches); // skip global match
|
||||
$this->token = key($yymatches); // token number
|
||||
$this->value = current($yymatches); // token value
|
||||
$this->line = substr_count("\n", $this->value);
|
||||
}
|
||||
} while ($this->{'yy_r1_' . $this->token}() !== null);
|
||||
// accept
|
||||
$this->N += strlen($this->value);
|
||||
$this->line += substr_count("\n", $this->value);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
throw new Exception('Unexpected input at line' . $this->line .
|
||||
': ' . $this->path[$this->N]);
|
||||
}
|
||||
break;
|
||||
} while (true);
|
||||
} // end function
|
||||
|
||||
|
||||
const START = 1;
|
||||
function yy_r1_1($yy_subpatterns)
|
||||
{
|
||||
|
||||
$c = $yy_subpatterns[0];
|
||||
$part = self::createPart(Net_URL_Mapper_Part::DYNAMIC, $c, $this->value);
|
||||
$this->addPart($part);
|
||||
}
|
||||
function yy_r1_3($yy_subpatterns)
|
||||
{
|
||||
|
||||
$c = $yy_subpatterns[0];
|
||||
$part = self::createPart(Net_URL_Mapper_Part::WILDCARD, $c, $this->value);
|
||||
$this->addPart($part);
|
||||
}
|
||||
function yy_r1_5($yy_subpatterns)
|
||||
{
|
||||
|
||||
$c = $yy_subpatterns[0];
|
||||
$part = self::createPart(Net_URL_Mapper_Part::DYNAMIC, $c, $this->value);
|
||||
$this->addPart($part);
|
||||
}
|
||||
function yy_r1_7($yy_subpatterns)
|
||||
{
|
||||
|
||||
$c = $yy_subpatterns[0];
|
||||
$part = self::createPart(Net_URL_Mapper_Part::WILDCARD, $c, $this->value);
|
||||
$this->addPart($part);
|
||||
}
|
||||
function yy_r1_9($yy_subpatterns)
|
||||
{
|
||||
|
||||
$c = $yy_subpatterns[0];
|
||||
$part = self::createPart(Net_URL_Mapper_Part::FIXED, $c, $this->value);
|
||||
$this->addPart($part);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
162
htaccess.sample
162
htaccess.sample
@ -4,165 +4,9 @@ RewriteEngine On
|
||||
|
||||
RewriteBase /mublog/
|
||||
|
||||
RewriteRule ^$ index.php?action=public [L,QSA]
|
||||
RewriteRule ^rss$ index.php?action=publicrss [L,QSA]
|
||||
RewriteRule ^xrds$ index.php?action=publicxrds [L,QSA]
|
||||
RewriteRule ^featuredrss$ index.php?action=featuredrss [L,QSA]
|
||||
RewriteRule ^favoritedrss$ index.php?action=favoritedrss [L,QSA]
|
||||
RewriteRule ^opensearch/people$ index.php?action=opensearch&type=people [L,QSA]
|
||||
RewriteRule ^opensearch/notice$ index.php?action=opensearch&type=notice [L,QSA]
|
||||
|
||||
RewriteRule ^doc/about$ index.php?action=doc&title=about [L,QSA]
|
||||
RewriteRule ^doc/contact$ index.php?action=doc&title=contact [L,QSA]
|
||||
RewriteRule ^doc/faq$ index.php?action=doc&title=faq [L,QSA]
|
||||
RewriteRule ^doc/help$ index.php?action=doc&title=help [L,QSA]
|
||||
RewriteRule ^doc/im$ index.php?action=doc&title=im [L,QSA]
|
||||
RewriteRule ^doc/openid$ index.php?action=doc&title=openid [L,QSA]
|
||||
RewriteRule ^doc/openmublog$ index.php?action=doc&title=openmublog [L,QSA]
|
||||
RewriteRule ^doc/privacy$ index.php?action=doc&title=privacy [L,QSA]
|
||||
RewriteRule ^doc/source$ index.php?action=doc&title=source [L,QSA]
|
||||
RewriteRule ^doc/tags$ index.php?action=doc&title=tags [L,QSA]
|
||||
RewriteRule ^doc/groups$ index.php?action=doc&title=groups [L,QSA]
|
||||
RewriteRule ^doc/sms$ index.php?action=doc&title=sms [L,QSA]
|
||||
|
||||
RewriteRule ^facebook/$ index.php?action=facebookhome [L,QSA]
|
||||
RewriteRule ^facebook/index.php$ index.php?action=facebookhome [L,QSA]
|
||||
RewriteRule ^facebook/settings.php$ index.php?action=facebooksettings [L,QSA]
|
||||
RewriteRule ^facebook/invite.php$ index.php?action=facebookinvite [L,QSA]
|
||||
RewriteRule ^facebook/remove$ index.php?action=facebookremove [L,QSA]
|
||||
|
||||
RewriteRule ^main/login$ index.php?action=login [L,QSA]
|
||||
RewriteRule ^main/logout$ index.php?action=logout [L,QSA]
|
||||
RewriteRule ^main/register/(.*)$ index.php?action=register&code=$1 [L,QSA]
|
||||
RewriteRule ^main/register$ index.php?action=register [L,QSA]
|
||||
RewriteRule ^main/openid$ index.php?action=openidlogin [L,QSA]
|
||||
RewriteRule ^main/remote$ index.php?action=remotesubscribe [L,QSA]
|
||||
|
||||
RewriteRule ^main/subscribe$ index.php?action=subscribe [L,QSA]
|
||||
RewriteRule ^main/unsubscribe$ index.php?action=unsubscribe [L,QSA]
|
||||
RewriteRule ^main/confirmaddress$ index.php?action=confirmaddress [L,QSA]
|
||||
RewriteRule ^main/confirmaddress/(.*)$ index.php?action=confirmaddress&code=$1 [L,QSA]
|
||||
RewriteRule ^main/recoverpassword$ index.php?action=recoverpassword [L,QSA]
|
||||
RewriteRule ^main/recoverpassword/(.*)$ index.php?action=recoverpassword&code=$1 [L,QSA]
|
||||
RewriteRule ^main/invite$ index.php?action=invite [L,QSA]
|
||||
|
||||
RewriteRule ^main/favor$ index.php?action=favor [L,QSA]
|
||||
RewriteRule ^main/disfavor$ index.php?action=disfavor [L,QSA]
|
||||
|
||||
RewriteRule ^main/sup$ index.php?action=sup [L,QSA]
|
||||
|
||||
RewriteRule ^main/tagother$ index.php?action=tagother [L,QSA]
|
||||
|
||||
RewriteRule ^main/block$ index.php?action=block [L,QSA]
|
||||
|
||||
RewriteRule ^settings/profile$ index.php?action=profilesettings [L,QSA]
|
||||
RewriteRule ^settings/avatar$ index.php?action=avatarsettings [L,QSA]
|
||||
RewriteRule ^settings/password$ index.php?action=passwordsettings [L,QSA]
|
||||
RewriteRule ^settings/openid$ index.php?action=openidsettings [L,QSA]
|
||||
RewriteRule ^settings/im$ index.php?action=imsettings [L,QSA]
|
||||
RewriteRule ^settings/email$ index.php?action=emailsettings [L,QSA]
|
||||
RewriteRule ^settings/sms$ index.php?action=smssettings [L,QSA]
|
||||
RewriteRule ^settings/twitter$ index.php?action=twittersettings [L,QSA]
|
||||
RewriteRule ^settings/other$ index.php?action=othersettings [L,QSA]
|
||||
|
||||
RewriteRule ^search/group$ index.php?action=groupsearch [L,QSA]
|
||||
RewriteRule ^search/people$ index.php?action=peoplesearch [L,QSA]
|
||||
RewriteRule ^search/notice$ index.php?action=noticesearch [L,QSA]
|
||||
RewriteRule ^search/notice/rss$ index.php?action=noticesearchrss [L,QSA]
|
||||
|
||||
RewriteRule ^notice/new$ index.php?action=newnotice [L,QSA]
|
||||
RewriteRule ^notice/(\d+)$ index.php?action=shownotice¬ice=$1 [L,QSA]
|
||||
RewriteRule ^notice/delete/((\d+))?$ index.php?action=deletenotice¬ice=$2 [L,QSA]
|
||||
RewriteRule ^notice/delete$ index.php?action=deletenotice [L,QSA]
|
||||
|
||||
RewriteRule ^message/new$ index.php?action=newmessage [L,QSA]
|
||||
RewriteRule ^message/(\d+)$ index.php?action=showmessage&message=$1 [L,QSA]
|
||||
|
||||
RewriteRule ^user/(\d+)$ index.php?action=userbyid&id=$1 [L,QSA]
|
||||
|
||||
RewriteRule ^tags/?$ index.php?action=publictagcloud [L,QSA]
|
||||
RewriteRule ^tag/([a-zA-Z0-9]+)/rss$ index.php?action=tagrss&tag=$1 [L,QSA]
|
||||
RewriteRule ^tag(/(.*))?$ index.php?action=tag&tag=$2 [L,QSA]
|
||||
|
||||
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/([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]
|
||||
|
||||
# Twitter-compatible API rewrites
|
||||
# XXX: Surely these can be refactored a little -- Zach
|
||||
RewriteRule ^api/statuses/public_timeline(.*)$ index.php?action=api&apiaction=statuses&method=public_timeline$1 [L,QSA]
|
||||
RewriteRule ^api/statuses/friends_timeline(.*)$ index.php?action=api&apiaction=statuses&method=friends_timeline$1 [L,QSA]
|
||||
RewriteRule ^api/statuses/user_timeline/(.*)$ index.php?action=api&apiaction=statuses&method=user_timeline&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/statuses/user_timeline(.*)$ index.php?action=api&apiaction=statuses&method=user_timeline$1 [L,QSA]
|
||||
RewriteRule ^api/statuses/show/(.*)$ index.php?action=api&apiaction=statuses&method=show&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/statuses/update(.*)$ index.php?action=api&apiaction=statuses&method=update$1 [L,QSA]
|
||||
RewriteRule ^api/statuses/replies(.*)$ index.php?action=api&apiaction=statuses&method=replies&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/statuses/destroy/(.*)$ index.php?action=api&apiaction=statuses&method=destroy&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/statuses/friends/(.*)$ index.php?action=api&apiaction=statuses&method=friends&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/statuses/friends(.*)$ index.php?action=api&apiaction=statuses&method=friends$1 [L,QSA]
|
||||
RewriteRule ^api/statuses/followers/(.*)$ index.php?action=api&apiaction=statuses&method=followers&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/statuses/followers(.*)$ index.php?action=api&apiaction=statuses&method=followers$1 [L,QSA]
|
||||
RewriteRule ^api/statuses/featured(.*)$ index.php?action=api&apiaction=statuses&method=featured$1 [L,QSA]
|
||||
RewriteRule ^api/users/show/(.*)$ index.php?action=api&apiaction=users&method=show&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/users/show(.*)$ index.php?action=api&apiaction=users&method=show$1 [L,QSA]
|
||||
RewriteRule ^api/direct_messages/sent(.*)$ index.php?action=api&apiaction=direct_messages&method=sent$1 [L,QSA]
|
||||
RewriteRule ^api/direct_messages/destroy/(.*)$ index.php?action=api&apiaction=direct_messages&method=destroy&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/direct_messages/new(.*)$ index.php?action=api&apiaction=direct_messages&method=create$1 [L,QSA]
|
||||
RewriteRule ^api/direct_messages(.*)$ index.php?action=api&apiaction=direct_messages&method=direct_messages$1 [L,QSA]
|
||||
RewriteRule ^api/friendships/create/(.*)$ index.php?action=api&apiaction=friendships&method=create&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/friendships/destroy/(.*)$ index.php?action=api&apiaction=friendships&method=destroy&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/friendships/exists(.*)$ index.php?action=api&apiaction=friendships&method=exists$1 [L,QSA]
|
||||
RewriteRule ^api/account/verify_credentials(.*)$ index.php?action=api&apiaction=account&method=verify_credentials$1 [L,QSA]
|
||||
RewriteRule ^api/account/end_session$ index.php?action=api&apiaction=account&method=end_session$1 [L,QSA]
|
||||
RewriteRule ^api/account/update_location(.*)$ index.php?action=api&apiaction=account&method=update_location$1 [L,QSA]
|
||||
RewriteRule ^api/account/update_delivery_device(.*)$ index.php?action=api&apiaction=account&method=update_delivery_device$1 [L,QSA]
|
||||
RewriteRule ^api/account/rate_limit_status(.*)$ index.php?action=api&apiaction=account&method=rate_limit_status$1 [L,QSA]
|
||||
RewriteRule ^api/favorites/create/(.*)$ index.php?action=api&apiaction=favorites&method=create&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/favorites/destroy/(.*)$ index.php?action=api&apiaction=favorites&method=destroy&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/favorites/(.*)$ index.php?action=api&apiaction=favorites&method=favorites&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/favorites(.*)$ index.php?action=api&apiaction=favorites&method=favorites$1 [L,QSA]
|
||||
RewriteRule ^api/notifications/follow/(.*)$ index.php?action=api&apiaction=notifications&method=follow&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/notifications/leave/(.*)$ index.php?action=api&apiaction=notifications&method=leave&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/blocks/create/(.*)$ index.php?action=api&apiaction=blocks&method=create&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/blocks/destroy/(.*)$ index.php?action=api&apiaction=blocks&method=destroy&argument=$1 [L,QSA]
|
||||
RewriteRule ^api/help/(.*)$ index.php?action=api&apiaction=help&method=$1 [L,QSA]
|
||||
RewriteRule ^api/laconica/version(.*)$ index.php?action=api&apiaction=laconica&method=version$1 [L,QSA]
|
||||
RewriteRule ^api/laconica/config(.*)$ index.php?action=api&apiaction=laconica&method=config$1 [L,QSA]
|
||||
RewriteRule ^api/laconica/wadl\.xml$ index.php?action=api&apiaction=laconica&method=wadl.xml [L,QSA]
|
||||
|
||||
RewriteRule ^(\w+)/subscriptions$ index.php?action=subscriptions&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/subscriptions/([a-zA-Z0-9]+)$ index.php?action=subscriptions&nickname=$1&tag=$2 [L,QSA]
|
||||
RewriteRule ^(\w+)/subscribers/([a-zA-Z0-9]+)$ index.php?action=subscribers&nickname=$1&tag=$2 [L,QSA]
|
||||
RewriteRule ^(\w+)/subscribers$ index.php?action=subscribers&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/nudge$ index.php?action=nudge&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/xrds$ index.php?action=xrds&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/rss$ index.php?action=userrss&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/all$ index.php?action=all&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/all/rss$ index.php?action=allrss&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/foaf$ index.php?action=foaf&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/replies$ index.php?action=replies&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/replies/rss$ index.php?action=repliesrss&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/avatar/(original|96|48|24)$ index.php?action=avatarbynickname&nickname=$1&size=$2 [L,QSA]
|
||||
RewriteRule ^(\w+)/favorites$ index.php?action=showfavorites&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/favorites/rss$ index.php?action=favoritesrss&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/inbox$ index.php?action=inbox&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/outbox$ index.php?action=outbox&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/microsummary$ index.php?action=microsummary&nickname=$1 [L,QSA]
|
||||
RewriteRule ^(\w+)/groups$ index.php?action=usergroups&nickname=$1 [L,QSA]
|
||||
|
||||
RewriteRule ^(\w+)$ index.php?action=showstream&nickname=$1 [L,QSA]
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule (.*) index.php?p=$1 [L,QSA]
|
||||
|
||||
<FilesMatch "\.(ini)">
|
||||
Order allow,deny
|
||||
|
171
index.php
171
index.php
@ -22,70 +22,143 @@ define('LACONICA', true);
|
||||
|
||||
require_once INSTALLDIR . '/lib/common.php';
|
||||
|
||||
// get and cache current user
|
||||
$user = null;
|
||||
$action = null;
|
||||
|
||||
$user = common_current_user();
|
||||
|
||||
// initialize language env
|
||||
|
||||
common_init_language();
|
||||
|
||||
$action = $_REQUEST['action'];
|
||||
|
||||
if (!$action || !preg_match('/^[a-zA-Z0-9_-]*$/', $action)) {
|
||||
common_redirect(common_local_url('public'));
|
||||
function getPath($req)
|
||||
{
|
||||
if ((common_config('site', 'fancy') || !array_key_exists('PATH_INFO', $_SERVER))
|
||||
&& array_key_exists('p', $req)) {
|
||||
return $req['p'];
|
||||
} else if (array_key_exists('PATH_INFO', $_SERVER)) {
|
||||
return $_SERVER['PATH_INFO'];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// If the site is private, and they're not on one of the "public"
|
||||
// parts of the site, redirect to login
|
||||
function handleError($error)
|
||||
{
|
||||
if ($error->getCode() == DB_DATAOBJECT_ERROR_NODATA) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$user && common_config('site', 'private') &&
|
||||
!in_array($action, array('login', 'openidlogin', 'finishopenidlogin',
|
||||
'recoverpassword', 'api', 'doc', 'register'))) {
|
||||
common_redirect(common_local_url('login'));
|
||||
$logmsg = "PEAR error: " . $error->getMessage();
|
||||
if(common_config('site', 'logdebug')) {
|
||||
$logmsg .= " : ". $error->getDebugInfo();
|
||||
}
|
||||
common_log(LOG_ERR, $logmsg);
|
||||
$msg = sprintf(_('The database for %s isn\'t responding correctly, '.
|
||||
'so the site won\'t work properly. '.
|
||||
'The site admins probably know about the problem, '.
|
||||
'but you can contact them at %s to make sure. '.
|
||||
'Otherwise, wait a few minutes and try again.'),
|
||||
common_config('site', 'name'),
|
||||
common_config('site', 'email'));
|
||||
|
||||
$dac = new DBErrorAction($msg, 500);
|
||||
$dac->showPage();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
$actionfile = INSTALLDIR."/actions/$action.php";
|
||||
function main()
|
||||
{
|
||||
global $user, $action;
|
||||
|
||||
if (!file_exists($actionfile)) {
|
||||
$cac = new ClientErrorAction(_('Unknown action'), 404);
|
||||
$cac->showPage();
|
||||
} else {
|
||||
if (!_have_config()) {
|
||||
$msg = sprintf(_("No configuration file found. Try running ".
|
||||
"the installation program first."));
|
||||
$sac = new ServerErrorAction($msg);
|
||||
$sac->showPage();
|
||||
return;
|
||||
}
|
||||
|
||||
include_once $actionfile;
|
||||
// For database errors
|
||||
|
||||
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'handleError');
|
||||
|
||||
// XXX: we need a little more structure in this script
|
||||
|
||||
// get and cache current user
|
||||
|
||||
$user = common_current_user();
|
||||
|
||||
// initialize language env
|
||||
|
||||
common_init_language();
|
||||
|
||||
$path = getPath($_REQUEST);
|
||||
|
||||
$r = Router::get();
|
||||
|
||||
$args = $r->map($path);
|
||||
|
||||
if (!$args) {
|
||||
$cac = new ClientErrorAction(_('Unknown page'), 404);
|
||||
$cac->showPage();
|
||||
return;
|
||||
}
|
||||
|
||||
$args = array_merge($args, $_REQUEST);
|
||||
|
||||
$action = $args['action'];
|
||||
|
||||
if (!$action || !preg_match('/^[a-zA-Z0-9_-]*$/', $action)) {
|
||||
common_redirect(common_local_url('public'));
|
||||
return;
|
||||
}
|
||||
|
||||
// If the site is private, and they're not on one of the "public"
|
||||
// parts of the site, redirect to login
|
||||
|
||||
if (!$user && common_config('site', 'private') &&
|
||||
!in_array($action, array('login', 'openidlogin', 'finishopenidlogin',
|
||||
'recoverpassword', 'api', 'doc', 'register'))) {
|
||||
common_redirect(common_local_url('login'));
|
||||
return;
|
||||
}
|
||||
|
||||
$action_class = ucfirst($action).'Action';
|
||||
|
||||
$action_obj = new $action_class();
|
||||
|
||||
if ($config['db']['mirror'] && $action_obj->isReadOnly()) {
|
||||
if (is_array($config['db']['mirror'])) {
|
||||
// "load balancing", ha ha
|
||||
$k = array_rand($config['db']['mirror']);
|
||||
|
||||
$mirror = $config['db']['mirror'][$k];
|
||||
} else {
|
||||
$mirror = $config['db']['mirror'];
|
||||
}
|
||||
$config['db']['database'] = $mirror;
|
||||
}
|
||||
|
||||
try {
|
||||
if ($action_obj->prepare($_REQUEST)) {
|
||||
$action_obj->handle($_REQUEST);
|
||||
}
|
||||
} catch (ClientException $cex) {
|
||||
$cac = new ClientErrorAction($cex->getMessage(), $cex->getCode());
|
||||
if (!class_exists($action_class)) {
|
||||
$cac = new ClientErrorAction(_('Unknown action'), 404);
|
||||
$cac->showPage();
|
||||
} catch (ServerException $sex) { // snort snort guffaw
|
||||
$sac = new ServerErrorAction($sex->getMessage(), $sex->getCode());
|
||||
$sac->showPage();
|
||||
} catch (Exception $ex) {
|
||||
$sac = new ServerErrorAction($ex->getMessage());
|
||||
$sac->showPage();
|
||||
} else {
|
||||
$action_obj = new $action_class();
|
||||
|
||||
// XXX: find somewhere for this little block to live
|
||||
|
||||
if (common_config('db', 'mirror') && $action_obj->isReadOnly()) {
|
||||
if (is_array(common_config('db', 'mirror'))) {
|
||||
// "load balancing", ha ha
|
||||
$k = array_rand($config['db']['mirror']);
|
||||
|
||||
$mirror = $config['db']['mirror'][$k];
|
||||
} else {
|
||||
$mirror = $config['db']['mirror'];
|
||||
}
|
||||
$config['db']['database'] = $mirror;
|
||||
}
|
||||
|
||||
try {
|
||||
if ($action_obj->prepare($args)) {
|
||||
$action_obj->handle($args);
|
||||
}
|
||||
} catch (ClientException $cex) {
|
||||
$cac = new ClientErrorAction($cex->getMessage(), $cex->getCode());
|
||||
$cac->showPage();
|
||||
} catch (ServerException $sex) { // snort snort guffaw
|
||||
$sac = new ServerErrorAction($sex->getMessage(), $sex->getCode());
|
||||
$sac->showPage();
|
||||
} catch (Exception $ex) {
|
||||
$sac = new ServerErrorAction($ex->getMessage());
|
||||
$sac->showPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
// XXX: cleanup exit() calls or add an exit handler so
|
||||
// this always gets called
|
||||
|
||||
|
255
install.php
Normal file
255
install.php
Normal file
@ -0,0 +1,255 @@
|
||||
<?
|
||||
define('INSTALLDIR', dirname(__FILE__));
|
||||
|
||||
function main()
|
||||
{
|
||||
if (!checkPrereqs())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
handlePost();
|
||||
} else {
|
||||
showForm();
|
||||
}
|
||||
}
|
||||
|
||||
function checkPrereqs()
|
||||
{
|
||||
if (file_exists(INSTALLDIR.'/config.php')) {
|
||||
?><p class="error">Config file "config.php" already exists.</p>
|
||||
<?
|
||||
return false;
|
||||
}
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.0.0', '<')) {
|
||||
?><p class="error">Require PHP version 5 or greater.</p><?
|
||||
return false;
|
||||
}
|
||||
|
||||
$reqs = array('gd', 'mysql', 'curl',
|
||||
'xmlwriter', 'mbstring',
|
||||
'gettext');
|
||||
|
||||
foreach ($reqs as $req) {
|
||||
if (!checkExtension($req)) {
|
||||
?><p class="error">Cannot load required extension "<?= $req ?>".</p><?
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_writable(INSTALLDIR)) {
|
||||
?><p class="error">Cannot write config file to "<?= INSTALLDIR ?>".</p>
|
||||
<p>On your server, try this command:</p>
|
||||
<blockquote>chmod a+w <?= INSTALLDIR ?></blockquote>
|
||||
<?
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_writable(INSTALLDIR.'/avatar/')) {
|
||||
?><p class="error">Cannot write avatar directory "<?= INSTALLDIR ?>/avatar/".</p>
|
||||
<p>On your server, try this command:</p>
|
||||
<blockquote>chmod a+w <?= INSTALLDIR ?>/avatar/</blockquote>
|
||||
<?
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function checkExtension($name)
|
||||
{
|
||||
if (!extension_loaded($name)) {
|
||||
if (!dl($name.'.so')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function showForm()
|
||||
{
|
||||
?>
|
||||
<p>Enter your database connection information below to initialize the database.</p>
|
||||
<form method='post' action='install.php'>
|
||||
<fieldset>
|
||||
<ul class='form_data'>
|
||||
<li>
|
||||
<label for='sitename'>Site name</label>
|
||||
<input type='text' id='sitename' name='sitename' />
|
||||
<p>The name of your site</p>
|
||||
</li>
|
||||
<li>
|
||||
<li>
|
||||
<label for='host'>Hostname</label>
|
||||
<input type='text' id='host' name='host' />
|
||||
<p>Database hostname</p>
|
||||
</li>
|
||||
<li>
|
||||
<label for='host'>Database</label>
|
||||
<input type='text' id='database' name='database' />
|
||||
<p>Database name</p>
|
||||
</li>
|
||||
<li>
|
||||
<label for='username'>Username</label>
|
||||
<input type='text' id='username' name='username' />
|
||||
<p>Database username</p>
|
||||
</li>
|
||||
<li>
|
||||
<label for='password'>Password</label>
|
||||
<input type='password' id='password' name='password' />
|
||||
<p>Database password</p>
|
||||
</li>
|
||||
</ul>
|
||||
<input type='submit' name='submit' value='Submit'>
|
||||
</fieldset>
|
||||
</form>
|
||||
<?
|
||||
}
|
||||
|
||||
function updateStatus($status, $error=false)
|
||||
{
|
||||
?>
|
||||
<li>
|
||||
<?
|
||||
print $status;
|
||||
?>
|
||||
</li>
|
||||
<?
|
||||
}
|
||||
|
||||
function handlePost()
|
||||
{
|
||||
?>
|
||||
<ul>
|
||||
<?
|
||||
$host = $_POST['host'];
|
||||
$database = $_POST['database'];
|
||||
$username = $_POST['username'];
|
||||
$password = $_POST['password'];
|
||||
$sitename = $_POST['sitename'];
|
||||
|
||||
if (empty($host)) {
|
||||
updateStatus("No hostname specified.", true);
|
||||
showForm();
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($database)) {
|
||||
updateStatus("No database specified.", true);
|
||||
showForm();
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($username)) {
|
||||
updateStatus("No username specified.", true);
|
||||
showForm();
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($password)) {
|
||||
updateStatus("No password specified.", true);
|
||||
showForm();
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($sitename)) {
|
||||
updateStatus("No sitename specified.", true);
|
||||
showForm();
|
||||
return;
|
||||
}
|
||||
|
||||
updateStatus("Starting installation...");
|
||||
updateStatus("Checking database...");
|
||||
$conn = mysql_connect($host, $username, $password);
|
||||
if (!$conn) {
|
||||
updateStatus("Can't connect to server '$host' as '$username'.", true);
|
||||
showForm();
|
||||
return;
|
||||
}
|
||||
updateStatus("Changing to database...");
|
||||
$res = mysql_select_db($database, $conn);
|
||||
if (!$res) {
|
||||
updateStatus("Can't change to database.", true);
|
||||
showForm();
|
||||
return;
|
||||
}
|
||||
updateStatus("Running database script...");
|
||||
$res = runDbScript(INSTALLDIR.'/db/laconica.sql', $conn);
|
||||
if ($res === false) {
|
||||
updateStatus("Can't run database script.", true);
|
||||
showForm();
|
||||
return;
|
||||
}
|
||||
foreach (array('sms_carrier' => 'SMS carrier',
|
||||
'notice_source' => 'notice source',
|
||||
'foreign_services' => 'foreign service')
|
||||
as $scr => $name) {
|
||||
updateStatus(sprintf("Adding %s data to database...", $name));
|
||||
$res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn);
|
||||
if ($res === false) {
|
||||
updateStatus(sprintf("Can't run %d script.", $name), true);
|
||||
showForm();
|
||||
return;
|
||||
}
|
||||
}
|
||||
updateStatus("Writing config file...");
|
||||
$sqlUrl = "mysqli://$username:$password@$host/$database";
|
||||
$res = writeConf($sitename, $sqlUrl);
|
||||
if (!$res) {
|
||||
updateStatus("Can't write config file.", true);
|
||||
showForm();
|
||||
return;
|
||||
}
|
||||
updateStatus("Done!");
|
||||
?>
|
||||
</ul>
|
||||
<?
|
||||
}
|
||||
|
||||
function writeConf($sitename, $sqlUrl)
|
||||
{
|
||||
$res = file_put_contents(INSTALLDIR.'/config.php',
|
||||
"<?\n".
|
||||
"\$config['site']['name'] = \"$sitename\";\n\n".
|
||||
"\$config['db']['database'] = \"$sqlUrl\";\n\n");
|
||||
return $res;
|
||||
}
|
||||
|
||||
function runDbScript($filename, $conn)
|
||||
{
|
||||
$sql = trim(file_get_contents($filename));
|
||||
$stmts = explode(';', $sql);
|
||||
foreach ($stmts as $stmt) {
|
||||
$stmt = trim($stmt);
|
||||
if (!mb_strlen($stmt)) {
|
||||
continue;
|
||||
}
|
||||
$res = mysql_query($stmt, $conn);
|
||||
if ($res === false) {
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
?>
|
||||
<html>
|
||||
<head>
|
||||
<title>Install Laconica</title>
|
||||
<link rel="stylesheet" type="text/css" href="theme/base/css/display.css?version=0.7.1" media="screen, projection, tv"/>
|
||||
<link rel="stylesheet" type="text/css" href="theme/base/css/modal.css?version=0.7.1" media="screen, projection, tv"/>
|
||||
<link rel="stylesheet" type="text/css" href="theme/default/css/display.css?version=0.7.1" media="screen, projection, tv"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrap">
|
||||
<div id="core">
|
||||
<div id="content">
|
||||
<h1>Install Laconica</h1>
|
||||
<? main() ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
24
js/flowplayer-3.0.5.min.js
vendored
Normal file
24
js/flowplayer-3.0.5.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,4 +1,5 @@
|
||||
// identica badge -- updated to work with the native API, 12-4-2008
|
||||
// Modified to point to Identi.ca, 2-20-2009 by Zach
|
||||
// copyright Kent Brewster 2008
|
||||
// see http://kentbrewster.com/identica-badge for info
|
||||
( function() {
|
||||
@ -127,7 +128,7 @@
|
||||
var a = document.createElement('A');
|
||||
a.innerHTML = 'get this';
|
||||
a.target = '_blank';
|
||||
a.href = 'http://kentbrewster.com/identica-badge';
|
||||
a.href = 'http://identica/doc/badge';
|
||||
$.s.f.appendChild(a);
|
||||
$.s.appendChild($.s.f);
|
||||
$.f.getUser();
|
||||
|
@ -37,10 +37,3 @@
|
||||
$('#avatar_crop_w').val(c.w);
|
||||
$('#avatar_crop_h').val(c.h);
|
||||
};
|
||||
|
||||
function checkCoords() {
|
||||
if (parseInt($('#avatar_crop_w').val())) return true;
|
||||
alert('Please select a crop region then press submit.');
|
||||
return false;
|
||||
};
|
||||
|
||||
|
222
js/jquery.js
vendored
222
js/jquery.js
vendored
@ -1,13 +1,13 @@
|
||||
/*!
|
||||
* jQuery JavaScript Library v1.3
|
||||
* jQuery JavaScript Library v1.3.1
|
||||
* http://jquery.com/
|
||||
*
|
||||
* Copyright (c) 2009 John Resig
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
* http://docs.jquery.com/License
|
||||
*
|
||||
* Date: 2009-01-13 12:50:31 -0500 (Tue, 13 Jan 2009)
|
||||
* Revision: 6104
|
||||
* Date: 2009-01-21 20:42:16 -0500 (Wed, 21 Jan 2009)
|
||||
* Revision: 6158
|
||||
*/
|
||||
(function(){
|
||||
|
||||
@ -60,20 +60,16 @@ jQuery.fn = jQuery.prototype = {
|
||||
else {
|
||||
var elem = document.getElementById( match[3] );
|
||||
|
||||
// Make sure an element was located
|
||||
if ( elem ){
|
||||
// Handle the case where IE and Opera return items
|
||||
// by name instead of ID
|
||||
if ( elem.id != match[3] )
|
||||
return jQuery().find( selector );
|
||||
// Handle the case where IE and Opera return items
|
||||
// by name instead of ID
|
||||
if ( elem && elem.id != match[3] )
|
||||
return jQuery().find( selector );
|
||||
|
||||
// Otherwise, we inject the element directly into the jQuery object
|
||||
var ret = jQuery( elem );
|
||||
ret.context = document;
|
||||
ret.selector = selector;
|
||||
return ret;
|
||||
}
|
||||
selector = [];
|
||||
// Otherwise, we inject the element directly into the jQuery object
|
||||
var ret = jQuery( elem || [] );
|
||||
ret.context = document;
|
||||
ret.selector = selector;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// HANDLE: $(expr, [context])
|
||||
@ -99,7 +95,7 @@ jQuery.fn = jQuery.prototype = {
|
||||
selector: "",
|
||||
|
||||
// The current version of jQuery being used
|
||||
jquery: "1.3",
|
||||
jquery: "1.3.1",
|
||||
|
||||
// The number of elements contained in the matched element set
|
||||
size: function() {
|
||||
@ -634,8 +630,8 @@ jQuery.extend({
|
||||
|
||||
// check if an element is in a (or is an) XML document
|
||||
isXMLDoc: function( elem ) {
|
||||
return elem.documentElement && !elem.body ||
|
||||
elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
|
||||
return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
|
||||
!!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
|
||||
},
|
||||
|
||||
// Evalulates a script in a global context
|
||||
@ -725,7 +721,7 @@ jQuery.extend({
|
||||
|
||||
// internal only, use hasClass("class")
|
||||
has: function( elem, className ) {
|
||||
return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
|
||||
return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
|
||||
}
|
||||
},
|
||||
|
||||
@ -999,9 +995,11 @@ jQuery.extend({
|
||||
var attributeNode = elem.getAttributeNode( "tabIndex" );
|
||||
return attributeNode && attributeNode.specified
|
||||
? attributeNode.value
|
||||
: elem.nodeName.match(/^(a|area|button|input|object|select|textarea)$/i)
|
||||
: elem.nodeName.match(/(button|input|object|select|textarea)/i)
|
||||
? 0
|
||||
: undefined;
|
||||
: elem.nodeName.match(/^(a|area)$/i) && elem.href
|
||||
? 0
|
||||
: undefined;
|
||||
}
|
||||
|
||||
return elem[ name ];
|
||||
@ -1397,14 +1395,14 @@ jQuery.fn.extend({
|
||||
});
|
||||
}
|
||||
});/*!
|
||||
* Sizzle CSS Selector Engine - v0.9.1
|
||||
* Sizzle CSS Selector Engine - v0.9.3
|
||||
* Copyright 2009, The Dojo Foundation
|
||||
* Released under the MIT, BSD, and GPL Licenses.
|
||||
* More information: http://sizzlejs.com/
|
||||
*/
|
||||
(function(){
|
||||
|
||||
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|[^[\]]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g,
|
||||
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]+['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g,
|
||||
done = 0,
|
||||
toString = Object.prototype.toString;
|
||||
|
||||
@ -1433,40 +1431,27 @@ var Sizzle = function(selector, context, results, seed) {
|
||||
}
|
||||
}
|
||||
|
||||
if ( parts.length > 1 && Expr.match.POS.exec( selector ) ) {
|
||||
if ( parts.length > 1 && origPOS.exec( selector ) ) {
|
||||
if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
|
||||
var later = "", match;
|
||||
|
||||
// Position selectors must be done after the filter
|
||||
while ( (match = Expr.match.POS.exec( selector )) ) {
|
||||
later += match[0];
|
||||
selector = selector.replace( Expr.match.POS, "" );
|
||||
}
|
||||
|
||||
set = Sizzle.filter( later, Sizzle( /\s$/.test(selector) ? selector + "*" : selector, context ) );
|
||||
set = posProcess( parts[0] + parts[1], context );
|
||||
} else {
|
||||
set = Expr.relative[ parts[0] ] ?
|
||||
[ context ] :
|
||||
Sizzle( parts.shift(), context );
|
||||
|
||||
while ( parts.length ) {
|
||||
var tmpSet = [];
|
||||
|
||||
selector = parts.shift();
|
||||
|
||||
if ( Expr.relative[ selector ] )
|
||||
selector += parts.shift();
|
||||
|
||||
for ( var i = 0, l = set.length; i < l; i++ ) {
|
||||
Sizzle( selector, set[i], tmpSet );
|
||||
}
|
||||
|
||||
set = tmpSet;
|
||||
set = posProcess( selector, set );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var ret = seed ?
|
||||
{ expr: parts.pop(), set: makeArray(seed) } :
|
||||
Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context );
|
||||
Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
|
||||
set = Sizzle.filter( ret.expr, ret.set );
|
||||
|
||||
if ( parts.length > 0 ) {
|
||||
@ -1531,7 +1516,7 @@ Sizzle.matches = function(expr, set){
|
||||
return Sizzle(expr, null, null, set);
|
||||
};
|
||||
|
||||
Sizzle.find = function(expr, context){
|
||||
Sizzle.find = function(expr, context, isXML){
|
||||
var set, match;
|
||||
|
||||
if ( !expr ) {
|
||||
@ -1546,7 +1531,7 @@ Sizzle.find = function(expr, context){
|
||||
|
||||
if ( left.substr( left.length - 1 ) !== "\\" ) {
|
||||
match[1] = (match[1] || "").replace(/\\/g, "");
|
||||
set = Expr.find[ type ]( match, context );
|
||||
set = Expr.find[ type ]( match, context, isXML );
|
||||
if ( set != null ) {
|
||||
expr = expr.replace( Expr.match[ type ], "" );
|
||||
break;
|
||||
@ -1568,7 +1553,7 @@ Sizzle.filter = function(expr, set, inplace, not){
|
||||
while ( expr && set.length ) {
|
||||
for ( var type in Expr.filter ) {
|
||||
if ( (match = Expr.match[ type ].exec( expr )) != null ) {
|
||||
var filter = Expr.filter[ type ], goodArray = null, goodPos = 0, found, item;
|
||||
var filter = Expr.filter[ type ], found, item;
|
||||
anyFound = false;
|
||||
|
||||
if ( curLoop == result ) {
|
||||
@ -1582,26 +1567,13 @@ Sizzle.filter = function(expr, set, inplace, not){
|
||||
anyFound = found = true;
|
||||
} else if ( match === true ) {
|
||||
continue;
|
||||
} else if ( match[0] === true ) {
|
||||
goodArray = [];
|
||||
var last = null, elem;
|
||||
for ( var i = 0; (elem = curLoop[i]) !== undefined; i++ ) {
|
||||
if ( elem && last !== elem ) {
|
||||
goodArray.push( elem );
|
||||
last = elem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( match ) {
|
||||
for ( var i = 0; (item = curLoop[i]) !== undefined; i++ ) {
|
||||
for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
|
||||
if ( item ) {
|
||||
if ( goodArray && item != goodArray[goodPos] ) {
|
||||
goodPos++;
|
||||
}
|
||||
|
||||
found = filter( item, match, goodPos, goodArray );
|
||||
found = filter( item, match, i, curLoop );
|
||||
var pass = not ^ !!found;
|
||||
|
||||
if ( inplace && found != null ) {
|
||||
@ -1739,14 +1711,16 @@ var Expr = Sizzle.selectors = {
|
||||
}
|
||||
},
|
||||
find: {
|
||||
ID: function(match, context){
|
||||
if ( context.getElementById ) {
|
||||
ID: function(match, context, isXML){
|
||||
if ( typeof context.getElementById !== "undefined" && !isXML ) {
|
||||
var m = context.getElementById(match[1]);
|
||||
return m ? [m] : [];
|
||||
}
|
||||
},
|
||||
NAME: function(match, context){
|
||||
return context.getElementsByName ? context.getElementsByName(match[1]) : null;
|
||||
NAME: function(match, context, isXML){
|
||||
if ( typeof context.getElementsByName !== "undefined" && !isXML ) {
|
||||
return context.getElementsByName(match[1]);
|
||||
}
|
||||
},
|
||||
TAG: function(match, context){
|
||||
return context.getElementsByTagName(match[1]);
|
||||
@ -1756,12 +1730,15 @@ var Expr = Sizzle.selectors = {
|
||||
CLASS: function(match, curLoop, inplace, result, not){
|
||||
match = " " + match[1].replace(/\\/g, "") + " ";
|
||||
|
||||
for ( var i = 0; curLoop[i]; i++ ) {
|
||||
if ( not ^ (" " + curLoop[i].className + " ").indexOf(match) >= 0 ) {
|
||||
if ( !inplace )
|
||||
result.push( curLoop[i] );
|
||||
} else if ( inplace ) {
|
||||
curLoop[i] = false;
|
||||
var elem;
|
||||
for ( var i = 0; (elem = curLoop[i]) != null; i++ ) {
|
||||
if ( elem ) {
|
||||
if ( not ^ (" " + elem.className + " ").indexOf(match) >= 0 ) {
|
||||
if ( !inplace )
|
||||
result.push( elem );
|
||||
} else if ( inplace ) {
|
||||
curLoop[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1771,8 +1748,8 @@ var Expr = Sizzle.selectors = {
|
||||
return match[1].replace(/\\/g, "");
|
||||
},
|
||||
TAG: function(match, curLoop){
|
||||
for ( var i = 0; !curLoop[i]; i++ ){}
|
||||
return isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
|
||||
for ( var i = 0; curLoop[i] === false; i++ ){}
|
||||
return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
|
||||
},
|
||||
CHILD: function(match){
|
||||
if ( match[1] == "nth" ) {
|
||||
@ -1792,7 +1769,7 @@ var Expr = Sizzle.selectors = {
|
||||
return match;
|
||||
},
|
||||
ATTR: function(match){
|
||||
var name = match[1];
|
||||
var name = match[1].replace(/\\/g, "");
|
||||
|
||||
if ( Expr.attrMap[name] ) {
|
||||
match[1] = Expr.attrMap[name];
|
||||
@ -1916,7 +1893,7 @@ var Expr = Sizzle.selectors = {
|
||||
CHILD: function(elem, match){
|
||||
var type = match[1], parent = elem.parentNode;
|
||||
|
||||
var doneName = "child" + parent.childNodes.length;
|
||||
var doneName = match[0];
|
||||
|
||||
if ( parent && (!parent[ doneName ] || !elem.nodeIndex) ) {
|
||||
var count = 1;
|
||||
@ -1985,7 +1962,7 @@ var Expr = Sizzle.selectors = {
|
||||
ATTR: function(elem, match){
|
||||
var result = Expr.attrHandle[ match[1] ] ? Expr.attrHandle[ match[1] ]( elem ) : elem[ match[1] ] || elem.getAttribute( match[1] ), value = result + "", type = match[2], check = match[4];
|
||||
return result == null ?
|
||||
false :
|
||||
type === "!=" :
|
||||
type === "=" ?
|
||||
value === check :
|
||||
type === "*=" ?
|
||||
@ -2014,6 +1991,8 @@ var Expr = Sizzle.selectors = {
|
||||
}
|
||||
};
|
||||
|
||||
var origPOS = Expr.match.POS;
|
||||
|
||||
for ( var type in Expr.match ) {
|
||||
Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
|
||||
}
|
||||
@ -2072,15 +2051,15 @@ try {
|
||||
// The workaround has to do additional checks after a getElementById
|
||||
// Which slows things down for other browsers (hence the branching)
|
||||
if ( !!document.getElementById( id ) ) {
|
||||
Expr.find.ID = function(match, context){
|
||||
if ( context.getElementById ) {
|
||||
Expr.find.ID = function(match, context, isXML){
|
||||
if ( typeof context.getElementById !== "undefined" && !isXML ) {
|
||||
var m = context.getElementById(match[1]);
|
||||
return m ? m.id === match[1] || m.getAttributeNode && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
|
||||
return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
|
||||
}
|
||||
};
|
||||
|
||||
Expr.filter.ID = function(elem, match){
|
||||
var node = elem.getAttributeNode && elem.getAttributeNode("id");
|
||||
var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
|
||||
return elem.nodeType === 1 && node && node.nodeValue === match;
|
||||
};
|
||||
}
|
||||
@ -2120,7 +2099,7 @@ try {
|
||||
|
||||
// Check to see if an attribute returns normalized href attributes
|
||||
div.innerHTML = "<a href='#'></a>";
|
||||
if ( div.firstChild.getAttribute("href") !== "#" ) {
|
||||
if ( div.firstChild && div.firstChild.getAttribute("href") !== "#" ) {
|
||||
Expr.attrHandle.href = function(elem){
|
||||
return elem.getAttribute("href", 2);
|
||||
};
|
||||
@ -2128,12 +2107,21 @@ try {
|
||||
})();
|
||||
|
||||
if ( document.querySelectorAll ) (function(){
|
||||
var oldSizzle = Sizzle;
|
||||
var oldSizzle = Sizzle, div = document.createElement("div");
|
||||
div.innerHTML = "<p class='TEST'></p>";
|
||||
|
||||
// Safari can't handle uppercase or unicode characters when
|
||||
// in quirks mode.
|
||||
if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Sizzle = function(query, context, extra, seed){
|
||||
context = context || document;
|
||||
|
||||
if ( !seed && context.nodeType === 9 ) {
|
||||
// Only use querySelectorAll on non-XML documents
|
||||
// (ID selectors don't work in non-HTML documents)
|
||||
if ( !seed && context.nodeType === 9 && !isXML(context) ) {
|
||||
try {
|
||||
return makeArray( context.querySelectorAll(query), extra );
|
||||
} catch(e){}
|
||||
@ -2148,7 +2136,7 @@ if ( document.querySelectorAll ) (function(){
|
||||
Sizzle.matches = oldSizzle.matches;
|
||||
})();
|
||||
|
||||
if ( document.documentElement.getElementsByClassName ) {
|
||||
if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) {
|
||||
Expr.order.splice(1, 0, "CLASS");
|
||||
Expr.find.CLASS = function(match, context) {
|
||||
return context.getElementsByClassName(match[1]);
|
||||
@ -2229,8 +2217,28 @@ var contains = document.compareDocumentPosition ? function(a, b){
|
||||
};
|
||||
|
||||
var isXML = function(elem){
|
||||
return elem.documentElement && !elem.body ||
|
||||
elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
|
||||
return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
|
||||
!!elem.ownerDocument && isXML( elem.ownerDocument );
|
||||
};
|
||||
|
||||
var posProcess = function(selector, context){
|
||||
var tmpSet = [], later = "", match,
|
||||
root = context.nodeType ? [context] : context;
|
||||
|
||||
// Position selectors must be done after the filter
|
||||
// And so must :not(positional) so we move all PSEUDOs to the end
|
||||
while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
|
||||
later += match[0];
|
||||
selector = selector.replace( Expr.match.PSEUDO, "" );
|
||||
}
|
||||
|
||||
selector = Expr.relative[selector] ? selector + "*" : selector;
|
||||
|
||||
for ( var i = 0, l = root.length; i < l; i++ ) {
|
||||
Sizzle( selector, root[i], tmpSet );
|
||||
}
|
||||
|
||||
return Sizzle.filter( later, tmpSet );
|
||||
};
|
||||
|
||||
// EXPOSE
|
||||
@ -2681,13 +2689,13 @@ jQuery.Event = function( src ){
|
||||
if( src && src.type ){
|
||||
this.originalEvent = src;
|
||||
this.type = src.type;
|
||||
this.timeStamp = src.timeStamp;
|
||||
// Event type
|
||||
}else
|
||||
this.type = src;
|
||||
|
||||
if( !this.timeStamp )
|
||||
this.timeStamp = now();
|
||||
// timeStamp is buggy for some events on Firefox(#3843)
|
||||
// So we won't rely on the native value
|
||||
this.timeStamp = now();
|
||||
|
||||
// Mark it as fixed
|
||||
this[expando] = true;
|
||||
@ -2876,9 +2884,8 @@ function liveHandler( event ){
|
||||
});
|
||||
|
||||
jQuery.each(elems, function(){
|
||||
if ( !event.isImmediatePropagationStopped() &&
|
||||
this.fn.call(this.elem, event, this.fn.data) === false )
|
||||
stop = false;
|
||||
if ( this.fn.call(this.elem, event, this.fn.data) === false )
|
||||
stop = false;
|
||||
});
|
||||
|
||||
return stop;
|
||||
@ -2942,7 +2949,7 @@ function bindReady(){
|
||||
|
||||
// If IE and not an iframe
|
||||
// continually check to see if the document is ready
|
||||
if ( document.documentElement.doScroll && !window.frameElement ) (function(){
|
||||
if ( document.documentElement.doScroll && typeof window.frameElement === "undefined" ) (function(){
|
||||
if ( jQuery.isReady ) return;
|
||||
|
||||
try {
|
||||
@ -3477,6 +3484,9 @@ jQuery.extend({
|
||||
// Fire the complete handlers
|
||||
complete();
|
||||
|
||||
if ( isTimeout )
|
||||
xhr.abort();
|
||||
|
||||
// Stop memory leaks
|
||||
if ( s.async )
|
||||
xhr = null;
|
||||
@ -3491,14 +3501,8 @@ jQuery.extend({
|
||||
if ( s.timeout > 0 )
|
||||
setTimeout(function(){
|
||||
// Check to see if the request is still happening
|
||||
if ( xhr ) {
|
||||
if( !requestDone )
|
||||
onreadystatechange( "timeout" );
|
||||
|
||||
// Cancel the request
|
||||
if ( xhr )
|
||||
xhr.abort();
|
||||
}
|
||||
if ( xhr && !requestDone )
|
||||
onreadystatechange( "timeout" );
|
||||
}, s.timeout);
|
||||
}
|
||||
|
||||
@ -3637,6 +3641,7 @@ jQuery.extend({
|
||||
|
||||
});
|
||||
var elemdisplay = {},
|
||||
timerId,
|
||||
fxAttrs = [
|
||||
// height animations
|
||||
[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
|
||||
@ -3859,7 +3864,6 @@ jQuery.extend({
|
||||
},
|
||||
|
||||
timers: [],
|
||||
timerId: null,
|
||||
|
||||
fx: function( elem, options, prop ){
|
||||
this.options = options;
|
||||
@ -3911,10 +3915,8 @@ jQuery.fx.prototype = {
|
||||
|
||||
t.elem = this.elem;
|
||||
|
||||
jQuery.timers.push(t);
|
||||
|
||||
if ( t() && jQuery.timerId == null ) {
|
||||
jQuery.timerId = setInterval(function(){
|
||||
if ( t() && jQuery.timers.push(t) == 1 ) {
|
||||
timerId = setInterval(function(){
|
||||
var timers = jQuery.timers;
|
||||
|
||||
for ( var i = 0; i < timers.length; i++ )
|
||||
@ -3922,8 +3924,7 @@ jQuery.fx.prototype = {
|
||||
timers.splice(i--, 1);
|
||||
|
||||
if ( !timers.length ) {
|
||||
clearInterval( jQuery.timerId );
|
||||
jQuery.timerId = null;
|
||||
clearInterval( timerId );
|
||||
}
|
||||
}, 13);
|
||||
}
|
||||
@ -3989,11 +3990,10 @@ jQuery.fx.prototype = {
|
||||
if ( this.options.hide || this.options.show )
|
||||
for ( var p in this.options.curAnim )
|
||||
jQuery.attr(this.elem.style, p, this.options.orig[p]);
|
||||
}
|
||||
|
||||
if ( done )
|
||||
|
||||
// Execute the complete function
|
||||
this.options.complete.call( this.elem );
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
@ -4087,7 +4087,7 @@ jQuery.offset = {
|
||||
initialize: function() {
|
||||
if ( this.initialized ) return;
|
||||
var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
|
||||
html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"cellpadding="0"cellspacing="0"><tr><td></td></tr></table>';
|
||||
html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';
|
||||
|
||||
rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
|
||||
for ( prop in rules ) container.style[prop] = rules[prop];
|
||||
|
12
js/jquery.min.js
vendored
12
js/jquery.min.js
vendored
File diff suppressed because one or more lines are too long
8
js/jquery.simplemodal-1.2.2.pack.js
Normal file
8
js/jquery.simplemodal-1.2.2.pack.js
Normal file
@ -0,0 +1,8 @@
|
||||
/*
|
||||
* SimpleModal 1.2.2 - jQuery Plugin
|
||||
* http://www.ericmmartin.com/projects/simplemodal/
|
||||
* Copyright (c) 2008 Eric Martin
|
||||
* Dual licensed under the MIT and GPL licenses
|
||||
* Revision: $Id: jquery.simplemodal.js 181 2008-12-16 16:51:44Z emartin24 $
|
||||
*/
|
||||
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(g($){m f=$.Q.1Q&&1a($.Q.1D)==6&&!10[\'2g\'],1f=$.Q.1Q&&!$.2a,w=[];$.y=g(a,b){I $.y.12.1n(a,b)};$.y.D=g(){$.y.12.D()};$.1P.y=g(a){I $.y.12.1n(3,a)};$.y.1O={V:29,1J:\'r-H\',1B:{},1z:\'r-n\',20:{},1Z:{},v:2t,D:1o,1T:\'<a 2j="2h" 2f="2e"></a>\',X:\'r-D\',l:F,1g:K,1e:F,1d:F,1c:F};$.y.12={7:F,4:{},1n:g(a,b){8(3.4.j){I K}3.7=$.U({},$.y.1O,b);3.v=3.7.v;3.1w=K;8(J a==\'27\'){a=a 25 1A?a:$(a);8(a.1v().1v().23()>0){3.4.T=a.1v();8(!3.7.1g){3.4.21=a.2x(1o)}}}q 8(J a==\'2w\'||J a==\'1r\'){a=$(\'<1q/>\').2s(a)}q{2r(\'2q 2p: 2o j 2l: \'+J a);I K}3.4.j=a.11(\'r-j\').E(3.7.1Z);a=F;3.1S();3.1R();8($.1m(3.7.1d)){3.7.1d.1l(3,[3.4])}I 3},1S:g(){w=3.1k();8(f){3.4.x=$(\'<x 2d="2c:K;"/>\').E($.U(3.7.2b,{1j:\'1i\',V:0,l:\'1h\',A:w[0],z:w[1],v:3.7.v,L:0,B:0})).O(\'u\')}3.4.H=$(\'<1q/>\').1N(\'1M\',3.7.1J).11(\'r-H\').E($.U(3.7.1B,{1j:\'1i\',V:3.7.V/1b,A:w[0],z:w[1],l:\'1h\',B:0,L:0,v:3.7.v+1})).O(\'u\');3.4.n=$(\'<1q/>\').1N(\'1M\',3.7.1z).11(\'r-n\').E($.U(3.7.20,{1j:\'1i\',l:\'1h\',v:3.7.v+2})).1K(3.7.D?$(3.7.1T).11(3.7.X):\'\').O(\'u\');3.19();8(f||1f){3.18()}3.4.n.1K(3.4.j.1I())},1H:g(){m a=3;$(\'.\'+3.7.X).1G(\'1L.r\',g(e){e.28();a.D()});$(10).1G(\'1F.r\',g(){w=a.1k();a.19();8(f||1f){a.18()}q{a.4.x&&a.4.x.E({A:w[0],z:w[1]});a.4.H.E({A:w[0],z:w[1]})}})},1E:g(){$(\'.\'+3.7.X).1C(\'1L.r\');$(10).1C(\'1F.r\')},18:g(){m p=3.7.l;$.26([3.4.x||F,3.4.H,3.4.n],g(i,e){8(e){m a=\'k.u.17\',N=\'k.u.1W\',16=\'k.u.24\',S=\'k.u.1y\',R=\'k.u.1x\',15=\'k.u.22\',1t=\'k.P.17\',1s=\'k.P.1W\',C=\'k.P.1y\',G=\'k.P.1x\',s=e[0].2v;s.l=\'2u\';8(i<2){s.14(\'A\');s.14(\'z\');s.Z(\'A\',\'\'+16+\' > \'+a+\' ? \'+16+\' : \'+a+\' + "o"\');s.Z(\'z\',\'\'+15+\' > \'+N+\' ? \'+15+\' : \'+N+\' + "o"\')}q{m b,W;8(p&&p.1Y==1X){8(p[0]){m c=J p[0]==\'1r\'?p[0].1V():p[0].13(/o/,\'\');b=c.1U(\'%\')==-1?c+\' + (t = \'+G+\' ? \'+G+\' : \'+R+\') + "o"\':1a(c.13(/%/,\'\'))+\' * ((\'+1t+\' || \'+a+\') / 1b) + (t = \'+G+\' ? \'+G+\' : \'+R+\') + "o"\'}8(p[1]){m d=J p[1]==\'1r\'?p[1].1V():p[1].13(/o/,\'\');W=d.1U(\'%\')==-1?d+\' + (t = \'+C+\' ? \'+C+\' : \'+S+\') + "o"\':1a(d.13(/%/,\'\'))+\' * ((\'+1s+\' || \'+N+\') / 1b) + (t = \'+C+\' ? \'+C+\' : \'+S+\') + "o"\'}}q{b=\'(\'+1t+\' || \'+a+\') / 2 - (3.2n / 2) + (t = \'+G+\' ? \'+G+\' : \'+R+\') + "o"\';W=\'(\'+1s+\' || \'+N+\') / 2 - (3.2m / 2) + (t = \'+C+\' ? \'+C+\' : \'+S+\') + "o"\'}s.14(\'L\');s.14(\'B\');s.Z(\'L\',b);s.Z(\'B\',W)}}})},1k:g(){m a=$(10);m h=$.Q.2k&&$.Q.1D>\'9.5\'&&$.1P.2i<=\'1.2.6\'?k.P[\'17\']:a.A();I[h,a.z()]},19:g(){m a,B,1u=(w[0]/2)-((3.4.n.A()||3.4.j.A())/2),1p=(w[1]/2)-((3.4.n.z()||3.4.j.z())/2);8(3.7.l&&3.7.l.1Y==1X){a=3.7.l[0]||1u;B=3.7.l[1]||1p}q{a=1u;B=1p}3.4.n.E({B:B,L:a})},1R:g(){3.4.x&&3.4.x.Y();8($.1m(3.7.1e)){3.7.1e.1l(3,[3.4])}q{3.4.H.Y();3.4.n.Y();3.4.j.Y()}3.1H()},D:g(){8(!3.4.j){I K}8($.1m(3.7.1c)&&!3.1w){3.1w=1o;3.7.1c.1l(3,[3.4])}q{8(3.4.T){8(3.7.1g){3.4.j.1I().O(3.4.T)}q{3.4.j.M();3.4.21.O(3.4.T)}}q{3.4.j.M()}3.4.n.M();3.4.H.M();3.4.x&&3.4.x.M();3.4={}}3.1E()}}})(1A);',62,158,'|||this|dialog|||opts|if||||||||function|||data|document|position|var|container|px||else|simplemodal|||body|zIndex||iframe|modal|width|height|left|sl|close|css|null|st|overlay|return|typeof|false|top|remove|bcw|appendTo|documentElement|browser|bst|bsl|parentNode|extend|opacity|le|closeClass|show|setExpression|window|addClass|impl|replace|removeExpression|bsw|bsh|clientHeight|fixIE|setPosition|parseInt|100|onClose|onShow|onOpen|ieQuirks|persist|fixed|none|display|getDimensions|apply|isFunction|init|true|vCenter|div|number|cw|ch|hCenter|parent|occb|scrollTop|scrollLeft|containerId|jQuery|overlayCss|unbind|version|unbindEvents|resize|bind|bindEvents|hide|overlayId|append|click|id|attr|defaults|fn|msie|open|create|closeHTML|indexOf|toString|clientWidth|Array|constructor|dataCss|containerCss|orig|scrollWidth|size|scrollHeight|instanceof|each|object|preventDefault|50|boxModel|iframeCss|javascript|src|Close|title|XMLHttpRequest|modalCloseImg|jquery|class|opera|type|offsetWidth|offsetHeight|Unsupported|Error|SimpleModal|alert|html|1000|absolute|style|string|clone'.split('|'),0,{}))
|
9
js/video.js
Normal file
9
js/video.js
Normal file
@ -0,0 +1,9 @@
|
||||
$('document').ready(function() {
|
||||
$('a.media, a.mediamp3').append(' <sup>[PLAY]</sup>');
|
||||
$('a.mediamp3').html('').css('display', 'block').css('width', '224px').css('height','24px').flowplayer('../bin/flowplayer-3.0.5.swf');
|
||||
$('a.media').click(function() {
|
||||
$('<a id="p1i"></a>').attr('href', $(this).attr('href')).flowplayer('../bin/flowplayer-3.0.5.swf').modal({'closeHTML':'<a class="modalCloseImg" title="Close"><img src="x.png" /></a>'});
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
169
lib/action.php
169
lib/action.php
@ -93,7 +93,10 @@ class Action extends HTMLOutputter // lawsuit
|
||||
*/
|
||||
function showPage()
|
||||
{
|
||||
$this->startHTML();
|
||||
if (Event::handle('StartShowHTML', array($this))) {
|
||||
$this->startHTML();
|
||||
Event::handle('EndShowHTML', array($this));
|
||||
}
|
||||
$this->showHead();
|
||||
$this->showBody();
|
||||
$this->endHTML();
|
||||
@ -151,25 +154,50 @@ class Action extends HTMLOutputter // lawsuit
|
||||
*/
|
||||
function showStylesheets()
|
||||
{
|
||||
$this->element('link', array('rel' => 'stylesheet',
|
||||
'type' => 'text/css',
|
||||
'href' => theme_path('css/display.css', 'base') . '?version=' . LACONICA_VERSION,
|
||||
'media' => 'screen, projection, tv'));
|
||||
$this->element('link', array('rel' => 'stylesheet',
|
||||
'type' => 'text/css',
|
||||
'href' => theme_path('css/display.css', null) . '?version=' . LACONICA_VERSION,
|
||||
'media' => 'screen, projection, tv'));
|
||||
$this->comment('[if IE]><link rel="stylesheet" type="text/css" '.
|
||||
'href="'.theme_path('css/ie.css', 'base').'?version='.LACONICA_VERSION.'" /><![endif]');
|
||||
foreach (array(6,7) as $ver) {
|
||||
if (file_exists(theme_file('css/ie'.$ver.'.css', 'base'))) {
|
||||
// Yes, IE people should be put in jail.
|
||||
$this->comment('[if lte IE '.$ver.']><link rel="stylesheet" type="text/css" '.
|
||||
'href="'.theme_path('css/ie'.$ver.'.css', 'base').'?version='.LACONICA_VERSION.'" /><![endif]');
|
||||
if (Event::handle('StartShowStyles', array($this))) {
|
||||
if (Event::handle('StartShowLaconicaStyles', array($this))) {
|
||||
|
||||
$this->element('link', array('rel' => 'stylesheet',
|
||||
'type' => 'text/css',
|
||||
'href' => theme_path('css/display.css', 'base') . '?version=' . LACONICA_VERSION,
|
||||
'media' => 'screen, projection, tv'));
|
||||
$this->element('link', array('rel' => 'stylesheet',
|
||||
'type' => 'text/css',
|
||||
'href' => theme_path('css/modal.css', 'base') . '?version=' . LACONICA_VERSION,
|
||||
'media' => 'screen, projection, tv'));
|
||||
$this->element('link', array('rel' => 'stylesheet',
|
||||
'type' => 'text/css',
|
||||
'href' => theme_path('css/display.css', null) . '?version=' . LACONICA_VERSION,
|
||||
'media' => 'screen, projection, tv'));
|
||||
if (common_config('site', 'mobile')) {
|
||||
$this->element('link', array('rel' => 'stylesheet',
|
||||
'type' => 'text/css',
|
||||
'href' => theme_path('css/mobile.css', 'base') . '?version=' . LACONICA_VERSION,
|
||||
// TODO: "handheld" CSS for other mobile devices
|
||||
'media' => 'only screen and (max-device-width: 480px)')); // Mobile WebKit
|
||||
}
|
||||
$this->element('link', array('rel' => 'stylesheet',
|
||||
'type' => 'text/css',
|
||||
'href' => theme_path('css/print.css', 'base') . '?version=' . LACONICA_VERSION,
|
||||
'media' => 'print'));
|
||||
Event::handle('EndShowLaconicaStyles', array($this));
|
||||
}
|
||||
if (Event::handle('StartShowUAStyles', array($this))) {
|
||||
$this->comment('[if IE]><link rel="stylesheet" type="text/css" '.
|
||||
'href="'.theme_path('css/ie.css', 'base').'?version='.LACONICA_VERSION.'" /><![endif]');
|
||||
foreach (array(6,7) as $ver) {
|
||||
if (file_exists(theme_file('css/ie'.$ver.'.css', 'base'))) {
|
||||
// Yes, IE people should be put in jail.
|
||||
$this->comment('[if lte IE '.$ver.']><link rel="stylesheet" type="text/css" '.
|
||||
'href="'.theme_path('css/ie'.$ver.'.css', 'base').'?version='.LACONICA_VERSION.'" /><![endif]');
|
||||
}
|
||||
}
|
||||
$this->comment('[if IE]><link rel="stylesheet" type="text/css" '.
|
||||
'href="'.theme_path('css/ie.css', null).'?version='.LACONICA_VERSION.'" /><![endif]');
|
||||
Event::handle('EndShowUAStyles', array($this));
|
||||
}
|
||||
Event::handle('EndShowStyles', array($this));
|
||||
}
|
||||
$this->comment('[if IE]><link rel="stylesheet" type="text/css" '.
|
||||
'href="'.theme_path('css/ie.css', null).'?version='.LACONICA_VERSION.'" /><![endif]');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,6 +215,11 @@ class Action extends HTMLOutputter // lawsuit
|
||||
$this->element('script', array('type' => 'text/javascript',
|
||||
'src' => common_path('js/jquery.form.js')),
|
||||
' ');
|
||||
|
||||
$this->element('script', array('type' => 'text/javascript',
|
||||
'src' => common_path('js/jquery.simplemodal-1.2.2.pack.js')),
|
||||
' ');
|
||||
|
||||
Event::handle('EndShowJQueryScripts', array($this));
|
||||
}
|
||||
if (Event::handle('StartShowLaconicaScripts', array($this))) {
|
||||
@ -196,6 +229,17 @@ class Action extends HTMLOutputter // lawsuit
|
||||
$this->element('script', array('type' => 'text/javascript',
|
||||
'src' => common_path('js/util.js?version='.LACONICA_VERSION)),
|
||||
' ');
|
||||
// Frame-busting code to avoid clickjacking attacks.
|
||||
$this->element('script', array('type' => 'text/javascript'),
|
||||
'if (window.top !== window.self) { window.top.location.href = window.self.location.href; }');
|
||||
|
||||
$this->element('script', array('type' => 'text/javascript',
|
||||
'src' => common_path('js/flowplayer-3.0.5.min.js')),
|
||||
' ');
|
||||
|
||||
$this->element('script', array('type' => 'text/javascript',
|
||||
'src' => common_path('js/video.js')),
|
||||
' ');
|
||||
Event::handle('EndShowLaconicaScripts', array($this));
|
||||
}
|
||||
Event::handle('EndShowScripts', array($this));
|
||||
@ -225,9 +269,19 @@ class Action extends HTMLOutputter // lawsuit
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
|
||||
function showFeeds()
|
||||
{
|
||||
// does nothing by default
|
||||
$feeds = $this->getFeeds();
|
||||
|
||||
if ($feeds) {
|
||||
foreach ($feeds as $feed) {
|
||||
$this->element('link', array('rel' => $feed->rel(),
|
||||
'href' => $feed->url,
|
||||
'type' => $feed->mimeType(),
|
||||
'title' => $feed->title));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -265,9 +319,15 @@ class Action extends HTMLOutputter // lawsuit
|
||||
{
|
||||
$this->elementStart('body', array('id' => $this->trimmed('action')));
|
||||
$this->elementStart('div', array('id' => 'wrap'));
|
||||
$this->showHeader();
|
||||
if (Event::handle('StartShowHeader', array($this))) {
|
||||
$this->showHeader();
|
||||
Event::handle('EndShowHeader', array($this));
|
||||
}
|
||||
$this->showCore();
|
||||
$this->showFooter();
|
||||
if (Event::handle('StartShowFooter', array($this))) {
|
||||
$this->showFooter();
|
||||
Event::handle('EndShowFooter', array($this));
|
||||
}
|
||||
$this->elementEnd('div');
|
||||
$this->elementEnd('body');
|
||||
}
|
||||
@ -421,8 +481,14 @@ class Action extends HTMLOutputter // lawsuit
|
||||
function showCore()
|
||||
{
|
||||
$this->elementStart('div', array('id' => 'core'));
|
||||
$this->showLocalNavBlock();
|
||||
$this->showContentBlock();
|
||||
if (Event::handle('StartShowLocalNavBlock', array($this))) {
|
||||
$this->showLocalNavBlock();
|
||||
Event::handle('EndShowLocalNavBlock', array($this));
|
||||
}
|
||||
if (Event::handle('StartShowContentBlock', array($this))) {
|
||||
$this->showContentBlock();
|
||||
Event::handle('EndShowContentBlock', array($this));
|
||||
}
|
||||
$this->showAside();
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
@ -524,27 +590,32 @@ class Action extends HTMLOutputter // lawsuit
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
|
||||
function showAside()
|
||||
{
|
||||
$this->elementStart('div', array('id' => 'aside_primary',
|
||||
'class' => 'aside'));
|
||||
$this->showExportData();
|
||||
$this->showSections();
|
||||
if (Event::handle('StartShowSections', array($this))) {
|
||||
$this->showSections();
|
||||
Event::handle('EndShowSections', array($this));
|
||||
}
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show export data feeds.
|
||||
*
|
||||
* MAY overload if there are feeds
|
||||
*
|
||||
* @return nothing
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showExportData()
|
||||
{
|
||||
// is there structure to this?
|
||||
// list of (visible!) feed links
|
||||
// can we reuse list of feeds from showFeeds() ?
|
||||
$feeds = $this->getFeeds();
|
||||
if ($feeds) {
|
||||
$fl = new FeedList($this);
|
||||
$fl->show($feeds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -596,6 +667,8 @@ class Action extends HTMLOutputter // lawsuit
|
||||
_('Source'));
|
||||
$this->menuItem(common_local_url('doc', array('title' => 'contact')),
|
||||
_('Contact'));
|
||||
$this->menuItem(common_local_url('doc', array('title' => 'badge')),
|
||||
_('Badge'));
|
||||
Event::handle('EndSecondaryNav', array($this));
|
||||
}
|
||||
$this->elementEnd('ul');
|
||||
@ -746,12 +819,15 @@ class Action extends HTMLOutputter // lawsuit
|
||||
}
|
||||
if ($lm) {
|
||||
header('Last-Modified: ' . date(DATE_RFC1123, $lm));
|
||||
$if_modified_since = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
|
||||
if ($if_modified_since) {
|
||||
if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) {
|
||||
$if_modified_since = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
|
||||
$ims = strtotime($if_modified_since);
|
||||
if ($lm <= $ims) {
|
||||
if (!$etag ||
|
||||
$this->_hasEtag($etag, $_SERVER['HTTP_IF_NONE_MATCH'])) {
|
||||
$if_none_match = (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER)) ?
|
||||
$_SERVER['HTTP_IF_NONE_MATCH'] : null;
|
||||
if (!$if_none_match ||
|
||||
!$etag ||
|
||||
$this->_hasEtag($etag, $if_none_match)) {
|
||||
header('HTTP/1.1 304 Not Modified');
|
||||
// Better way to do this?
|
||||
exit(0);
|
||||
@ -769,9 +845,11 @@ class Action extends HTMLOutputter // lawsuit
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
|
||||
function _hasEtag($etag, $if_none_match)
|
||||
{
|
||||
return ($if_none_match) && in_array($etag, explode(',', $if_none_match));
|
||||
$etags = explode(',', $if_none_match);
|
||||
return in_array($etag, $etags) || in_array('*', $etags);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -899,17 +977,17 @@ class Action extends HTMLOutputter // lawsuit
|
||||
}
|
||||
if ($have_before) {
|
||||
$pargs = array('page' => $page-1);
|
||||
$newargs = $args ? array_merge($args, $pargs) : $pargs;
|
||||
$this->elementStart('li', array('class' => 'nav_prev'));
|
||||
$this->element('a', array('href' => common_local_url($action, $newargs), 'rel' => 'prev'),
|
||||
$this->element('a', array('href' => common_local_url($action, $args, $pargs),
|
||||
'rel' => 'prev'),
|
||||
_('After'));
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
if ($have_after) {
|
||||
$pargs = array('page' => $page+1);
|
||||
$newargs = $args ? array_merge($args, $pargs) : $pargs;
|
||||
$this->elementStart('li', array('class' => 'nav_next'));
|
||||
$this->element('a', array('href' => common_local_url($action, $newargs), 'rel' => 'next'),
|
||||
$this->element('a', array('href' => common_local_url($action, $args, $pargs),
|
||||
'rel' => 'next'),
|
||||
_('Before'));
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
@ -920,4 +998,17 @@ class Action extends HTMLOutputter // lawsuit
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of feeds for this action.
|
||||
*
|
||||
* Returns an array of potential feeds for this action.
|
||||
*
|
||||
* @return array Feed object to show in head and links
|
||||
*/
|
||||
|
||||
function getFeeds()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ if (!defined('LACONICA')) { exit(1); }
|
||||
|
||||
class Channel
|
||||
{
|
||||
|
||||
function on($user)
|
||||
{
|
||||
return false;
|
@ -49,7 +49,7 @@ class ClientErrorAction extends ErrorAction
|
||||
function __construct($message='Error', $code=400)
|
||||
{
|
||||
parent::__construct($message, $code);
|
||||
|
||||
|
||||
$this->status = array(400 => 'Bad Request',
|
||||
401 => 'Unauthorized',
|
||||
402 => 'Payment Required',
|
||||
@ -72,7 +72,7 @@ class ClientErrorAction extends ErrorAction
|
||||
}
|
||||
|
||||
// XXX: Should these error actions even be invokable via URI?
|
||||
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
@ -84,11 +84,16 @@ class ClientErrorAction extends ErrorAction
|
||||
}
|
||||
|
||||
$this->message = $this->trimmed('message');
|
||||
|
||||
|
||||
if (!$this->message) {
|
||||
$this->message = "Client Error $this->code";
|
||||
}
|
||||
$this->message = "Client Error $this->code";
|
||||
}
|
||||
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
return $this->status[$this->code];
|
||||
}
|
||||
}
|
||||
|
@ -19,18 +19,18 @@
|
||||
|
||||
if (!defined('LACONICA')) { exit(1); }
|
||||
|
||||
require_once(INSTALLDIR.'/classes/Channel.php');
|
||||
require_once(INSTALLDIR.'/lib/channel.php');
|
||||
|
||||
class Command
|
||||
{
|
||||
|
||||
|
||||
var $user = null;
|
||||
|
||||
|
||||
function __construct($user=null)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
|
||||
function execute($channel)
|
||||
{
|
||||
return false;
|
||||
@ -109,7 +109,7 @@ class StatsCommand extends Command
|
||||
$notices = new Notice();
|
||||
$notices->profile_id = $this->user->id;
|
||||
$notice_count = (int) $notices->count();
|
||||
|
||||
|
||||
$channel->output($this->user, sprintf(_("Subscriptions: %1\$s\n".
|
||||
"Subscribers: %2\$s\n".
|
||||
"Notices: %3\$s"),
|
||||
@ -121,21 +121,21 @@ class StatsCommand extends Command
|
||||
|
||||
class FavCommand extends Command
|
||||
{
|
||||
|
||||
|
||||
var $other = null;
|
||||
|
||||
|
||||
function __construct($user, $other)
|
||||
{
|
||||
parent::__construct($user);
|
||||
$this->other = $other;
|
||||
}
|
||||
|
||||
|
||||
function execute($channel)
|
||||
{
|
||||
|
||||
$recipient =
|
||||
|
||||
$recipient =
|
||||
common_relative_profile($this->user, common_canonical_nickname($this->other));
|
||||
|
||||
|
||||
if (!$recipient) {
|
||||
$channel->error($this->user, _('No such user.'));
|
||||
return;
|
||||
@ -145,7 +145,7 @@ class FavCommand extends Command
|
||||
$channel->error($this->user, _('User has no last notice'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$fave = Fave::addNew($this->user, $notice);
|
||||
|
||||
if (!$fave) {
|
||||
@ -154,15 +154,15 @@ class FavCommand extends Command
|
||||
}
|
||||
|
||||
$other = User::staticGet('id', $recipient->id);
|
||||
|
||||
|
||||
if ($other && $other->id != $user->id) {
|
||||
if ($other->email && $other->emailnotifyfav) {
|
||||
mail_notify_fave($other, $this->user, $notice);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$this->user->blowFavesCache();
|
||||
|
||||
|
||||
$channel->output($this->user, _('Notice marked as fave.'));
|
||||
}
|
||||
}
|
||||
@ -175,17 +175,17 @@ class WhoisCommand extends Command
|
||||
parent::__construct($user);
|
||||
$this->other = $other;
|
||||
}
|
||||
|
||||
|
||||
function execute($channel)
|
||||
{
|
||||
$recipient =
|
||||
$recipient =
|
||||
common_relative_profile($this->user, common_canonical_nickname($this->other));
|
||||
|
||||
|
||||
if (!$recipient) {
|
||||
$channel->error($this->user, _('No such user.'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$whois = sprintf(_("%1\$s (%2\$s)"), $recipient->nickname,
|
||||
$recipient->profileurl);
|
||||
if ($recipient->fullname) {
|
||||
@ -214,7 +214,7 @@ class MessageCommand extends Command
|
||||
$this->other = $other;
|
||||
$this->text = $text;
|
||||
}
|
||||
|
||||
|
||||
function execute($channel)
|
||||
{
|
||||
$other = User::staticGet('nickname', common_canonical_nickname($this->other));
|
||||
@ -229,7 +229,7 @@ class MessageCommand extends Command
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!$other) {
|
||||
$channel->error($this->user, _('No such user.'));
|
||||
return;
|
||||
@ -251,19 +251,19 @@ class MessageCommand extends Command
|
||||
|
||||
class GetCommand extends Command
|
||||
{
|
||||
|
||||
|
||||
var $other = null;
|
||||
|
||||
|
||||
function __construct($user, $other)
|
||||
{
|
||||
parent::__construct($user);
|
||||
$this->other = $other;
|
||||
}
|
||||
|
||||
|
||||
function execute($channel)
|
||||
{
|
||||
$target_nickname = common_canonical_nickname($this->other);
|
||||
|
||||
|
||||
$target =
|
||||
common_relative_profile($this->user, $target_nickname);
|
||||
|
||||
@ -277,32 +277,32 @@ class GetCommand extends Command
|
||||
return;
|
||||
}
|
||||
$notice_content = $notice->content;
|
||||
|
||||
|
||||
$channel->output($this->user, $target_nickname . ": " . $notice_content);
|
||||
}
|
||||
}
|
||||
|
||||
class SubCommand extends Command
|
||||
{
|
||||
|
||||
|
||||
var $other = null;
|
||||
|
||||
|
||||
function __construct($user, $other)
|
||||
{
|
||||
parent::__construct($user);
|
||||
$this->other = $other;
|
||||
}
|
||||
|
||||
|
||||
function execute($channel)
|
||||
{
|
||||
|
||||
|
||||
if (!$this->other) {
|
||||
$channel->error($this->user, _('Specify the name of the user to subscribe to'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$result = subs_subscribe_user($this->user, $this->other);
|
||||
|
||||
|
||||
if ($result == 'true') {
|
||||
$channel->output($this->user, sprintf(_('Subscribed to %s'), $this->other));
|
||||
} else {
|
||||
@ -315,7 +315,7 @@ class UnsubCommand extends Command
|
||||
{
|
||||
|
||||
var $other = null;
|
||||
|
||||
|
||||
function __construct($user, $other)
|
||||
{
|
||||
parent::__construct($user);
|
||||
@ -328,9 +328,9 @@ class UnsubCommand extends Command
|
||||
$channel->error($this->user, _('Specify the name of the user to unsubscribe from'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$result=subs_unsubscribe_user($this->user, $this->other);
|
||||
|
||||
|
||||
if ($result) {
|
||||
$channel->output($this->user, sprintf(_('Unsubscribed from %s'), $this->other));
|
||||
} else {
|
||||
@ -369,7 +369,7 @@ class OnCommand extends Command
|
||||
parent::__construct($user);
|
||||
$this->other = $other;
|
||||
}
|
||||
|
||||
|
||||
function execute($channel)
|
||||
{
|
||||
if ($other) {
|
||||
@ -406,7 +406,7 @@ class HelpCommand extends Command
|
||||
"unsub <nickname> - same as 'leave'\n".
|
||||
"last <nickname> - same as 'get'\n".
|
||||
"on <nickname> - not yet implemented.\n".
|
||||
"off <nickname> - not yet implemented.\n".
|
||||
"off <nickname> - not yet implemented.\n".
|
||||
"nudge <nickname> - not yet implemented.\n".
|
||||
"invite <phone number> - not yet implemented.\n".
|
||||
"track <word> - not yet implemented.\n".
|
@ -19,11 +19,10 @@
|
||||
|
||||
if (!defined('LACONICA')) { exit(1); }
|
||||
|
||||
require_once(INSTALLDIR.'/classes/Command.php');
|
||||
require_once INSTALLDIR.'/lib/command.php';
|
||||
|
||||
class CommandInterpreter
|
||||
{
|
||||
|
||||
function handle_command($user, $text)
|
||||
{
|
||||
# XXX: localise
|
@ -73,6 +73,7 @@ $config =
|
||||
'theme' => 'default',
|
||||
'path' => $_path,
|
||||
'logfile' => null,
|
||||
'logdebug' => false,
|
||||
'fancy' => false,
|
||||
'locale_path' => INSTALLDIR.'/locale',
|
||||
'language' => 'en_US',
|
||||
@ -106,7 +107,8 @@ $config =
|
||||
array('server' => null),
|
||||
'public' =>
|
||||
array('localonly' => true,
|
||||
'blacklist' => array()),
|
||||
'blacklist' => array(),
|
||||
'autosource' => array()),
|
||||
'theme' =>
|
||||
array('server' => null),
|
||||
'throttle' =>
|
||||
@ -142,6 +144,8 @@ $config =
|
||||
array('enabled' => false,
|
||||
'server' => 'localhost',
|
||||
'port' => 11211),
|
||||
'ping' =>
|
||||
array('notify' => array()),
|
||||
'inboxes' =>
|
||||
array('enabled' => true), # on by default for new sites
|
||||
);
|
||||
@ -177,12 +181,31 @@ if (strlen($_path) > 0) {
|
||||
|
||||
$_config_files[] = INSTALLDIR.'/config.php';
|
||||
|
||||
$_have_a_config = false;
|
||||
|
||||
foreach ($_config_files as $_config_file) {
|
||||
if (file_exists($_config_file)) {
|
||||
include_once($_config_file);
|
||||
$_have_a_config = true;
|
||||
}
|
||||
}
|
||||
|
||||
function _have_config()
|
||||
{
|
||||
global $_have_a_config;
|
||||
return $_have_a_config;
|
||||
}
|
||||
|
||||
// XXX: Throw a conniption if database not installed
|
||||
|
||||
// Fixup for laconica.ini
|
||||
|
||||
$_db_name = substr($config['db']['database'], strrpos($config['db']['database'], '/') + 1);
|
||||
|
||||
if ($_db_name != 'laconica' && !array_key_exists('ini_'.$_db_name, $config['db'])) {
|
||||
$config['db']['ini_'.$_db_name] = INSTALLDIR.'/classes/laconica.ini';
|
||||
}
|
||||
|
||||
// XXX: how many of these could be auto-loaded on use?
|
||||
|
||||
require_once('Validate.php');
|
||||
@ -211,6 +234,9 @@ function __autoload($class)
|
||||
require_once(INSTALLDIR.'/classes/' . $class . '.php');
|
||||
} else if (file_exists(INSTALLDIR.'/lib/' . strtolower($class) . '.php')) {
|
||||
require_once(INSTALLDIR.'/lib/' . strtolower($class) . '.php');
|
||||
} else if (mb_substr($class, -6) == 'Action' &&
|
||||
file_exists(INSTALLDIR.'/actions/' . strtolower(mb_substr($class, 0, -6)) . '.php')) {
|
||||
require_once(INSTALLDIR.'/actions/' . strtolower(mb_substr($class, 0, -6)) . '.php');
|
||||
}
|
||||
}
|
||||
|
||||
|
73
lib/dberroraction.php
Normal file
73
lib/dberroraction.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* DB error action.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Action
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @author Zach Copley <zach@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://laconi.ca/
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/servererroraction.php';
|
||||
|
||||
/**
|
||||
* Class for displaying DB Errors
|
||||
*
|
||||
* This only occurs if there's been a DB_DataObject_Error that's
|
||||
* reported through PEAR, so we try to avoid doing anything that connects
|
||||
* to the DB, so we don't trigger it again.
|
||||
*
|
||||
* @category Action
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
class DBErrorAction extends ServerErrorAction
|
||||
{
|
||||
function __construct($message='Error', $code=500)
|
||||
{
|
||||
parent::__construct($message, $code);
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
return _('Database error');
|
||||
}
|
||||
|
||||
function getLanguage()
|
||||
{
|
||||
// Don't try to figure out user's language; just show the page
|
||||
return common_config('site', 'language');
|
||||
}
|
||||
|
||||
function showPrimaryNav()
|
||||
{
|
||||
// don't show primary nav
|
||||
}
|
||||
}
|
@ -25,21 +25,6 @@ define("FACEBOOK_SERVICE", 2); // Facebook is foreign_service ID 2
|
||||
define("FACEBOOK_NOTICE_PREFIX", 1);
|
||||
define("FACEBOOK_PROMPTED_UPDATE_PREF", 2);
|
||||
|
||||
// Gets all the notices from users with a Facebook link since a given ID
|
||||
function getFacebookNotices($since)
|
||||
{
|
||||
$qry = 'SELECT notice.* ' .
|
||||
'FROM notice ' .
|
||||
'JOIN foreign_link ' .
|
||||
'WHERE notice.profile_id = foreign_link.user_id ' .
|
||||
'AND foreign_link.service = 2';
|
||||
|
||||
// XXX: What should the limit be?
|
||||
//static function getStreamDirect($qry, $offset, $limit, $since_id, $before_id, $order, $since) {
|
||||
|
||||
return Notice::getStreamDirect($qry, 0, 1000, 0, 0, null, $since);
|
||||
}
|
||||
|
||||
function getFacebook()
|
||||
{
|
||||
$apikey = common_config('facebook', 'apikey');
|
||||
@ -52,3 +37,97 @@ function updateProfileBox($facebook, $flink, $notice) {
|
||||
$fbaction->updateProfileBox($notice);
|
||||
}
|
||||
|
||||
function isFacebookBound($notice, $flink) {
|
||||
|
||||
// If the user does not want to broadcast to Facebook, move along
|
||||
if (!($flink->noticesync & FOREIGN_NOTICE_SEND == FOREIGN_NOTICE_SEND)) {
|
||||
common_log(LOG_INFO, "Skipping notice $notice->id " .
|
||||
'because user has FOREIGN_NOTICE_SEND bit off.');
|
||||
return false;
|
||||
}
|
||||
|
||||
$success = false;
|
||||
|
||||
// If it's not a reply, or if the user WANTS to send @-replies...
|
||||
if (!preg_match('/@[a-zA-Z0-9_]{1,15}\b/u', $notice->content) ||
|
||||
($flink->noticesync & FOREIGN_NOTICE_SEND_REPLY)) {
|
||||
|
||||
$success = true;
|
||||
|
||||
// The two condition below are deal breakers:
|
||||
|
||||
// Avoid a loop
|
||||
if ($notice->source == 'Facebook') {
|
||||
common_log(LOG_INFO, "Skipping notice $notice->id because its " .
|
||||
'source is Facebook.');
|
||||
$success = false;
|
||||
}
|
||||
|
||||
$facebook = getFacebook();
|
||||
$fbuid = $flink->foreign_id;
|
||||
|
||||
try {
|
||||
|
||||
// Check to see if the user has given the FB app status update perms
|
||||
$result = $facebook->api_client->
|
||||
users_hasAppPermission('status_update', $fbuid);
|
||||
|
||||
if ($result != 1) {
|
||||
$user = $flink->getUser();
|
||||
$msg = "Can't send notice $notice->id to Facebook " .
|
||||
"because user $user->nickname hasn't given the " .
|
||||
'Facebook app \'status_update\' permission.';
|
||||
common_log(LOG_INFO, $msg);
|
||||
$success = false;
|
||||
}
|
||||
|
||||
} catch(FacebookRestClientException $e){
|
||||
common_log(LOG_ERR, $e->getMessage());
|
||||
$success = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $success;
|
||||
|
||||
}
|
||||
|
||||
|
||||
function facebookBroadcastNotice($notice)
|
||||
{
|
||||
$facebook = getFacebook();
|
||||
$flink = Foreign_link::getByUserID($notice->profile_id, FACEBOOK_SERVICE);
|
||||
$fbuid = $flink->foreign_id;
|
||||
|
||||
if (isFacebookBound($notice, $flink)) {
|
||||
|
||||
$status = null;
|
||||
|
||||
// Get the status 'verb' (prefix) the user has set
|
||||
try {
|
||||
$prefix = $facebook->api_client->
|
||||
data_getUserPreference(FACEBOOK_NOTICE_PREFIX, $fbuid);
|
||||
|
||||
$status = "$prefix $notice->content";
|
||||
|
||||
} catch(FacebookRestClientException $e) {
|
||||
common_log(LOG_ERR, $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Okay, we're good to go!
|
||||
|
||||
try {
|
||||
$facebook->api_client->users_setStatus($status, $fbuid, false, true);
|
||||
updateProfileBox($facebook, $flink, $notice);
|
||||
} catch(FacebookRestClientException $e) {
|
||||
common_log(LOG_ERR, $e->getMessage());
|
||||
return false;
|
||||
|
||||
// Should we remove flink if this fails?
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -86,4 +86,9 @@ class FeaturedUsersSection extends ProfileSection
|
||||
{
|
||||
return 'featured_users';
|
||||
}
|
||||
|
||||
function moreUrl()
|
||||
{
|
||||
return common_local_url('featured');
|
||||
}
|
||||
}
|
||||
|
110
lib/feed.php
Normal file
110
lib/feed.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* Data structure for info about syndication feeds (RSS 1.0, RSS 2.0, Atom)
|
||||
*
|
||||
* 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 Feed
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @copyright 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data structure for feeds
|
||||
*
|
||||
* This structure is a helpful container for shipping around information about syndication feeds.
|
||||
*
|
||||
* @category Feed
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@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 Feed
|
||||
{
|
||||
const RSS1 = 1;
|
||||
const RSS2 = 2;
|
||||
const ATOM = 3;
|
||||
const FOAF = 4;
|
||||
|
||||
var $type = null;
|
||||
var $url = null;
|
||||
var $title = null;
|
||||
|
||||
function __construct($type, $url, $title)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->url = $url;
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
function mimeType()
|
||||
{
|
||||
switch ($this->type) {
|
||||
case Feed::RSS1:
|
||||
return 'application/rdf+xml';
|
||||
case Feed::RSS2:
|
||||
return 'application/rss+xml';
|
||||
case Feed::ATOM:
|
||||
return 'application/atom+xml';
|
||||
case Feed::FOAF:
|
||||
return 'application/rdf+xml';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function typeName()
|
||||
{
|
||||
switch ($this->type) {
|
||||
case Feed::RSS1:
|
||||
return _('RSS 1.0');
|
||||
case Feed::RSS2:
|
||||
return _('RSS 2.0');
|
||||
case Feed::ATOM:
|
||||
return _('Atom');
|
||||
case Feed::FOAF:
|
||||
return _('FOAF');
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function rel()
|
||||
{
|
||||
switch ($this->type) {
|
||||
case Feed::RSS1:
|
||||
case Feed::RSS2:
|
||||
case Feed::ATOM:
|
||||
return 'alternate';
|
||||
case Feed::FOAF:
|
||||
return 'meta';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -50,7 +50,7 @@ if (!defined('LACONICA')) {
|
||||
class FeedList extends Widget
|
||||
{
|
||||
var $action = null;
|
||||
|
||||
|
||||
function __construct($action=null)
|
||||
{
|
||||
parent::__construct($action);
|
||||
@ -64,8 +64,8 @@ class FeedList extends Widget
|
||||
$this->out->element('h2', null, _('Export data'));
|
||||
$this->out->elementStart('ul', array('class' => 'xoxo'));
|
||||
|
||||
foreach ($feeds as $key => $value) {
|
||||
$this->feedItem($feeds[$key]);
|
||||
foreach ($feeds as $feed) {
|
||||
$this->feedItem($feed);
|
||||
}
|
||||
|
||||
$this->out->elementEnd('ul');
|
||||
@ -74,85 +74,27 @@ class FeedList extends Widget
|
||||
|
||||
function feedItem($feed)
|
||||
{
|
||||
$nickname = $this->action->trimmed('nickname');
|
||||
$classname = null;
|
||||
|
||||
switch($feed['item']) {
|
||||
case 'notices': default:
|
||||
$feed_classname = $feed['type'];
|
||||
$feed_mimetype = "application/".$feed['type']."+xml";
|
||||
$feed_title = "$nickname's ".$feed['version']." notice feed";
|
||||
$feed['textContent'] = "RSS";
|
||||
switch ($feed->type) {
|
||||
case Feed::RSS1:
|
||||
case Feed::RSS2:
|
||||
$classname = 'rss';
|
||||
break;
|
||||
|
||||
case 'allrss':
|
||||
$feed_classname = $feed['type'];
|
||||
$feed_mimetype = "application/".$feed['type']."+xml";
|
||||
$feed_title = $feed['version']." feed for $nickname and friends";
|
||||
$feed['textContent'] = "RSS";
|
||||
case Feed::ATOM:
|
||||
$classname = 'atom';
|
||||
break;
|
||||
|
||||
case 'repliesrss':
|
||||
$feed_classname = $feed['type'];
|
||||
$feed_mimetype = "application/".$feed['type']."+xml";
|
||||
$feed_title = $feed['version']." feed for replies to $nickname";
|
||||
$feed['textContent'] = "RSS";
|
||||
break;
|
||||
|
||||
case 'publicrss':
|
||||
$feed_classname = $feed['type'];
|
||||
$feed_mimetype = "application/".$feed['type']."+xml";
|
||||
$feed_title = "Public timeline ".$feed['version']." feed";
|
||||
$feed['textContent'] = "RSS";
|
||||
break;
|
||||
|
||||
case 'publicatom':
|
||||
$feed_classname = "atom";
|
||||
$feed_mimetype = "application/".$feed['type']."+xml";
|
||||
$feed_title = "Public timeline ".$feed['version']." feed";
|
||||
$feed['textContent'] = "Atom";
|
||||
break;
|
||||
|
||||
case 'tagrss':
|
||||
$feed_classname = $feed['type'];
|
||||
$feed_mimetype = "application/".$feed['type']."+xml";
|
||||
$feed_title = $feed['version']." feed for this tag";
|
||||
$feed['textContent'] = "RSS";
|
||||
break;
|
||||
|
||||
case 'favoritedrss':
|
||||
$feed_classname = $feed['type'];
|
||||
$feed_mimetype = "application/".$feed['type']."+xml";
|
||||
$feed_title = "Favorited ".$feed['version']." feed";
|
||||
$feed['textContent'] = "RSS";
|
||||
break;
|
||||
|
||||
case 'foaf':
|
||||
$feed_classname = "foaf";
|
||||
$feed_mimetype = "application/".$feed['type']."+xml";
|
||||
$feed_title = "$nickname's FOAF file";
|
||||
$feed['textContent'] = "FOAF";
|
||||
break;
|
||||
|
||||
case 'favoritesrss':
|
||||
$feed_classname = "favorites";
|
||||
$feed_mimetype = "application/".$feed['type']."+xml";
|
||||
$feed_title = "Feed for favorites of $nickname";
|
||||
$feed['textContent'] = "RSS";
|
||||
break;
|
||||
|
||||
case 'usertimeline':
|
||||
$feed_classname = "atom";
|
||||
$feed_mimetype = "application/".$feed['type']."+xml";
|
||||
$feed_title = "$nickname's ".$feed['version']." notice feed";
|
||||
$feed['textContent'] = "Atom";
|
||||
case Feed::FOAF:
|
||||
$classname = 'foaf';
|
||||
break;
|
||||
}
|
||||
|
||||
$this->out->elementStart('li');
|
||||
$this->out->element('a', array('href' => $feed['href'],
|
||||
'class' => $feed_classname,
|
||||
'type' => $feed_mimetype,
|
||||
'title' => $feed_title),
|
||||
$feed['textContent']);
|
||||
$this->out->element('a', array('href' => $feed->url,
|
||||
'class' => $classname,
|
||||
'type' => $feed->mimeType(),
|
||||
'title' => $feed->title),
|
||||
$feed->typeName());
|
||||
$this->out->elementEnd('li');
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ class GroupList extends Widget
|
||||
if ($this->group->location) {
|
||||
$this->out->elementStart('dl', 'entity_location');
|
||||
$this->out->element('dt', null, _('Location'));
|
||||
$this->out->elementStart('dd', 'location');
|
||||
$this->out->elementStart('dd', 'label');
|
||||
$this->out->raw($this->highlight($this->group->location));
|
||||
$this->out->elementEnd('dd');
|
||||
$this->out->elementEnd('dl');
|
||||
@ -151,7 +151,7 @@ class GroupList extends Widget
|
||||
|
||||
# If we're on a list with an owner (subscriptions or subscribers)...
|
||||
|
||||
if ($user && $user->id == $this->owner->id) {
|
||||
if (!empty($user) && !empty($this->owner) && $user->id == $this->owner->id) {
|
||||
$this->showOwnerControls();
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ class GroupsByMembersSection extends GroupSection
|
||||
$qry = 'SELECT user_group.*, count(*) as value ' .
|
||||
'FROM user_group JOIN group_member '.
|
||||
'ON user_group.id = group_member.group_id ' .
|
||||
'GROUP BY user_group.id ' .
|
||||
'GROUP BY user_group.id,user_group.nickname,user_group.fullname,user_group.homepage,user_group.description,user_group.location,user_group.original_logo,user_group.homepage_logo,user_group.stream_logo,user_group.mini_logo,user_group.created,user_group.modified ' .
|
||||
'ORDER BY value DESC ';
|
||||
|
||||
$limit = GROUPS_PER_SECTION;
|
||||
|
@ -48,7 +48,7 @@ class GroupsByPostsSection extends GroupSection
|
||||
$qry = 'SELECT user_group.*, count(*) as value ' .
|
||||
'FROM user_group JOIN group_inbox '.
|
||||
'ON user_group.id = group_inbox.group_id ' .
|
||||
'GROUP BY user_group.id ' .
|
||||
'GROUP BY user_group.id,user_group.nickname,user_group.fullname,user_group.homepage,user_group.description,user_group.location,user_group.original_logo,user_group.homepage_logo,user_group.stream_logo,user_group.mini_logo,user_group.created,user_group.modified ' .
|
||||
'ORDER BY value DESC ';
|
||||
|
||||
$limit = GROUPS_PER_SECTION;
|
||||
|
@ -58,8 +58,14 @@ class GroupTagCloudSection extends TagCloudSection
|
||||
|
||||
function getTags()
|
||||
{
|
||||
if (common_config('db', 'type') == 'pgsql') {
|
||||
$weightexpr='sum(exp(-extract(epoch from (now() - notice_tag.created)) / %s))';
|
||||
} else {
|
||||
$weightexpr='sum(exp(-(now() - notice_tag.created) / %s))';
|
||||
}
|
||||
|
||||
$qry = 'SELECT notice_tag.tag, '.
|
||||
'sum(exp(-(now() - notice_tag.created)/%s)) as weight ' .
|
||||
$weightexpr . ' as weight ' .
|
||||
'FROM notice_tag JOIN notice ' .
|
||||
'ON notice_tag.notice_id = notice.id ' .
|
||||
'JOIN group_inbox on group_inbox.notice_id = notice.id ' .
|
||||
|
@ -101,29 +101,32 @@ class HTMLOutputter extends XMLOutputter
|
||||
$type = common_negotiate_type($cp, $sp);
|
||||
|
||||
if (!$type) {
|
||||
common_user_error(_('This page is not available in a '.
|
||||
'media type you accept'), 406);
|
||||
exit(0);
|
||||
throw new ClientException(_('This page is not available in a '.
|
||||
'media type you accept'), 406);
|
||||
}
|
||||
}
|
||||
|
||||
header('Content-Type: '.$type);
|
||||
|
||||
|
||||
$this->extraHeaders();
|
||||
|
||||
$this->startXML('html',
|
||||
'-//W3C//DTD XHTML 1.0 Strict//EN',
|
||||
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd');
|
||||
|
||||
// FIXME: correct language for interface
|
||||
|
||||
$language = common_language();
|
||||
$language = $this->getLanguage();
|
||||
|
||||
$this->elementStart('html', array('xmlns' => 'http://www.w3.org/1999/xhtml',
|
||||
'xml:lang' => $language,
|
||||
'lang' => $language));
|
||||
}
|
||||
|
||||
function getLanguage()
|
||||
{
|
||||
// FIXME: correct language for interface
|
||||
return common_language();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends an HTML document
|
||||
*
|
||||
@ -134,7 +137,7 @@ class HTMLOutputter extends XMLOutputter
|
||||
$this->elementEnd('html');
|
||||
$this->endXML();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* To specify additional HTTP headers for the action
|
||||
*
|
||||
@ -255,7 +258,7 @@ class HTMLOutputter extends XMLOutputter
|
||||
foreach ($content as $value => $option) {
|
||||
if ($value == $selected) {
|
||||
$this->element('option', array('value' => $value,
|
||||
'selected' => $value),
|
||||
'selected' => 'selected'),
|
||||
$option);
|
||||
} else {
|
||||
$this->element('option', array('value' => $value), $option);
|
||||
|
@ -68,17 +68,17 @@ class ImageFile
|
||||
static function fromUpload($param='upload')
|
||||
{
|
||||
switch ($_FILES[$param]['error']) {
|
||||
case UPLOAD_ERR_OK: // success, jump out
|
||||
case UPLOAD_ERR_OK: // success, jump out
|
||||
break;
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
case UPLOAD_ERR_FORM_SIZE:
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
case UPLOAD_ERR_FORM_SIZE:
|
||||
throw new Exception(sprintf(_('That file is too big. The maximum file size is %d.'), $this->maxFileSize()));
|
||||
return;
|
||||
case UPLOAD_ERR_PARTIAL:
|
||||
case UPLOAD_ERR_PARTIAL:
|
||||
@unlink($_FILES[$param]['tmp_name']);
|
||||
throw new Exception(_('Partial upload.'));
|
||||
return;
|
||||
default:
|
||||
default:
|
||||
throw new Exception(_('System error uploading file.'));
|
||||
return;
|
||||
}
|
||||
@ -113,6 +113,23 @@ class ImageFile
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't crop/scale if it isn't necessary
|
||||
if ($size === $this->width
|
||||
&& $size === $this->height
|
||||
&& $x === 0
|
||||
&& $y === 0
|
||||
&& $w === $this->width
|
||||
&& $h === $this->height) {
|
||||
|
||||
$outname = Avatar::filename($this->id,
|
||||
image_type_to_extension($this->type),
|
||||
$size,
|
||||
common_timestamp());
|
||||
$outpath = Avatar::path($outname);
|
||||
@copy($this->filepath, $outpath);
|
||||
return $outname;
|
||||
}
|
||||
|
||||
switch ($this->type) {
|
||||
case IMAGETYPE_GIF:
|
||||
$image_src = imagecreatefromgif($this->filepath);
|
||||
@ -154,9 +171,9 @@ class ImageFile
|
||||
imagecopyresampled($image_dest, $image_src, 0, 0, $x, $y, $size, $size, $w, $h);
|
||||
|
||||
$outname = Avatar::filename($this->id,
|
||||
image_type_to_extension($this->type),
|
||||
$size,
|
||||
common_timestamp());
|
||||
image_type_to_extension($this->type),
|
||||
$size,
|
||||
common_timestamp());
|
||||
|
||||
$outpath = Avatar::path($outname);
|
||||
|
||||
@ -165,7 +182,7 @@ class ImageFile
|
||||
imagegif($image_dest, $outpath);
|
||||
break;
|
||||
case IMAGETYPE_JPEG:
|
||||
imagejpeg($image_dest, $outpath);
|
||||
imagejpeg($image_dest, $outpath, 100);
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
imagepng($image_dest, $outpath);
|
||||
@ -175,6 +192,9 @@ class ImageFile
|
||||
return;
|
||||
}
|
||||
|
||||
imagedestroy($image_src);
|
||||
imagedestroy($image_dest);
|
||||
|
||||
return $outname;
|
||||
}
|
||||
|
||||
@ -209,12 +229,12 @@ class ImageFile
|
||||
$num = substr($str, 0, -1);
|
||||
|
||||
switch(strtoupper($unit)){
|
||||
case 'G':
|
||||
$num *= 1024;
|
||||
case 'M':
|
||||
$num *= 1024;
|
||||
case 'K':
|
||||
$num *= 1024;
|
||||
case 'G':
|
||||
$num *= 1024;
|
||||
case 'M':
|
||||
$num *= 1024;
|
||||
case 'K':
|
||||
$num *= 1024;
|
||||
}
|
||||
|
||||
return $num;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user