Merge branch '0.9.x' into userflag
This commit is contained in:
commit
5f5413624d
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -24,4 +24,4 @@ config-*.php
|
||||||
good-config.php
|
good-config.php
|
||||||
lac08.log
|
lac08.log
|
||||||
php.log
|
php.log
|
||||||
|
.DS_Store
|
||||||
|
|
84
EVENTS.txt
84
EVENTS.txt
|
@ -129,6 +129,9 @@ StartSubGroupNav: Showing the subscriptions group nav menu
|
||||||
EndSubGroupNav: At the end of the subscriptions group nav menu
|
EndSubGroupNav: At the end of the subscriptions group nav menu
|
||||||
- $action: the current action
|
- $action: the current action
|
||||||
|
|
||||||
|
StartInitializeRouter: Before the router instance has been initialized; good place to add routes
|
||||||
|
- $m: the Net_URL_Mapper that has just been set up
|
||||||
|
|
||||||
RouterInitialized: After the router instance has been initialized
|
RouterInitialized: After the router instance has been initialized
|
||||||
- $m: the Net_URL_Mapper that has just been set up
|
- $m: the Net_URL_Mapper that has just been set up
|
||||||
|
|
||||||
|
@ -390,3 +393,84 @@ EndProfilePageProfileTags: after showing the tags on the profile page
|
||||||
- $action: the current action
|
- $action: the current action
|
||||||
- &$profile: the profile being shown
|
- &$profile: the profile being shown
|
||||||
|
|
||||||
|
StartProfileList: when starting a list of profiles (before <ul>)
|
||||||
|
- $profilelist: ProfileList widget, with $profile, $action, and $out
|
||||||
|
|
||||||
|
EndProfileList: when ending a list of profiles (after </ul>)
|
||||||
|
- $profilelist: ProfileList widget
|
||||||
|
|
||||||
|
StartProfileListItem: when starting to show a profile list item
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
EndProfileListItem: after showing a profile list item
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
StartProfileListItemProfile: the profile data part of the item
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
EndProfileListItemProfile: the profile data part of the item
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
StartProfileListItemActions: the actions (buttons) for an item
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
EndProfileListItemActions: the actions (buttons) for an item
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
StartProfileListItemProfileElements: inside the <div>
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
EndProfileListItemProfileElements: inside the <div>
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
StartProfileListItemAvatar: Showing a profile list avatar
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
EndProfileListItemAvatar: Showing a profile list avatar
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
StartProfileListItemFullName: Showing the profile list full name
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
EndProfileListItemFullName: Showing the profile list full name
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
StartProfileListItemLocation: Showing the profile list location
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
EndProfileListItemLocation: Showing the profile list location
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
StartProfileListItemHomepage: Showing the profile list homepage
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
EndProfileListItemHomepage: Showing the profile list homepage
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
StartProfileListItemBio: Showing the profile list bio
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
EndProfileListItemBio: Showing the profile list bio
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
StartProfileListItemActionElements: Showing the profile list actions (prepend a button here, or replace all buttons)
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
EndProfileListItemActionElements: Showing profile list actions (append a button here)
|
||||||
|
- $item: ProfileListItem widget
|
||||||
|
|
||||||
|
StartUserXRDS: Start XRDS output (right after the opening XRDS tag)
|
||||||
|
- $action: the current action
|
||||||
|
- &$xrdsoutputter - XRDSOutputter object to write to
|
||||||
|
|
||||||
|
EndUserXRDS: End XRDS output (right before the closing XRDS tag)
|
||||||
|
- $action: the current action
|
||||||
|
- &$xrdsoutputter - XRDSOutputter object to write to
|
||||||
|
|
||||||
|
StartPublicXRDS: Start XRDS output (right after the opening XRDS tag)
|
||||||
|
- $action: the current action
|
||||||
|
- &$xrdsoutputter - XRDSOutputter object to write to
|
||||||
|
|
||||||
|
EndPublicXRDS: End XRDS output (right before the closing XRDS tag)
|
||||||
|
- $action: the current action
|
||||||
|
- &$xrdsoutputter - XRDSOutputter object to write to
|
||||||
|
|
263
README
263
README
|
@ -2,8 +2,8 @@
|
||||||
README
|
README
|
||||||
------
|
------
|
||||||
|
|
||||||
StatusNet 0.8.1 ("Second Guessing")
|
StatusNet 0.8.2 ("Life and How to Live It")
|
||||||
26 Aug 2009
|
1 Nov 2009
|
||||||
|
|
||||||
This is the README file for StatusNet (formerly Laconica), the Open
|
This is the README file for StatusNet (formerly Laconica), the Open
|
||||||
Source microblogging platform. It includes installation instructions,
|
Source microblogging platform. It includes installation instructions,
|
||||||
|
@ -77,49 +77,80 @@ for additional terms.
|
||||||
New this version
|
New this version
|
||||||
================
|
================
|
||||||
|
|
||||||
This is a minor feature and bugfix release since version 0.8.0,
|
This is a minor feature and bugfix release since version 0.8.1,
|
||||||
released Jul 15 2009. Notable changes this version:
|
released Aug 26 2009. Notable changes this version:
|
||||||
|
|
||||||
- Laconica has been renamed StatusNet. With a few minor compatibility
|
- New script for deleting user accounts. Not particularly safe or
|
||||||
exceptions, all references to "Laconica" in code, documentation
|
community-friendly. Better for deleting abusive accounts than for
|
||||||
and comments were changed to "StatusNet".
|
users who are 'retiring'.
|
||||||
- A new plugin to support "infinite scroll".
|
- Improved detection of URLs in notices, specifically for punctuation
|
||||||
- A new plugin to support reCaptcha <http://recaptcha.net>.
|
chars like ~, :, $, _, -, +, !, @, and %.
|
||||||
- Better logging of server errors.
|
- Removed some extra <dl> semantic HTML code.
|
||||||
- Add an Openid-only mode for authentication.
|
- Correct error in status-network database ini file (having multiple
|
||||||
- 'lite' parameter for some Twitter API methods.
|
statusnet sites with a single codebase)
|
||||||
- A new plugin to auto-complete nicknames for @-replies.
|
- Fixed error output for Twitter posting failures.
|
||||||
- Configuration options to disable OpenID, SMS, Twitter, post-by-email, and IM.
|
- Fixed bug in Twitter queue handler that requeued inapplicable
|
||||||
- Support for lighttpd <http://lighttpd.org/> using 404-based
|
notices ad infinitum.
|
||||||
rewrites.
|
- Improve FOAF output for remote users.
|
||||||
- Support for using Twitter's OAuth authentication as a client.
|
- new commands to join and leave groups.
|
||||||
- First version of the groups API.
|
- Fixed bug in which you cannot turn off importing friends timelines
|
||||||
- Can configure a site-wide design, including background image and
|
flag.
|
||||||
colors.
|
- Better error handling in Twitter posting.
|
||||||
- Improved algorithm for replies and conversations, making
|
- Show oEmbed data for XHTML files as well as plain HTML.
|
||||||
conversation trees more accurate and useful.
|
- Updated bug database link in README.
|
||||||
- Add a script to create a simulation database for testing/debugging.
|
- require HTML tidy extension.
|
||||||
- Sanitize HTML for OEmbed.
|
- add support for HTTP Basic Auth in PHP CGI or FastCGI (e.g. GoDaddy).
|
||||||
- Improved queue management for DB-based queuing.
|
- autofocus input to selected entry elements depending on page.
|
||||||
- More complete URL detection.
|
- updated layout for filter-by-tag form.
|
||||||
- Hashtags now support full Unicode character set.
|
- better layout for inbox and outbox pages.
|
||||||
- Notice inboxes are now garbage-collected on a regular basis
|
- fix highlighting search terms in attributes of notice list elements.
|
||||||
at notice-write time.
|
- Correctly handle errors in linkback plugin.
|
||||||
- PiwikAnalyticsPlugin updated for latest Piwik interface.
|
- Updated biz theme.
|
||||||
- Attachment and notice pages can be embedded with OEmbed
|
- Updated cloudy theme.
|
||||||
<http://www.oembed.com>.
|
- Don't match '::' as an IPv6 address.
|
||||||
- Failed authentication is logged.
|
- Use the same decision logic for deciding whether to mark an
|
||||||
- PostgreSQL schema and support brought up-to-date with 0.8.x features.
|
attachment as an enclosure in RSS or as a paperclip item in Web
|
||||||
- The installer works with PostgreSQL as well as MySQL.
|
output.
|
||||||
- RSS 1.0 feeds use HTTP Basic authentication in private mode.
|
- Fixed a bug in the Piwik plugin that hard-coded the site ID.
|
||||||
- Many, many bug fixes, particularly with performance.
|
- Add a param, inreplyto, to notice/new to allow an explicit response
|
||||||
- Better (=working) garbage collection for old sessions.
|
to another notice.
|
||||||
- Better (=working) search queries.
|
- Show username in subject of emails.
|
||||||
- Some cleanup of HTML output.
|
- Check if avatar exists before trying to delete it.
|
||||||
- Better error handling when updating Facebook.
|
- Correctly add omb_version to response for request token in OMB.
|
||||||
- Considerably better performance when using replication for API
|
- Add a few more SMS carriers.
|
||||||
calls.
|
- Add a few more notice sources.
|
||||||
- Initial unit tests.
|
- Vary: header.
|
||||||
|
- Improvements to the AutoCompletePlugin.
|
||||||
|
- Check for 'dl' before using it.
|
||||||
|
- Make it impossible to delete self-subscriptions via the API.
|
||||||
|
- Fix pagination of tagged user pages.
|
||||||
|
- Make PiwikAnalyticsPlugin work with addPlugin().
|
||||||
|
- Removed trailing single space in user nicknames in notice lists.
|
||||||
|
- Show context link if a notice starts a conversation.
|
||||||
|
- blacklist all files and directories in install dir.
|
||||||
|
- handle GoDaddy-style PATH_INFO, including script name.
|
||||||
|
- add home_timeline synonym for friends_timeline.
|
||||||
|
- Add a popup window for the realtime plugin.
|
||||||
|
- Add some more streams for the realtime plugin.
|
||||||
|
- Fix a bug that overwrote group creation timestamp on every edit.
|
||||||
|
- Moved HTTP error code strings to a class variable.
|
||||||
|
- The Twitter API now returns server errors in the correct format.
|
||||||
|
- Reset the doctype for HTML output.
|
||||||
|
- Fixed a number of notices.
|
||||||
|
- Don't show search suggestions for private sites.
|
||||||
|
- Some corrections to FBConnect nav overrides.
|
||||||
|
- Slightly less database-intensive session management.
|
||||||
|
- Updated name of software in installer script.
|
||||||
|
- Include long-form attachment URLs if url-shortener is disabled.
|
||||||
|
- Include updated localisations for Polish, Greek, Hebrew, Icelandic,
|
||||||
|
Norwegian, and Chinese.
|
||||||
|
- Include upstream fixes to gettext.php.
|
||||||
|
- Correct for regression in Facebook API for updates.
|
||||||
|
- Ignore "Sent from my iPhone" (and similar) in mail updates.
|
||||||
|
- Use the NICKNAME_FMT constant for detecting nicknames.
|
||||||
|
- Check for site servername config'd.
|
||||||
|
- Compatibility fix for empty status updates with Twitter API.
|
||||||
|
- Option to show files privately (EXPERIMENTAL! Use with caution.)
|
||||||
|
|
||||||
Prerequisites
|
Prerequisites
|
||||||
=============
|
=============
|
||||||
|
@ -225,9 +256,9 @@ especially if you've previously installed PHP/MySQL packages.
|
||||||
1. Unpack the tarball you downloaded on your Web server. Usually a
|
1. Unpack the tarball you downloaded on your Web server. Usually a
|
||||||
command like this will work:
|
command like this will work:
|
||||||
|
|
||||||
tar zxf statusnet-0.8.1.tar.gz
|
tar zxf statusnet-0.8.2.tar.gz
|
||||||
|
|
||||||
...which will make a statusnet-0.8.1 subdirectory in your current
|
...which will make a statusnet-0.8.2 subdirectory in your current
|
||||||
directory. (If you don't have shell access on your Web server, you
|
directory. (If you don't have shell access on your Web server, you
|
||||||
may have to unpack the tarball on your local computer and FTP the
|
may have to unpack the tarball on your local computer and FTP the
|
||||||
files to the server.)
|
files to the server.)
|
||||||
|
@ -235,7 +266,7 @@ especially if you've previously installed PHP/MySQL packages.
|
||||||
2. Move the tarball to a directory of your choosing in your Web root
|
2. Move the tarball to a directory of your choosing in your Web root
|
||||||
directory. Usually something like this will work:
|
directory. Usually something like this will work:
|
||||||
|
|
||||||
mv statusnet-0.8.1 /var/www/mublog
|
mv statusnet-0.8.2 /var/www/mublog
|
||||||
|
|
||||||
This will make your StatusNet instance available in the mublog path of
|
This will make your StatusNet instance available in the mublog path of
|
||||||
your server, like "http://example.net/mublog". "microblog" or
|
your server, like "http://example.net/mublog". "microblog" or
|
||||||
|
@ -526,10 +557,6 @@ This will run eight (for now) queue handlers:
|
||||||
of registered users.
|
of registered users.
|
||||||
* xmppconfirmhandler.php - sends confirmation messages to registered
|
* xmppconfirmhandler.php - sends confirmation messages to registered
|
||||||
users.
|
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
|
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
|
particular, they leak memory, and you may want to restart them on a
|
||||||
|
@ -547,101 +574,6 @@ our kind of hacky home-grown DB-based queue solution. See the "queues"
|
||||||
config section below for how to configure to use STOMP. As of this
|
config section below for how to configure to use STOMP. As of this
|
||||||
writing, the software has been tested with ActiveMQ (
|
writing, the software has been tested with ActiveMQ (
|
||||||
|
|
||||||
Twitter Bridge
|
|
||||||
--------------
|
|
||||||
|
|
||||||
* OAuth
|
|
||||||
|
|
||||||
As of 0.8.1, OAuth is used to to access protected resources on Twitter
|
|
||||||
instead of HTTP Basic Auth. To use Twitter bridging you will need
|
|
||||||
to register your instance of StatusNet as an application on Twitter
|
|
||||||
(http://twitter.com/apps), and update the following variables in your
|
|
||||||
config.php with the consumer key and secret Twitter generates for you:
|
|
||||||
|
|
||||||
$config['twitter']['consumer_key'] = 'YOURKEY';
|
|
||||||
$config['twitter']['consumer_secret'] = 'YOURSECRET';
|
|
||||||
|
|
||||||
When registering your application with Twitter set the type to "Browser"
|
|
||||||
and your Callback URL to:
|
|
||||||
|
|
||||||
http://example.org/mublog/twitter/authorization
|
|
||||||
|
|
||||||
The default access type should be, "Read & Write".
|
|
||||||
|
|
||||||
* Importing statuses from Twitter
|
|
||||||
|
|
||||||
To allow your users to import their friends' Twitter statuses, you will
|
|
||||||
need to enable the bidirectional Twitter bridge in config.php:
|
|
||||||
|
|
||||||
$config['twitterbridge']['enabled'] = true;
|
|
||||||
|
|
||||||
and run the TwitterStatusFetcher daemon (scripts/twitterstatusfetcher.php).
|
|
||||||
Additionally, you will want to set the integration source variable,
|
|
||||||
which will keep notices posted to Twitter via StatusNet from looping
|
|
||||||
back. The integration source should be set to the name of your
|
|
||||||
application, exactly as you specified it on the settings page for your
|
|
||||||
StatusNet application on Twitter, e.g.:
|
|
||||||
|
|
||||||
$config['integration']['source'] = 'YourApp';
|
|
||||||
|
|
||||||
* Twitter Friends Syncing
|
|
||||||
|
|
||||||
Users may set a flag in their settings ("Subscribe to my Twitter friends
|
|
||||||
here" under the Twitter tab) to have StatusNet attempt to locate and
|
|
||||||
subscribe to "friends" (people they "follow") on Twitter who also have
|
|
||||||
accounts on your StatusNet system, and who have previously set up a link
|
|
||||||
for automatically posting notices to Twitter.
|
|
||||||
|
|
||||||
As of 0.8.0, this is no longer accomplished via a cron job. Instead you
|
|
||||||
must run the SyncTwitterFriends daemon (scripts/synctwitterfreinds.php).
|
|
||||||
|
|
||||||
Built-in Facebook Application
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
StatusNet'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 StatusNet 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:
|
|
||||||
|
|
||||||
- Canvas Callback URL: http://example.net/mublog/facebook/
|
|
||||||
- Post-Remove Callback URL: http://example.net/mublog/facebook/remove
|
|
||||||
- Post-Add Redirect URL: http://apps.facebook.com/yourapp/
|
|
||||||
- Canvas Page URL: http://apps.facebook.com/yourapp/
|
|
||||||
|
|
||||||
(Replace 'example.net' with your host's URL, 'mublog' with the path
|
|
||||||
to your StatusNet 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
|
|
||||||
StatusNet wiki:
|
|
||||||
|
|
||||||
http://status.net/trac/wiki/FacebookApplication
|
|
||||||
|
|
||||||
Sitemaps
|
Sitemaps
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
@ -755,6 +687,16 @@ private site, but users of the private site may be able to subscribe
|
||||||
to users on a remote site. (Or not... it's not well tested.) The
|
to users on a remote site. (Or not... it's not well tested.) The
|
||||||
"proper behaviour" hasn't been defined here, so handle with care.
|
"proper behaviour" hasn't been defined here, so handle with care.
|
||||||
|
|
||||||
|
If fancy URLs is enabled, access to file attachments can also be
|
||||||
|
restricted to logged-in users only. Uncomment the appropriate rewrite
|
||||||
|
<<<<<<< HEAD:README
|
||||||
|
rule in .htaccess or your server's httpd.conf. (This most likely will
|
||||||
|
not work if you are using a virtual server for attachments, so consider
|
||||||
|
the performance/security tradeoff.)
|
||||||
|
=======
|
||||||
|
rule in .htaccess or your server's httpd.conf.
|
||||||
|
>>>>>>> 446de62... Revert "Added some explanatory text to README":README
|
||||||
|
|
||||||
Upgrading
|
Upgrading
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
@ -768,7 +710,7 @@ with this situation.
|
||||||
If you've been using StatusNet 0.7, 0.6, 0.5 or lower, or if you've
|
If you've been using StatusNet 0.7, 0.6, 0.5 or lower, or if you've
|
||||||
been tracking the "git" version of the software, you will probably
|
been tracking the "git" version of the software, you will probably
|
||||||
want to upgrade and keep your existing data. There is no automated
|
want to upgrade and keep your existing data. There is no automated
|
||||||
upgrade procedure in StatusNet 0.8.1. Try these step-by-step
|
upgrade procedure in StatusNet 0.8.2. Try these step-by-step
|
||||||
instructions; read to the end first before trying them.
|
instructions; read to the end first before trying them.
|
||||||
|
|
||||||
0. Download StatusNet and set up all the prerequisites as if you were
|
0. Download StatusNet and set up all the prerequisites as if you were
|
||||||
|
@ -789,7 +731,7 @@ instructions; read to the end first before trying them.
|
||||||
5. Once all writing processes to your site are turned off, make a
|
5. Once all writing processes to your site are turned off, make a
|
||||||
final backup of the Web directory and database.
|
final backup of the Web directory and database.
|
||||||
6. Move your StatusNet directory to a backup spot, like "mublog.bak".
|
6. Move your StatusNet directory to a backup spot, like "mublog.bak".
|
||||||
7. Unpack your StatusNet 0.8.1 tarball and move it to "mublog" or
|
7. Unpack your StatusNet 0.8.2 tarball and move it to "mublog" or
|
||||||
wherever your code used to be.
|
wherever your code used to be.
|
||||||
8. Copy the config.php file and avatar directory from your old
|
8. Copy the config.php file and avatar directory from your old
|
||||||
directory to your new directory.
|
directory to your new directory.
|
||||||
|
@ -1251,24 +1193,11 @@ For SMS integration.
|
||||||
enabled: Whether to enable SMS integration. Defaults to true. Queues
|
enabled: Whether to enable SMS integration. Defaults to true. Queues
|
||||||
should also be enabled.
|
should also be enabled.
|
||||||
|
|
||||||
twitter
|
|
||||||
-------
|
|
||||||
|
|
||||||
For Twitter integration
|
|
||||||
|
|
||||||
enabled: Whether to enable Twitter integration. Defaults to true.
|
|
||||||
Queues should also be enabled.
|
|
||||||
|
|
||||||
integration
|
integration
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
A catch-all for integration with other systems.
|
A catch-all for integration with other systems.
|
||||||
|
|
||||||
source: The name to use for the source of posts to Twitter. Defaults
|
|
||||||
to 'statusnet', but if you request your own source name from
|
|
||||||
Twitter <http://twitter.com/help/request_source>, you can use
|
|
||||||
that here instead. Status updates on Twitter will then have
|
|
||||||
links to your site.
|
|
||||||
taguri: base for tag:// URIs. Defaults to site-server + ',2009'.
|
taguri: base for tag:// URIs. Defaults to site-server + ',2009'.
|
||||||
|
|
||||||
inboxes
|
inboxes
|
||||||
|
@ -1446,15 +1375,6 @@ dir: directory to write backgrounds too. Default is '/background/'
|
||||||
path: path to backgrounds. Default is sub-path of install path; note
|
path: path to backgrounds. Default is sub-path of install path; note
|
||||||
that you may need to change this if you change site-path too.
|
that you may need to change this if you change site-path too.
|
||||||
|
|
||||||
twitterbridge
|
|
||||||
-------------
|
|
||||||
|
|
||||||
A bi-direction bridge to Twitter (http://twitter.com/).
|
|
||||||
|
|
||||||
enabled: default false. If true, will show user's Twitter friends'
|
|
||||||
notices in their inbox and faves pages, only to the user. You
|
|
||||||
must also run the twitterstatusfetcher.php script.
|
|
||||||
|
|
||||||
ping
|
ping
|
||||||
----
|
----
|
||||||
|
|
||||||
|
@ -1553,7 +1473,7 @@ repository (see below), and you get a compilation error ("unexpected
|
||||||
T_STRING") in the browser, check to see that you don't have any
|
T_STRING") in the browser, check to see that you don't have any
|
||||||
conflicts in your code.
|
conflicts in your code.
|
||||||
|
|
||||||
If you upgraded to StatusNet 0.8.1 without reading the "Notice
|
If you upgraded to StatusNet 0.8.2 without reading the "Notice
|
||||||
inboxes" section above, and all your users' 'Personal' tabs are empty,
|
inboxes" section above, and all your users' 'Personal' tabs are empty,
|
||||||
read the "Notice inboxes" section above.
|
read the "Notice inboxes" section above.
|
||||||
|
|
||||||
|
@ -1661,6 +1581,7 @@ if anyone's been overlooked in error.
|
||||||
* Jeffery To
|
* Jeffery To
|
||||||
* Federico Marani
|
* Federico Marani
|
||||||
* Craig Andrews
|
* Craig Andrews
|
||||||
|
* mEDI
|
||||||
|
|
||||||
Thanks also to the developers of our upstream library code and to the
|
Thanks also to the developers of our upstream library code and to the
|
||||||
thousands of people who have tried out Identi.ca, installed StatusNet,
|
thousands of people who have tried out Identi.ca, installed StatusNet,
|
||||||
|
|
|
@ -99,19 +99,17 @@ class AllAction extends ProfileAction
|
||||||
sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->user->nickname)),
|
sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->user->nickname)),
|
||||||
new Feed(Feed::RSS2,
|
new Feed(Feed::RSS2,
|
||||||
common_local_url(
|
common_local_url(
|
||||||
'api', array(
|
'ApiTimelineFriends', array(
|
||||||
'apiaction' => 'statuses',
|
'format' => 'rss',
|
||||||
'method' => 'friends_timeline',
|
'id' => $this->user->nickname
|
||||||
'argument' => $this->user->nickname.'.rss'
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->user->nickname)),
|
sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->user->nickname)),
|
||||||
new Feed(Feed::ATOM,
|
new Feed(Feed::ATOM,
|
||||||
common_local_url(
|
common_local_url(
|
||||||
'api', array(
|
'ApiTimelineFriends', array(
|
||||||
'apiaction' => 'statuses',
|
'format' => 'atom',
|
||||||
'method' => 'friends_timeline',
|
'id' => $this->user->nickname
|
||||||
'argument' => $this->user->nickname.'.atom'
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
sprintf(_('Feed for friends of %s (Atom)'), $this->user->nickname))
|
sprintf(_('Feed for friends of %s (Atom)'), $this->user->nickname))
|
||||||
|
|
|
@ -157,7 +157,7 @@ class ApiDirectMessageNewAction extends ApiAuthAction
|
||||||
// Note: sending msgs to yourself is allowed by Twitter
|
// Note: sending msgs to yourself is allowed by Twitter
|
||||||
|
|
||||||
$errmsg = 'Don\'t send a message to yourself; ' .
|
$errmsg = 'Don\'t send a message to yourself; ' .
|
||||||
'just say it to yourself quietly instead.'
|
'just say it to yourself quietly instead.';
|
||||||
|
|
||||||
$this->clientError(_($errmsg), 403, $this->format);
|
$this->clientError(_($errmsg), 403, $this->format);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -127,7 +127,7 @@ class ApiFavoriteCreateAction extends ApiAuthAction
|
||||||
|
|
||||||
if (empty($fave)) {
|
if (empty($fave)) {
|
||||||
$this->clientError(
|
$this->clientError(
|
||||||
_('Could not create favorite.')
|
_('Could not create favorite.'),
|
||||||
403,
|
403,
|
||||||
$this->format
|
$this->format
|
||||||
);
|
);
|
||||||
|
|
|
@ -38,6 +38,7 @@ if (!defined('STATUSNET')) {
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once INSTALLDIR . '/lib/apiauth.php';
|
require_once INSTALLDIR . '/lib/apiauth.php';
|
||||||
|
require_once INSTALLDIR . '/lib/mediafile.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the authenticating user's status (posts a notice).
|
* Updates the authenticating user's status (posts a notice).
|
||||||
|
@ -60,7 +61,6 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
||||||
var $source = null;
|
var $source = null;
|
||||||
var $status = null;
|
var $status = null;
|
||||||
var $in_reply_to_status_id = null;
|
var $in_reply_to_status_id = null;
|
||||||
|
|
||||||
static $reserved_sources = array('web', 'omb', 'mail', 'xmpp', 'api');
|
static $reserved_sources = array('web', 'omb', 'mail', 'xmpp', 'api');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,25 +76,8 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
||||||
{
|
{
|
||||||
parent::prepare($args);
|
parent::prepare($args);
|
||||||
|
|
||||||
$this->user = $this->auth_user;
|
$this->user = $this->auth_user;
|
||||||
|
|
||||||
if (empty($this->user)) {
|
|
||||||
$this->clientError(_('No such user!'), 404, $this->format);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->status = $this->trimmed('status');
|
$this->status = $this->trimmed('status');
|
||||||
|
|
||||||
if (empty($this->status)) {
|
|
||||||
$this->clientError(
|
|
||||||
'Client must provide a \'status\' parameter with a value.',
|
|
||||||
400,
|
|
||||||
$this->format
|
|
||||||
);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->source = $this->trimmed('source');
|
$this->source = $this->trimmed('source');
|
||||||
|
|
||||||
if (empty($this->source) || in_array($source, $this->reserved_sources)) {
|
if (empty($this->source) || in_array($source, $this->reserved_sources)) {
|
||||||
|
@ -129,6 +112,27 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (empty($this->status)) {
|
||||||
|
$this->clientError(
|
||||||
|
'Client must provide a \'status\' parameter with a value.',
|
||||||
|
400,
|
||||||
|
$this->format
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($this->user)) {
|
||||||
|
$this->clientError(_('No such user!'), 404, $this->format);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Workaround for PHP returning empty $_FILES when POST length > PHP settings
|
||||||
|
|
||||||
|
if (empty($_POST) && ($_SERVER['CONTENT_LENGTH'] > 0)) {
|
||||||
|
$this->clientError(_('Unable to handle that much POST data!'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$status_shortened = common_shorten_links($this->status);
|
$status_shortened = common_shorten_links($this->status);
|
||||||
|
|
||||||
if (Notice::contentTooLong($status_shortened)) {
|
if (Notice::contentTooLong($status_shortened)) {
|
||||||
|
@ -187,14 +191,40 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$upload = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$upload = MediaFile::fromUpload('media', $this->user);
|
||||||
|
} catch (ClientException $ce) {
|
||||||
|
$this->clientError($ce->getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($upload)) {
|
||||||
|
$status_shortened .= ' ' . $upload->shortUrl();
|
||||||
|
|
||||||
|
if (Notice::contentTooLong($status_shortened)) {
|
||||||
|
$upload->delete();
|
||||||
|
$msg = _(
|
||||||
|
'Max notice size is %d chars, ' .
|
||||||
|
'including attachment URL.'
|
||||||
|
);
|
||||||
|
$this->clientError(sprintf($msg, Notice::maxContent()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->notice = Notice::saveNew(
|
$this->notice = Notice::saveNew(
|
||||||
$this->user->id,
|
$this->user->id,
|
||||||
html_entity_decode($this->status, ENT_NOQUOTES, 'UTF-8'),
|
html_entity_decode($status_shortened, ENT_NOQUOTES, 'UTF-8'),
|
||||||
$this->source,
|
$this->source,
|
||||||
1,
|
1,
|
||||||
$reply_to
|
$reply_to
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (isset($upload)) {
|
||||||
|
$upload->attachToNotice($this->notice);
|
||||||
|
}
|
||||||
|
|
||||||
common_broadcast_notice($this->notice);
|
common_broadcast_notice($this->notice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
75
actions/bookmarklet.php
Normal file
75
actions/bookmarklet.php
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Handler for posting new notices
|
||||||
|
*
|
||||||
|
* 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 Bookmarklet
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Sarven Capadisli <csarven@status.net>
|
||||||
|
* @copyright 2008-2009 StatusNet, Inc.
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once INSTALLDIR . '/actions/newnotice.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action for posting a notice
|
||||||
|
*
|
||||||
|
* @category Bookmarklet
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Sarven Capadisli <csarven@status.net>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
class BookmarkletAction extends NewnoticeAction
|
||||||
|
{
|
||||||
|
function showTitle()
|
||||||
|
{
|
||||||
|
$this->element('title', null, _('Post to ').common_config('site', 'name'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function showHeader()
|
||||||
|
{
|
||||||
|
$this->elementStart('div', array('id' => 'header'));
|
||||||
|
$this->elementStart('address');
|
||||||
|
$this->element('a', array('class' => 'url',
|
||||||
|
'href' => common_local_url('public')),
|
||||||
|
'');
|
||||||
|
$this->elementEnd('address');
|
||||||
|
if (common_logged_in()) {
|
||||||
|
$this->showNoticeForm();
|
||||||
|
}
|
||||||
|
$this->elementEnd('div');
|
||||||
|
}
|
||||||
|
|
||||||
|
function showCore()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
function showFooter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -326,7 +326,7 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||||
$this->showForm(_('Cannot normalize that email address'));
|
$this->showForm(_('Cannot normalize that email address'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!Validate::email($email, true)) {
|
if (!Validate::email($email, common_config('email', 'check_domain'))) {
|
||||||
$this->showForm(_('Not a valid email address'));
|
$this->showForm(_('Not a valid email address'));
|
||||||
return;
|
return;
|
||||||
} else if ($user->email == $email) {
|
} else if ($user->email == $email) {
|
||||||
|
|
145
actions/getfile.php
Normal file
145
actions/getfile.php
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Returns a given file attachment, allowing private sites to only allow
|
||||||
|
* access to file attachments after login.
|
||||||
|
*
|
||||||
|
* 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 Personal
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Jeffery To <jeffery.to@gmail.com>
|
||||||
|
* @copyright 2008-2009 StatusNet, Inc.
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once 'MIME/Type.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action for getting a file attachment
|
||||||
|
*
|
||||||
|
* @category Personal
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Jeffery To <jeffery.to@gmail.com>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
class GetfileAction extends Action
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Path of file to return
|
||||||
|
*/
|
||||||
|
|
||||||
|
var $path = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get file name
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST array
|
||||||
|
*
|
||||||
|
* @return success flag
|
||||||
|
*/
|
||||||
|
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
|
||||||
|
$filename = $this->trimmed('filename');
|
||||||
|
$path = null;
|
||||||
|
|
||||||
|
if ($filename) {
|
||||||
|
$path = common_config('attachments', 'dir') . $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($path) or !file_exists($path)) {
|
||||||
|
$this->clientError(_('No such file.'), 404);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_readable($path)) {
|
||||||
|
$this->clientError(_('Cannot read file.'), 403);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->path = $path;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this page read-only?
|
||||||
|
*
|
||||||
|
* @return boolean true
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last-modified date for file
|
||||||
|
*
|
||||||
|
* @return int last-modified date as unix timestamp
|
||||||
|
*/
|
||||||
|
|
||||||
|
function lastModified()
|
||||||
|
{
|
||||||
|
return filemtime($this->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* etag for file
|
||||||
|
*
|
||||||
|
* This returns the same data (inode, size, mtime) as Apache would,
|
||||||
|
* but in decimal instead of hex.
|
||||||
|
*
|
||||||
|
* @return string etag http header
|
||||||
|
*/
|
||||||
|
function etag()
|
||||||
|
{
|
||||||
|
$stat = stat($this->path);
|
||||||
|
return '"' . $stat['ino'] . '-' . $stat['size'] . '-' . $stat['mtime'] . '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle input, produce output
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST contents
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
// undo headers set by PHP sessions
|
||||||
|
$sec = session_cache_expire() * 60;
|
||||||
|
header('Expires: ' . date(DATE_RFC1123, time() + $sec));
|
||||||
|
header('Cache-Control: public, max-age=' . $sec);
|
||||||
|
header('Pragma: public');
|
||||||
|
|
||||||
|
parent::handle($args);
|
||||||
|
|
||||||
|
$path = $this->path;
|
||||||
|
header('Content-Type: ' . MIME_Type::autoDetect($path));
|
||||||
|
readfile($path);
|
||||||
|
}
|
||||||
|
}
|
|
@ -179,9 +179,12 @@ class GroupMemberListItem extends ProfileListItem
|
||||||
function showActions()
|
function showActions()
|
||||||
{
|
{
|
||||||
$this->startActions();
|
$this->startActions();
|
||||||
$this->showSubscribeButton();
|
if (Event::handle('StartProfileListItemActionElements', array($this))) {
|
||||||
$this->showMakeAdminForm();
|
$this->showSubscribeButton();
|
||||||
$this->showGroupBlockForm();
|
$this->showMakeAdminForm();
|
||||||
|
$this->showGroupBlockForm();
|
||||||
|
Event::handle('EndProfileListItemActionElements', array($this));
|
||||||
|
}
|
||||||
$this->endActions();
|
$this->endActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ class InviteAction extends CurrentUserDesignAction
|
||||||
|
|
||||||
foreach ($addresses as $email) {
|
foreach ($addresses as $email) {
|
||||||
$email = trim($email);
|
$email = trim($email);
|
||||||
if (!Validate::email($email, true)) {
|
if (!Validate::email($email, common_config('email', 'check_domain'))) {
|
||||||
$this->showForm(sprintf(_('Invalid email address: %s'), $email));
|
$this->showForm(sprintf(_('Invalid email address: %s'), $email));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,9 @@ class NewmessageAction extends Action
|
||||||
$user = common_current_user();
|
$user = common_current_user();
|
||||||
|
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
$this->clientError(_('Only logged-in users can send direct messages.'), 403);
|
/* Go log in, and then come back. */
|
||||||
|
common_set_returnto($_SERVER['REQUEST_URI']);
|
||||||
|
common_redirect(common_local_url('login'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +223,22 @@ class NewmessageAction extends Action
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->msg = $msg;
|
$this->msg = $msg;
|
||||||
$this->showPage();
|
if ($this->trimmed('ajax')) {
|
||||||
|
$this->startHTML('text/xml;charset=UTF-8');
|
||||||
|
$this->elementStart('head');
|
||||||
|
$this->element('title', null, _('New message'));
|
||||||
|
$this->elementEnd('head');
|
||||||
|
$this->elementStart('body');
|
||||||
|
if (common_logged_in()) {
|
||||||
|
$this->showNoticeForm();
|
||||||
|
}
|
||||||
|
$this->elementEnd('div');
|
||||||
|
$this->elementEnd('body');
|
||||||
|
$this->endHTML();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->showPage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showPageNotice()
|
function showPageNotice()
|
||||||
|
|
|
@ -33,7 +33,8 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once INSTALLDIR.'/lib/noticelist.php';
|
require_once INSTALLDIR . '/lib/noticelist.php';
|
||||||
|
require_once INSTALLDIR . '/lib/mediafile.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action for posting new notices
|
* Action for posting new notices
|
||||||
|
@ -113,33 +114,6 @@ class NewnoticeAction extends Action
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUploadedFileType() {
|
|
||||||
require_once 'MIME/Type.php';
|
|
||||||
|
|
||||||
$cmd = &PEAR::getStaticProperty('MIME_Type', 'fileCmd');
|
|
||||||
$cmd = common_config('attachments', 'filecommand');
|
|
||||||
|
|
||||||
$filetype = MIME_Type::autoDetect($_FILES['attach']['tmp_name']);
|
|
||||||
if (in_array($filetype, common_config('attachments', 'supported'))) {
|
|
||||||
return $filetype;
|
|
||||||
}
|
|
||||||
$media = MIME_Type::getMedia($filetype);
|
|
||||||
if ('application' !== $media) {
|
|
||||||
$hint = sprintf(_(' Try using another %s format.'), $media);
|
|
||||||
} else {
|
|
||||||
$hint = '';
|
|
||||||
}
|
|
||||||
$this->clientError(sprintf(
|
|
||||||
_('%s is not a supported filetype on this server.'), $filetype) . $hint);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isRespectsQuota($user) {
|
|
||||||
$file = new File;
|
|
||||||
$ret = $file->isRespectsQuota($user,$_FILES['attach']['size']);
|
|
||||||
if (true === $ret) return true;
|
|
||||||
$this->clientError($ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a new notice, based on arguments
|
* Save a new notice, based on arguments
|
||||||
*
|
*
|
||||||
|
@ -160,18 +134,12 @@ class NewnoticeAction extends Action
|
||||||
|
|
||||||
if (!$content) {
|
if (!$content) {
|
||||||
$this->clientError(_('No content!'));
|
$this->clientError(_('No content!'));
|
||||||
} else {
|
return;
|
||||||
$content_shortened = common_shorten_links($content);
|
|
||||||
if (Notice::contentTooLong($content_shortened)) {
|
|
||||||
$this->clientError(sprintf(_('That\'s too long. '.
|
|
||||||
'Max notice size is %d chars.'),
|
|
||||||
Notice::maxContent()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$inter = new CommandInterpreter();
|
$inter = new CommandInterpreter();
|
||||||
|
|
||||||
$cmd = $inter->handle_command($user, $content_shortened);
|
$cmd = $inter->handle_command($user, $content);
|
||||||
|
|
||||||
if ($cmd) {
|
if ($cmd) {
|
||||||
if ($this->boolean('ajax')) {
|
if ($this->boolean('ajax')) {
|
||||||
|
@ -182,6 +150,13 @@ class NewnoticeAction extends Action
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$content_shortened = common_shorten_links($content);
|
||||||
|
if (Notice::contentTooLong($content_shortened)) {
|
||||||
|
$this->clientError(sprintf(_('That\'s too long. '.
|
||||||
|
'Max notice size is %d chars.'),
|
||||||
|
Notice::maxContent()));
|
||||||
|
}
|
||||||
|
|
||||||
$replyto = $this->trimmed('inreplyto');
|
$replyto = $this->trimmed('inreplyto');
|
||||||
#If an ID of 0 is wrongly passed here, it will cause a database error,
|
#If an ID of 0 is wrongly passed here, it will cause a database error,
|
||||||
#so override it...
|
#so override it...
|
||||||
|
@ -189,84 +164,37 @@ class NewnoticeAction extends Action
|
||||||
$replyto = 'false';
|
$replyto = 'false';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_FILES['attach']['error'])) {
|
$upload = null;
|
||||||
switch ($_FILES['attach']['error']) {
|
$upload = MediaFile::fromUpload('attach');
|
||||||
case UPLOAD_ERR_NO_FILE:
|
|
||||||
// no file uploaded, nothing to do
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UPLOAD_ERR_OK:
|
if (isset($upload)) {
|
||||||
$mimetype = $this->getUploadedFileType();
|
|
||||||
if (!$this->isRespectsQuota($user)) {
|
|
||||||
die('clientError() should trigger an exception before reaching here.');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UPLOAD_ERR_INI_SIZE:
|
$content_shortened .= ' ' . $upload->shortUrl();
|
||||||
$this->clientError(_('The uploaded file exceeds the upload_max_filesize directive in php.ini.'));
|
|
||||||
|
|
||||||
case UPLOAD_ERR_FORM_SIZE:
|
|
||||||
$this->clientError(_('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'));
|
|
||||||
|
|
||||||
case UPLOAD_ERR_PARTIAL:
|
|
||||||
$this->clientError(_('The uploaded file was only partially uploaded.'));
|
|
||||||
|
|
||||||
case UPLOAD_ERR_NO_TMP_DIR:
|
|
||||||
$this->clientError(_('Missing a temporary folder.'));
|
|
||||||
|
|
||||||
case UPLOAD_ERR_CANT_WRITE:
|
|
||||||
$this->clientError(_('Failed to write file to disk.'));
|
|
||||||
|
|
||||||
case UPLOAD_ERR_EXTENSION:
|
|
||||||
$this->clientError(_('File upload stopped by extension.'));
|
|
||||||
|
|
||||||
default:
|
|
||||||
die('Should never reach here.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($mimetype)) {
|
|
||||||
$filename = $this->saveFile($mimetype);
|
|
||||||
if (empty($filename)) {
|
|
||||||
$this->clientError(_('Couldn\'t save file.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$fileRecord = $this->storeFile($filename, $mimetype);
|
|
||||||
|
|
||||||
$fileurl = common_local_url('attachment',
|
|
||||||
array('attachment' => $fileRecord->id));
|
|
||||||
|
|
||||||
// not sure this is necessary -- Zach
|
|
||||||
$this->maybeAddRedir($fileRecord->id, $fileurl);
|
|
||||||
|
|
||||||
$short_fileurl = common_shorten_url($fileurl);
|
|
||||||
if (!$short_fileurl) {
|
|
||||||
// todo -- Consider forcing default shortener if none selected?
|
|
||||||
$short_fileurl = $fileurl;
|
|
||||||
}
|
|
||||||
$content_shortened .= ' ' . $short_fileurl;
|
|
||||||
|
|
||||||
if (Notice::contentTooLong($content_shortened)) {
|
if (Notice::contentTooLong($content_shortened)) {
|
||||||
$this->deleteFile($filename);
|
$upload->delete();
|
||||||
$this->clientError(sprintf(_('Max notice size is %d chars, including attachment URL.'),
|
$this->clientError(
|
||||||
Notice::maxContent()));
|
sprintf(
|
||||||
|
_('Max notice size is %d chars, including attachment URL.'),
|
||||||
|
Notice::maxContent()
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also, not sure this is necessary -- Zach
|
|
||||||
$this->maybeAddRedir($fileRecord->id, $short_fileurl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$notice = Notice::saveNew($user->id, $content_shortened, 'web', 1,
|
$notice = Notice::saveNew($user->id, $content_shortened, 'web', 1,
|
||||||
($replyto == 'false') ? null : $replyto);
|
($replyto == 'false') ? null : $replyto);
|
||||||
|
|
||||||
if (isset($mimetype)) {
|
if (isset($upload)) {
|
||||||
$this->attachFile($notice, $fileRecord);
|
$upload->attachToNotice($notice);
|
||||||
}
|
}
|
||||||
|
|
||||||
common_broadcast_notice($notice);
|
common_broadcast_notice($notice);
|
||||||
|
|
||||||
if ($this->boolean('ajax')) {
|
if ($this->boolean('ajax')) {
|
||||||
$this->startHTML('text/xml;charset=utf-8');
|
header('Content-Type: text/xml;charset=utf-8');
|
||||||
|
$this->xw->startDocument('1.0', 'UTF-8');
|
||||||
|
$this->elementStart('html');
|
||||||
$this->elementStart('head');
|
$this->elementStart('head');
|
||||||
$this->element('title', null, _('Notice posted'));
|
$this->element('title', null, _('Notice posted'));
|
||||||
$this->elementEnd('head');
|
$this->elementEnd('head');
|
||||||
|
@ -288,87 +216,6 @@ class NewnoticeAction extends Action
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveFile($mimetype) {
|
|
||||||
|
|
||||||
$cur = common_current_user();
|
|
||||||
|
|
||||||
if (empty($cur)) {
|
|
||||||
$this->serverError(_('Somehow lost the login in saveFile'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$basename = basename($_FILES['attach']['name']);
|
|
||||||
|
|
||||||
$filename = File::filename($cur->getProfile(), $basename, $mimetype);
|
|
||||||
|
|
||||||
$filepath = File::path($filename);
|
|
||||||
|
|
||||||
if (move_uploaded_file($_FILES['attach']['tmp_name'], $filepath)) {
|
|
||||||
return $filename;
|
|
||||||
} else {
|
|
||||||
$this->clientError(_('File could not be moved to destination directory.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteFile($filename)
|
|
||||||
{
|
|
||||||
$filepath = File::path($filename);
|
|
||||||
@unlink($filepath);
|
|
||||||
}
|
|
||||||
|
|
||||||
function storeFile($filename, $mimetype) {
|
|
||||||
|
|
||||||
$file = new File;
|
|
||||||
$file->filename = $filename;
|
|
||||||
|
|
||||||
$file->url = File::url($filename);
|
|
||||||
|
|
||||||
$filepath = File::path($filename);
|
|
||||||
|
|
||||||
$file->size = filesize($filepath);
|
|
||||||
$file->date = time();
|
|
||||||
$file->mimetype = $mimetype;
|
|
||||||
|
|
||||||
$file_id = $file->insert();
|
|
||||||
|
|
||||||
if (!$file_id) {
|
|
||||||
common_log_db_error($file, "INSERT", __FILE__);
|
|
||||||
$this->clientError(_('There was a database error while saving your file. Please try again.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $file;
|
|
||||||
}
|
|
||||||
|
|
||||||
function rememberFile($file, $short)
|
|
||||||
{
|
|
||||||
$this->maybeAddRedir($file->id, $short);
|
|
||||||
}
|
|
||||||
|
|
||||||
function maybeAddRedir($file_id, $url)
|
|
||||||
{
|
|
||||||
$file_redir = File_redirection::staticGet('url', $url);
|
|
||||||
|
|
||||||
if (empty($file_redir)) {
|
|
||||||
$file_redir = new File_redirection;
|
|
||||||
$file_redir->url = $url;
|
|
||||||
$file_redir->file_id = $file_id;
|
|
||||||
|
|
||||||
$result = $file_redir->insert();
|
|
||||||
|
|
||||||
if (!$result) {
|
|
||||||
common_log_db_error($file_redir, "INSERT", __FILE__);
|
|
||||||
$this->clientError(_('There was a database error while saving your file. Please try again.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function attachFile($notice, $filerec)
|
|
||||||
{
|
|
||||||
File_to_post::processNew($filerec->id, $notice->id);
|
|
||||||
|
|
||||||
$this->maybeAddRedir($filerec->id,
|
|
||||||
common_local_url('file', array('notice' => $notice->id)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show an Ajax-y error message
|
* Show an Ajax-y error message
|
||||||
*
|
*
|
||||||
|
|
|
@ -103,7 +103,7 @@ class OthersettingsAction extends AccountSettingsAction
|
||||||
foreach($_shorteners as $name=>$value)
|
foreach($_shorteners as $name=>$value)
|
||||||
{
|
{
|
||||||
$services[$name]=$name;
|
$services[$name]=$name;
|
||||||
if($value['info']['freeService']){
|
if(!empty($value['info']['freeService'])){
|
||||||
// I18N
|
// I18N
|
||||||
$services[$name].=' (free service)';
|
$services[$name].=' (free service)';
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,6 +306,16 @@ class ProfilesettingsAction extends AccountSettingsAction
|
||||||
$profile->homepage = $homepage;
|
$profile->homepage = $homepage;
|
||||||
$profile->bio = $bio;
|
$profile->bio = $bio;
|
||||||
$profile->location = $location;
|
$profile->location = $location;
|
||||||
|
|
||||||
|
$loc = Location::fromName($location);
|
||||||
|
|
||||||
|
if (!empty($loc)) {
|
||||||
|
$profile->lat = $loc->lat;
|
||||||
|
$profile->lon = $loc->lon;
|
||||||
|
$profile->location_id = $loc->location_id;
|
||||||
|
$profile->location_ns = $loc->location_ns;
|
||||||
|
}
|
||||||
|
|
||||||
$profile->profileurl = common_profile_url($nickname);
|
$profile->profileurl = common_profile_url($nickname);
|
||||||
|
|
||||||
common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__);
|
common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__);
|
||||||
|
|
|
@ -132,6 +132,13 @@ class PublicAction extends Action
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function extraHead()
|
||||||
|
{
|
||||||
|
parent::extraHead();
|
||||||
|
$this->element('meta', array('http-equiv' => 'X-XRDS-Location',
|
||||||
|
'content' => common_local_url('publicxrds')));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output <head> elements for RSS and Atom feeds
|
* Output <head> elements for RSS and Atom feeds
|
||||||
*
|
*
|
||||||
|
@ -143,14 +150,12 @@ class PublicAction extends Action
|
||||||
return array(new Feed(Feed::RSS1, common_local_url('publicrss'),
|
return array(new Feed(Feed::RSS1, common_local_url('publicrss'),
|
||||||
_('Public Stream Feed (RSS 1.0)')),
|
_('Public Stream Feed (RSS 1.0)')),
|
||||||
new Feed(Feed::RSS2,
|
new Feed(Feed::RSS2,
|
||||||
common_local_url('api',
|
common_local_url('ApiTimelinePublic',
|
||||||
array('apiaction' => 'statuses',
|
array('format' => 'rss')),
|
||||||
'method' => 'public_timeline.rss')),
|
|
||||||
_('Public Stream Feed (RSS 2.0)')),
|
_('Public Stream Feed (RSS 2.0)')),
|
||||||
new Feed(Feed::ATOM,
|
new Feed(Feed::ATOM,
|
||||||
common_local_url('api',
|
common_local_url('ApiTimelinePublic',
|
||||||
array('apiaction' => 'statuses',
|
array('format' => 'atom')),
|
||||||
'method' => 'public_timeline.atom')),
|
|
||||||
_('Public Stream Feed (Atom)')));
|
_('Public Stream Feed (Atom)')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
81
actions/publicxrds.php
Normal file
81
actions/publicxrds.php
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public XRDS for OpenID
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* @category Action
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @author Robin Millette <millette@status.net>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||||
|
* @link http://status.net/
|
||||||
|
*
|
||||||
|
* StatusNet - the distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2008, 2009, StatusNet, 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('STATUSNET') && !defined('LACONICA')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once INSTALLDIR.'/plugins/OpenID/openid.php';
|
||||||
|
require_once INSTALLDIR.'/lib/xrdsoutputter.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public XRDS
|
||||||
|
*
|
||||||
|
* @category Action
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @author Robin Millette <millette@status.net>
|
||||||
|
* @author Craig Andrews <candrews@integralblue.com>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||||
|
* @link http://status.net/
|
||||||
|
*
|
||||||
|
* @todo factor out similarities with XrdsAction
|
||||||
|
*/
|
||||||
|
class PublicxrdsAction extends Action
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Is read only?
|
||||||
|
*
|
||||||
|
* @return boolean true
|
||||||
|
*/
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class handler.
|
||||||
|
*
|
||||||
|
* @param array $args array of arguments
|
||||||
|
*
|
||||||
|
* @return nothing
|
||||||
|
*/
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
parent::handle($args);
|
||||||
|
$xrdsOutputter = new XRDSOutputter();
|
||||||
|
$xrdsOutputter->startXRDS();
|
||||||
|
Event::handle('StartPublicXRDS', array($this,&$xrdsOutputter));
|
||||||
|
Event::handle('EndPublicXRDS', array($this,&$xrdsOutputter));
|
||||||
|
$xrdsOutputter->endXRDS();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -191,7 +191,7 @@ class RegisterAction extends Action
|
||||||
if (!$this->boolean('license')) {
|
if (!$this->boolean('license')) {
|
||||||
$this->showForm(_('You can\'t register if you don\'t '.
|
$this->showForm(_('You can\'t register if you don\'t '.
|
||||||
'agree to the license.'));
|
'agree to the license.'));
|
||||||
} else if ($email && !Validate::email($email, true)) {
|
} else if ($email && !Validate::email($email, common_config('email', 'check_domain'))) {
|
||||||
$this->showForm(_('Not a valid email address.'));
|
$this->showForm(_('Not a valid email address.'));
|
||||||
} else if (!Validate::string($nickname, array('min_length' => 1,
|
} else if (!Validate::string($nickname, array('min_length' => 1,
|
||||||
'max_length' => 64,
|
'max_length' => 64,
|
||||||
|
|
|
@ -138,11 +138,25 @@ class RepliesAction extends OwnerDesignAction
|
||||||
|
|
||||||
function getFeeds()
|
function getFeeds()
|
||||||
{
|
{
|
||||||
$rssurl = common_local_url('repliesrss',
|
return array(new Feed(Feed::RSS1,
|
||||||
array('nickname' => $this->user->nickname));
|
common_local_url('repliesrss',
|
||||||
$rsstitle = sprintf(_('Feed for replies to %s'), $this->user->nickname);
|
array('nickname' => $this->user->nickname)),
|
||||||
|
sprintf(_('Replies feed for %s (RSS 1.0)'),
|
||||||
return array(new Feed(Feed::RSS1, $rssurl, $rsstitle));
|
$this->user->nickname)),
|
||||||
|
new Feed(Feed::RSS2,
|
||||||
|
common_local_url('ApiTimelineMentions',
|
||||||
|
array(
|
||||||
|
'id' => $this->user->nickname,
|
||||||
|
'format' => 'rss')),
|
||||||
|
sprintf(_('Replies feed for %s (RSS 2.0)'),
|
||||||
|
$this->user->nickname)),
|
||||||
|
new Feed(Feed::ATOM,
|
||||||
|
common_local_url('ApiTimelineMentions',
|
||||||
|
array(
|
||||||
|
'id' => $this->user->nickname,
|
||||||
|
'format' => 'atom')),
|
||||||
|
sprintf(_('Replies feed for %s (Atom)'),
|
||||||
|
$this->user->nickname)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -164,13 +164,25 @@ class ShowfavoritesAction extends OwnerDesignAction
|
||||||
|
|
||||||
function getFeeds()
|
function getFeeds()
|
||||||
{
|
{
|
||||||
$feedurl = common_local_url('favoritesrss',
|
return array(new Feed(Feed::RSS1,
|
||||||
array('nickname' =>
|
common_local_url('favoritesrss',
|
||||||
$this->user->nickname));
|
array('nickname' => $this->user->nickname)),
|
||||||
$feedtitle = sprintf(_('Feed for favorites of %s'),
|
sprintf(_('Feed for favorites of %s (RSS 1.0)'),
|
||||||
$this->user->nickname);
|
$this->user->nickname)),
|
||||||
|
new Feed(Feed::RSS2,
|
||||||
return array(new Feed(Feed::RSS1, $feedurl, $feedtitle));
|
common_local_url('ApiTimelineFavorites',
|
||||||
|
array(
|
||||||
|
'id' => $this->user->nickname,
|
||||||
|
'format' => 'rss')),
|
||||||
|
sprintf(_('Feed for favorites of %s (RSS 2.0)'),
|
||||||
|
$this->user->nickname)),
|
||||||
|
new Feed(Feed::ATOM,
|
||||||
|
common_local_url('ApiTimelineFavorites',
|
||||||
|
array(
|
||||||
|
'id' => $this->user->nickname,
|
||||||
|
'format' => 'atom')),
|
||||||
|
sprintf(_('Feed for favorites of %s (Atom)'),
|
||||||
|
$this->user->nickname)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -328,17 +328,15 @@ class ShowgroupAction extends GroupDesignAction
|
||||||
sprintf(_('Notice feed for %s group (RSS 1.0)'),
|
sprintf(_('Notice feed for %s group (RSS 1.0)'),
|
||||||
$this->group->nickname)),
|
$this->group->nickname)),
|
||||||
new Feed(Feed::RSS2,
|
new Feed(Feed::RSS2,
|
||||||
common_local_url('api',
|
common_local_url('ApiTimelineGroup',
|
||||||
array('apiaction' => 'groups',
|
array('format' => 'rss',
|
||||||
'method' => 'timeline',
|
'id' => $this->group->nickname)),
|
||||||
'argument' => $this->group->nickname.'.rss')),
|
|
||||||
sprintf(_('Notice feed for %s group (RSS 2.0)'),
|
sprintf(_('Notice feed for %s group (RSS 2.0)'),
|
||||||
$this->group->nickname)),
|
$this->group->nickname)),
|
||||||
new Feed(Feed::ATOM,
|
new Feed(Feed::ATOM,
|
||||||
common_local_url('api',
|
common_local_url('ApiTimelineGroup',
|
||||||
array('apiaction' => 'groups',
|
array('format' => 'atom',
|
||||||
'method' => 'timeline',
|
'id' => $this->group->nickname)),
|
||||||
'argument' => $this->group->nickname.'.atom')),
|
|
||||||
sprintf(_('Notice feed for %s group (Atom)'),
|
sprintf(_('Notice feed for %s group (Atom)'),
|
||||||
$this->group->nickname)),
|
$this->group->nickname)),
|
||||||
new Feed(Feed::FOAF,
|
new Feed(Feed::FOAF,
|
||||||
|
|
|
@ -172,9 +172,9 @@ class ShownoticeAction extends OwnerDesignAction
|
||||||
function title()
|
function title()
|
||||||
{
|
{
|
||||||
if (!empty($this->profile->fullname)) {
|
if (!empty($this->profile->fullname)) {
|
||||||
$base = $this->profile->fullname . ' (' . $this->user->nickname . ') ';
|
$base = $this->profile->fullname . ' (' . $this->profile->nickname . ') ';
|
||||||
} else {
|
} else {
|
||||||
$base = $this->user->nickname;
|
$base = $this->profile->nickname;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sprintf(_('%1$s\'s status on %2$s'),
|
return sprintf(_('%1$s\'s status on %2$s'),
|
||||||
|
|
|
@ -128,17 +128,17 @@ class ShowstreamAction extends ProfileAction
|
||||||
sprintf(_('Notice feed for %s (RSS 1.0)'),
|
sprintf(_('Notice feed for %s (RSS 1.0)'),
|
||||||
$this->user->nickname)),
|
$this->user->nickname)),
|
||||||
new Feed(Feed::RSS2,
|
new Feed(Feed::RSS2,
|
||||||
common_local_url('api',
|
common_local_url('ApiTimelineUser',
|
||||||
array('apiaction' => 'statuses',
|
array(
|
||||||
'method' => 'user_timeline',
|
'id' => $this->user->nickname,
|
||||||
'argument' => $this->user->nickname.'.rss')),
|
'format' => 'rss')),
|
||||||
sprintf(_('Notice feed for %s (RSS 2.0)'),
|
sprintf(_('Notice feed for %s (RSS 2.0)'),
|
||||||
$this->user->nickname)),
|
$this->user->nickname)),
|
||||||
new Feed(Feed::ATOM,
|
new Feed(Feed::ATOM,
|
||||||
common_local_url('api',
|
common_local_url('ApiTimelineUser',
|
||||||
array('apiaction' => 'statuses',
|
array(
|
||||||
'method' => 'user_timeline',
|
'id' => $this->user->nickname,
|
||||||
'argument' => $this->user->nickname.'.atom')),
|
'format' => 'atom')),
|
||||||
sprintf(_('Notice feed for %s (Atom)'),
|
sprintf(_('Notice feed for %s (Atom)'),
|
||||||
$this->user->nickname)),
|
$this->user->nickname)),
|
||||||
new Feed(Feed::FOAF,
|
new Feed(Feed::FOAF,
|
||||||
|
@ -348,6 +348,8 @@ class ShowstreamAction extends ProfileAction
|
||||||
{
|
{
|
||||||
if (Event::handle('StartProfilePageActionsSection', array(&$this, $this->profile))) {
|
if (Event::handle('StartProfilePageActionsSection', array(&$this, $this->profile))) {
|
||||||
|
|
||||||
|
$cur = common_current_user();
|
||||||
|
|
||||||
$this->elementStart('div', 'entity_actions');
|
$this->elementStart('div', 'entity_actions');
|
||||||
$this->element('h2', null, _('User actions'));
|
$this->element('h2', null, _('User actions'));
|
||||||
$this->elementStart('ul');
|
$this->elementStart('ul');
|
||||||
|
@ -379,21 +381,21 @@ class ShowstreamAction extends ProfileAction
|
||||||
}
|
}
|
||||||
$this->elementEnd('li');
|
$this->elementEnd('li');
|
||||||
|
|
||||||
if ($cur->mutuallySubscribed($user)) {
|
if ($cur->mutuallySubscribed($this->user)) {
|
||||||
|
|
||||||
// message
|
// message
|
||||||
|
|
||||||
$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)),
|
$this->element('a', array('href' => common_local_url('newmessage', array('to' => $this->user->id)),
|
||||||
'title' => _('Send a direct message to this user')),
|
'title' => _('Send a direct message to this user')),
|
||||||
_('Message'));
|
_('Message'));
|
||||||
$this->elementEnd('li');
|
$this->elementEnd('li');
|
||||||
|
|
||||||
// nudge
|
// nudge
|
||||||
|
|
||||||
if ($user->email && $user->emailnotifynudge) {
|
if ($this->user->email && $this->user->emailnotifynudge) {
|
||||||
$this->elementStart('li', 'entity_nudge');
|
$this->elementStart('li', 'entity_nudge');
|
||||||
$nf = new NudgeForm($this, $user);
|
$nf = new NudgeForm($this, $this->user);
|
||||||
$nf->show();
|
$nf->show();
|
||||||
$this->elementEnd('li');
|
$this->elementEnd('li');
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,17 +86,15 @@ class TagAction extends Action
|
||||||
sprintf(_('Notice feed for tag %s (RSS 1.0)'),
|
sprintf(_('Notice feed for tag %s (RSS 1.0)'),
|
||||||
$this->tag)),
|
$this->tag)),
|
||||||
new Feed(Feed::RSS2,
|
new Feed(Feed::RSS2,
|
||||||
common_local_url('api',
|
common_local_url('ApiTimelineTag',
|
||||||
array('apiaction' => 'tags',
|
array('format' => 'rss',
|
||||||
'method' => 'timeline',
|
'tag' => $this->tag)),
|
||||||
'argument' => $this->tag.'.rss')),
|
sprintf(_('Notice feed for tag %s (RSS 2.0)'),
|
||||||
sprintf(_('Notice feed for %s group (RSS 2.0)'),
|
|
||||||
$this->tag)),
|
$this->tag)),
|
||||||
new Feed(Feed::ATOM,
|
new Feed(Feed::ATOM,
|
||||||
common_local_url('api',
|
common_local_url('ApiTimelineTag',
|
||||||
array('apiaction' => 'tags',
|
array('format' => 'atom',
|
||||||
'method' => 'timeline',
|
'tag' => $this->tag)),
|
||||||
'argument' => $this->tag.'.atom')),
|
|
||||||
sprintf(_('Notice feed for tag %s (Atom)'),
|
sprintf(_('Notice feed for tag %s (Atom)'),
|
||||||
$this->tag)));
|
$this->tag)));
|
||||||
}
|
}
|
||||||
|
|
108
actions/xrds.php
108
actions/xrds.php
|
@ -36,6 +36,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||||
require_once INSTALLDIR.'/lib/omb.php';
|
require_once INSTALLDIR.'/lib/omb.php';
|
||||||
require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
|
require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
|
||||||
require_once INSTALLDIR.'/extlib/libomb/xrds_mapper.php';
|
require_once INSTALLDIR.'/extlib/libomb/xrds_mapper.php';
|
||||||
|
require_once INSTALLDIR.'/lib/xrdsoutputter.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XRDS for OpenMicroBlogging
|
* XRDS for OpenMicroBlogging
|
||||||
|
@ -49,6 +50,8 @@ require_once INSTALLDIR.'/extlib/libomb/xrds_mapper.php';
|
||||||
*/
|
*/
|
||||||
class XrdsAction extends Action
|
class XrdsAction extends Action
|
||||||
{
|
{
|
||||||
|
var $user;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is read only?
|
* Is read only?
|
||||||
*
|
*
|
||||||
|
@ -59,6 +62,18 @@ class XrdsAction extends Action
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
$nickname = $this->trimmed('nickname');
|
||||||
|
$this->user = User::staticGet('nickname', $nickname);
|
||||||
|
if (!$this->user) {
|
||||||
|
$this->clientError(_('No such user.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class handler.
|
* Class handler.
|
||||||
*
|
*
|
||||||
|
@ -69,49 +84,64 @@ class XrdsAction extends Action
|
||||||
function handle($args)
|
function handle($args)
|
||||||
{
|
{
|
||||||
parent::handle($args);
|
parent::handle($args);
|
||||||
$nickname = $this->trimmed('nickname');
|
$xrdsOutputter = new XRDSOutputter();
|
||||||
$user = User::staticGet('nickname', $nickname);
|
$xrdsOutputter->startXRDS();
|
||||||
if (!$user) {
|
|
||||||
$this->clientError(_('No such user.'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->showXrds($user);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
Event::handle('StartUserXRDS', array($this,&$xrdsOutputter));
|
||||||
* Show XRDS for a user.
|
|
||||||
*
|
|
||||||
* @param class $user XRDS for this user.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function showXrds($user)
|
|
||||||
{
|
|
||||||
$srv = new OMB_Service_Provider(profile_to_omb_profile($user->uri,
|
|
||||||
$user->getProfile()));
|
|
||||||
/* Use libomb’s default XRDS Writer. */
|
|
||||||
$xrds_writer = null;
|
|
||||||
$srv->writeXRDS(new Laconica_XRDS_Mapper(), $xrds_writer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Laconica_XRDS_Mapper implements OMB_XRDS_Mapper
|
//oauth
|
||||||
{
|
$xrdsOutputter->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
|
||||||
protected $urls;
|
'xml:id' => 'oauth',
|
||||||
|
'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
|
||||||
|
'version' => '2.0'));
|
||||||
|
$xrdsOutputter->element('Type', null, 'xri://$xrds*simple');
|
||||||
|
$xrdsOutputter->showXrdsService(OAUTH_ENDPOINT_REQUEST,
|
||||||
|
common_local_url('requesttoken'),
|
||||||
|
array(OAUTH_AUTH_HEADER, OAUTH_POST_BODY, OAUTH_HMAC_SHA1));
|
||||||
|
$xrdsOutputter->showXrdsService( OAUTH_ENDPOINT_AUTHORIZE,
|
||||||
|
common_local_url('userauthorization'),
|
||||||
|
array(OAUTH_AUTH_HEADER, OAUTH_POST_BODY, OAUTH_HMAC_SHA1),
|
||||||
|
null,
|
||||||
|
$this->user->getIdentifierURI());
|
||||||
|
$xrdsOutputter->showXrdsService(OAUTH_ENDPOINT_ACCESS,
|
||||||
|
common_local_url('accesstoken'),
|
||||||
|
array(OAUTH_AUTH_HEADER, OAUTH_POST_BODY, OAUTH_HMAC_SHA1),
|
||||||
|
null,
|
||||||
|
$this->user->getIdentifierURI());
|
||||||
|
$xrdsOutputter->showXrdsService(OAUTH_ENDPOINT_RESOURCE,
|
||||||
|
null,
|
||||||
|
array(OAUTH_AUTH_HEADER, OAUTH_POST_BODY, OAUTH_HMAC_SHA1),
|
||||||
|
null,
|
||||||
|
$this->user->getIdentifierURI());
|
||||||
|
$xrdsOutputter->elementEnd('XRD');
|
||||||
|
|
||||||
public function __construct()
|
//omb
|
||||||
{
|
$xrdsOutputter->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
|
||||||
$this->urls = array(
|
'xml:id' => 'oauth',
|
||||||
OAUTH_ENDPOINT_REQUEST => 'requesttoken',
|
'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
|
||||||
OAUTH_ENDPOINT_AUTHORIZE => 'userauthorization',
|
'version' => '2.0'));
|
||||||
OAUTH_ENDPOINT_ACCESS => 'accesstoken',
|
$xrdsOutputter->element('Type', null, 'xri://$xrds*simple');
|
||||||
OMB_ENDPOINT_POSTNOTICE => 'postnotice',
|
$xrdsOutputter->showXrdsService(OMB_ENDPOINT_POSTNOTICE,
|
||||||
OMB_ENDPOINT_UPDATEPROFILE => 'updateprofile');
|
common_local_url('postnotice'));
|
||||||
}
|
$xrdsOutputter->showXrdsService(OMB_ENDPOINT_UPDATEPROFILE,
|
||||||
|
common_local_url('updateprofile'));
|
||||||
|
$xrdsOutputter->elementEnd('XRD');
|
||||||
|
|
||||||
|
//misc
|
||||||
|
$xrdsOutputter->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
|
||||||
|
'xml:id' => 'oauth',
|
||||||
|
'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
|
||||||
|
'version' => '2.0'));
|
||||||
|
$xrdsOutputter->showXrdsService(OAUTH_DISCOVERY,
|
||||||
|
'#oauth');
|
||||||
|
$xrdsOutputter->showXrdsService(OMB_VERSION,
|
||||||
|
'#omb');
|
||||||
|
$xrdsOutputter->elementEnd('XRD');
|
||||||
|
|
||||||
|
Event::handle('EndUserXRDS', array($this,&$xrdsOutputter));
|
||||||
|
|
||||||
|
$xrdsOutputter->endXRDS();
|
||||||
|
|
||||||
public function getURL($action)
|
|
||||||
{
|
|
||||||
return common_local_url($this->urls[$action]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -81,7 +81,7 @@ class Avatar extends Memcached_DataObject
|
||||||
if (empty($server)) {
|
if (empty($server)) {
|
||||||
$server = common_config('site', 'server');
|
$server = common_config('site', 'server');
|
||||||
}
|
}
|
||||||
|
common_debug('path = ' . $path);
|
||||||
// XXX: protocol
|
// XXX: protocol
|
||||||
|
|
||||||
return 'http://'.$server.$path.$filename;
|
return 'http://'.$server.$path.$filename;
|
||||||
|
|
46
classes/Location_namespace.php
Normal file
46
classes/Location_namespace.php
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* StatusNet - the distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2009, StatusNet, 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('STATUSNET') && !defined('LACONICA')) { exit(1); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table Definition for location_namespace
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
|
||||||
|
|
||||||
|
class Location_namespace extends Memcached_DataObject
|
||||||
|
{
|
||||||
|
###START_AUTOCODE
|
||||||
|
/* the code below is auto generated do not remove the above tag */
|
||||||
|
|
||||||
|
public $__table = 'location_namespace'; // table name
|
||||||
|
public $id; // int(4) primary_key not_null
|
||||||
|
public $description; // varchar(255)
|
||||||
|
public $created; // datetime() not_null
|
||||||
|
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
|
||||||
|
|
||||||
|
/* Static get */
|
||||||
|
function staticGet($k,$v=NULL) {
|
||||||
|
return Memcached_DataObject::staticGet('Location_namespace',$k,$v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the code above is auto generated do not remove the tag below */
|
||||||
|
###END_AUTOCODE
|
||||||
|
}
|
|
@ -66,9 +66,15 @@ class Notice extends Memcached_DataObject
|
||||||
public $is_local; // tinyint(1)
|
public $is_local; // tinyint(1)
|
||||||
public $source; // varchar(32)
|
public $source; // varchar(32)
|
||||||
public $conversation; // int(4)
|
public $conversation; // int(4)
|
||||||
|
public $lat; // decimal(10,7)
|
||||||
|
public $lon; // decimal(10,7)
|
||||||
|
public $location_id; // int(4)
|
||||||
|
public $location_ns; // int(4)
|
||||||
|
|
||||||
/* Static get */
|
/* 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 */
|
/* the code above is auto generated do not remove the tag below */
|
||||||
###END_AUTOCODE
|
###END_AUTOCODE
|
||||||
|
@ -162,7 +168,8 @@ class Notice extends Memcached_DataObject
|
||||||
}
|
}
|
||||||
|
|
||||||
static function saveNew($profile_id, $content, $source=null,
|
static function saveNew($profile_id, $content, $source=null,
|
||||||
$is_local=Notice::LOCAL_PUBLIC, $reply_to=null, $uri=null, $created=null) {
|
$is_local=Notice::LOCAL_PUBLIC, $reply_to=null, $uri=null, $created=null,
|
||||||
|
$lat=null, $lon=null, $location_id=null, $location_ns=null) {
|
||||||
|
|
||||||
$profile = Profile::staticGet($profile_id);
|
$profile = Profile::staticGet($profile_id);
|
||||||
|
|
||||||
|
@ -172,7 +179,7 @@ class Notice extends Memcached_DataObject
|
||||||
throw new ClientException(_('Problem saving notice. Too long.'));
|
throw new ClientException(_('Problem saving notice. Too long.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$profile) {
|
if (empty($profile)) {
|
||||||
throw new ClientException(_('Problem saving notice. Unknown user.'));
|
throw new ClientException(_('Problem saving notice. Unknown user.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +235,26 @@ class Notice extends Memcached_DataObject
|
||||||
$notice->conversation = $reply->conversation;
|
$notice->conversation = $reply->conversation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($lat) && !empty($lon)) {
|
||||||
|
$notice->lat = $lat;
|
||||||
|
$notice->lon = $lon;
|
||||||
|
$notice->location_id = $location_id;
|
||||||
|
$notice->location_ns = $location_ns;
|
||||||
|
} else if (!empty($location_ns) && !empty($location_id)) {
|
||||||
|
$location = Location::fromId($location_id, $location_ns);
|
||||||
|
if (!empty($location)) {
|
||||||
|
$notice->lat = $location->lat;
|
||||||
|
$notice->lon = $location->lon;
|
||||||
|
$notice->location_id = $location_id;
|
||||||
|
$notice->location_ns = $location_ns;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$notice->lat = $profile->lat;
|
||||||
|
$notice->lon = $profile->lon;
|
||||||
|
$notice->location_id = $profile->location_id;
|
||||||
|
$notice->location_ns = $profile->location_ns;
|
||||||
|
}
|
||||||
|
|
||||||
if (Event::handle('StartNoticeSave', array(&$notice))) {
|
if (Event::handle('StartNoticeSave', array(&$notice))) {
|
||||||
|
|
||||||
// XXX: some of these functions write to the DB
|
// XXX: some of these functions write to the DB
|
||||||
|
@ -269,7 +296,6 @@ class Notice extends Memcached_DataObject
|
||||||
|
|
||||||
// XXX: do we need to change this for remote users?
|
// XXX: do we need to change this for remote users?
|
||||||
|
|
||||||
$notice->saveReplies();
|
|
||||||
$notice->saveTags();
|
$notice->saveTags();
|
||||||
|
|
||||||
$notice->addToInboxes();
|
$notice->addToInboxes();
|
||||||
|
@ -307,11 +333,11 @@ class Notice extends Memcached_DataObject
|
||||||
|
|
||||||
static function checkDupes($profile_id, $content) {
|
static function checkDupes($profile_id, $content) {
|
||||||
$profile = Profile::staticGet($profile_id);
|
$profile = Profile::staticGet($profile_id);
|
||||||
if (!$profile) {
|
if (empty($profile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$notice = $profile->getNotices(0, NOTICE_CACHE_WINDOW);
|
$notice = $profile->getNotices(0, NOTICE_CACHE_WINDOW);
|
||||||
if ($notice) {
|
if (!empty($notice)) {
|
||||||
$last = 0;
|
$last = 0;
|
||||||
while ($notice->fetch()) {
|
while ($notice->fetch()) {
|
||||||
if (time() - strtotime($notice->created) >= common_config('site', 'dupelimit')) {
|
if (time() - strtotime($notice->created) >= common_config('site', 'dupelimit')) {
|
||||||
|
@ -337,7 +363,7 @@ class Notice extends Memcached_DataObject
|
||||||
|
|
||||||
static function checkEditThrottle($profile_id) {
|
static function checkEditThrottle($profile_id) {
|
||||||
$profile = Profile::staticGet($profile_id);
|
$profile = Profile::staticGet($profile_id);
|
||||||
if (!$profile) {
|
if (empty($profile)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
# Get the Nth notice
|
# Get the Nth notice
|
||||||
|
@ -658,7 +684,7 @@ class Notice extends Memcached_DataObject
|
||||||
|
|
||||||
$cache = common_memcache();
|
$cache = common_memcache();
|
||||||
|
|
||||||
if (!$cache) {
|
if (empty($cache)) {
|
||||||
return Notice::getStreamDirect($qry, $offset, $limit, null, null, $order, null);
|
return Notice::getStreamDirect($qry, $offset, $limit, null, null, $order, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -719,7 +745,7 @@ class Notice extends Memcached_DataObject
|
||||||
|
|
||||||
# If there are no hits, just return the value
|
# If there are no hits, just return the value
|
||||||
|
|
||||||
if (!$notice) {
|
if (empty($notice)) {
|
||||||
return $notice;
|
return $notice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -909,6 +935,18 @@ class Notice extends Memcached_DataObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$recipients = $this->saveReplies();
|
||||||
|
|
||||||
|
foreach ($recipients as $recipient) {
|
||||||
|
|
||||||
|
if (!array_key_exists($recipient, $ni)) {
|
||||||
|
$recipientUser = User::staticGet('id', $recipient);
|
||||||
|
if (!empty($recipientUser)) {
|
||||||
|
$ni[$recipient] = NOTICE_INBOX_SOURCE_REPLY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$cnt = 0;
|
$cnt = 0;
|
||||||
|
|
||||||
$qryhdr = 'INSERT INTO notice_inbox (user_id, notice_id, source, created) VALUES ';
|
$qryhdr = 'INSERT INTO notice_inbox (user_id, notice_id, source, created) VALUES ';
|
||||||
|
@ -1061,12 +1099,12 @@ class Notice extends Memcached_DataObject
|
||||||
for ($i=0; $i<count($names); $i++) {
|
for ($i=0; $i<count($names); $i++) {
|
||||||
$nickname = $names[$i];
|
$nickname = $names[$i];
|
||||||
$recipient = common_relative_profile($sender, $nickname, $this->created);
|
$recipient = common_relative_profile($sender, $nickname, $this->created);
|
||||||
if (!$recipient) {
|
if (empty($recipient)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Don't save replies from blocked profile to local user
|
// Don't save replies from blocked profile to local user
|
||||||
$recipient_user = User::staticGet('id', $recipient->id);
|
$recipient_user = User::staticGet('id', $recipient->id);
|
||||||
if ($recipient_user && $recipient_user->hasBlocked($sender)) {
|
if (!empty($recipient_user) && $recipient_user->hasBlocked($sender)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$reply = new Reply();
|
$reply = new Reply();
|
||||||
|
@ -1077,7 +1115,7 @@ class Notice extends Memcached_DataObject
|
||||||
$last_error = &PEAR::getStaticProperty('DB_DataObject','lastError');
|
$last_error = &PEAR::getStaticProperty('DB_DataObject','lastError');
|
||||||
common_log(LOG_ERR, 'DB error inserting reply: ' . $last_error->message);
|
common_log(LOG_ERR, 'DB error inserting reply: ' . $last_error->message);
|
||||||
common_server_error(sprintf(_('DB error inserting reply: %s'), $last_error->message));
|
common_server_error(sprintf(_('DB error inserting reply: %s'), $last_error->message));
|
||||||
return;
|
return array();
|
||||||
} else {
|
} else {
|
||||||
$replied[$recipient->id] = 1;
|
$replied[$recipient->id] = 1;
|
||||||
}
|
}
|
||||||
|
@ -1101,7 +1139,7 @@ class Notice extends Memcached_DataObject
|
||||||
$id = $reply->insert();
|
$id = $reply->insert();
|
||||||
if (!$id) {
|
if (!$id) {
|
||||||
common_log_db_error($reply, 'INSERT', __FILE__);
|
common_log_db_error($reply, 'INSERT', __FILE__);
|
||||||
return;
|
return array();
|
||||||
} else {
|
} else {
|
||||||
$replied[$recipient->id] = 1;
|
$replied[$recipient->id] = 1;
|
||||||
}
|
}
|
||||||
|
@ -1110,12 +1148,16 @@ class Notice extends Memcached_DataObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (array_keys($replied) as $recipient) {
|
$recipientIds = array_keys($replied);
|
||||||
|
|
||||||
|
foreach ($recipientIds as $recipient) {
|
||||||
$user = User::staticGet('id', $recipient);
|
$user = User::staticGet('id', $recipient);
|
||||||
if ($user) {
|
if ($user) {
|
||||||
mail_notify_attn($user, $this);
|
mail_notify_attn($user, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $recipientIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
function asAtomEntry($namespace=false, $source=false)
|
function asAtomEntry($namespace=false, $source=false)
|
||||||
|
@ -1139,10 +1181,9 @@ class Notice extends Memcached_DataObject
|
||||||
$xs->element('link', array('href' => $profile->profileurl));
|
$xs->element('link', array('href' => $profile->profileurl));
|
||||||
$user = User::staticGet('id', $profile->id);
|
$user = User::staticGet('id', $profile->id);
|
||||||
if (!empty($user)) {
|
if (!empty($user)) {
|
||||||
$atom_feed = common_local_url('api',
|
$atom_feed = common_local_url('ApiTimelineUser',
|
||||||
array('apiaction' => 'statuses',
|
array('format' => 'atom',
|
||||||
'method' => 'user_timeline',
|
'id' => $profile->nickname));
|
||||||
'argument' => $profile->nickname.'.atom'));
|
|
||||||
$xs->element('link', array('rel' => 'self',
|
$xs->element('link', array('rel' => 'self',
|
||||||
'type' => 'application/atom+xml',
|
'type' => 'application/atom+xml',
|
||||||
'href' => $profile->profileurl));
|
'href' => $profile->profileurl));
|
||||||
|
@ -1370,4 +1411,21 @@ class Notice extends Memcached_DataObject
|
||||||
$contentlimit = self::maxContent();
|
$contentlimit = self::maxContent();
|
||||||
return ($contentlimit > 0 && !empty($content) && (mb_strlen($content) > $contentlimit));
|
return ($contentlimit > 0 && !empty($content) && (mb_strlen($content) > $contentlimit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLocation()
|
||||||
|
{
|
||||||
|
$location = null;
|
||||||
|
|
||||||
|
if (!empty($this->location_id) && !empty($this->location_ns)) {
|
||||||
|
$location = Location::fromId($this->location_id, $this->location_ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_null($location)) { // no ID, or Location::fromId() failed
|
||||||
|
if (!empty($this->lat) && !empty($this->lon)) {
|
||||||
|
$location = Location::fromLatLon($this->lat, $this->lon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $location;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,15 +37,26 @@ class Profile extends Memcached_DataObject
|
||||||
public $homepage; // varchar(255) multiple_key
|
public $homepage; // varchar(255) multiple_key
|
||||||
public $bio; // text() multiple_key
|
public $bio; // text() multiple_key
|
||||||
public $location; // varchar(255) multiple_key
|
public $location; // varchar(255) multiple_key
|
||||||
|
public $lat; // decimal(10,7)
|
||||||
|
public $lon; // decimal(10,7)
|
||||||
|
public $location_id; // int(4)
|
||||||
|
public $location_ns; // int(4)
|
||||||
public $created; // datetime() not_null
|
public $created; // datetime() not_null
|
||||||
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
|
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
|
||||||
|
|
||||||
/* Static get */
|
/* Static get */
|
||||||
function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('Profile',$k,$v); }
|
function staticGet($k,$v=NULL) {
|
||||||
|
return Memcached_DataObject::staticGet('Profile',$k,$v);
|
||||||
|
}
|
||||||
|
|
||||||
/* the code above is auto generated do not remove the tag below */
|
/* the code above is auto generated do not remove the tag below */
|
||||||
###END_AUTOCODE
|
###END_AUTOCODE
|
||||||
|
|
||||||
|
function getUser()
|
||||||
|
{
|
||||||
|
return User::staticGet('id', $this->id);
|
||||||
|
}
|
||||||
|
|
||||||
function getAvatar($width, $height=null)
|
function getAvatar($width, $height=null)
|
||||||
{
|
{
|
||||||
if (is_null($height)) {
|
if (is_null($height)) {
|
||||||
|
@ -551,4 +562,29 @@ class Profile extends Memcached_DataObject
|
||||||
$block->blocked = $this->id;
|
$block->blocked = $this->id;
|
||||||
$block->delete();
|
$block->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: identical to Notice::getLocation.
|
||||||
|
|
||||||
|
function getLocation()
|
||||||
|
{
|
||||||
|
$location = null;
|
||||||
|
|
||||||
|
if (!empty($this->location_id) && !empty($this->location_ns)) {
|
||||||
|
$location = Location::fromId($this->location_id, $this->location_ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_null($location)) { // no ID, or Location::fromId() failed
|
||||||
|
if (!empty($this->lat) && !empty($this->lon)) {
|
||||||
|
$location = Location::fromLatLon($this->lat, $this->lon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_null($location)) { // still haven't found it!
|
||||||
|
if (!empty($this->location)) {
|
||||||
|
$location = Location::fromName($this->location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $location;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,6 +198,15 @@ class User extends Memcached_DataObject
|
||||||
}
|
}
|
||||||
if (!empty($location)) {
|
if (!empty($location)) {
|
||||||
$profile->location = $location;
|
$profile->location = $location;
|
||||||
|
|
||||||
|
$loc = Location::fromName($location);
|
||||||
|
|
||||||
|
if (!empty($loc)) {
|
||||||
|
$profile->lat = $loc->lat;
|
||||||
|
$profile->lon = $loc->lon;
|
||||||
|
$profile->location_id = $loc->location_id;
|
||||||
|
$profile->location_ns = $loc->location_ns;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$profile->created = common_sql_now();
|
$profile->created = common_sql_now();
|
||||||
|
@ -319,6 +328,7 @@ class User extends Memcached_DataObject
|
||||||
common_config('site', 'name'),
|
common_config('site', 'name'),
|
||||||
$user->nickname),
|
$user->nickname),
|
||||||
'system');
|
'system');
|
||||||
|
common_broadcast_notice($notice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
[avatar]
|
[avatar]
|
||||||
profile_id = 129
|
profile_id = 129
|
||||||
original = 17
|
original = 17
|
||||||
|
@ -243,6 +244,15 @@ created = 142
|
||||||
[invitation__keys]
|
[invitation__keys]
|
||||||
code = K
|
code = K
|
||||||
|
|
||||||
|
[location_namespace]
|
||||||
|
id = 129
|
||||||
|
description = 2
|
||||||
|
created = 142
|
||||||
|
modified = 384
|
||||||
|
|
||||||
|
[location_namespace__keys]
|
||||||
|
id = K
|
||||||
|
|
||||||
[message]
|
[message]
|
||||||
id = 129
|
id = 129
|
||||||
uri = 2
|
uri = 2
|
||||||
|
@ -284,6 +294,10 @@ reply_to = 1
|
||||||
is_local = 17
|
is_local = 17
|
||||||
source = 2
|
source = 2
|
||||||
conversation = 1
|
conversation = 1
|
||||||
|
lat = 1
|
||||||
|
lon = 1
|
||||||
|
location_id = 1
|
||||||
|
location_ns = 1
|
||||||
|
|
||||||
[notice__keys]
|
[notice__keys]
|
||||||
id = N
|
id = N
|
||||||
|
@ -325,6 +339,10 @@ profileurl = 2
|
||||||
homepage = 2
|
homepage = 2
|
||||||
bio = 34
|
bio = 34
|
||||||
location = 2
|
location = 2
|
||||||
|
lat = 1
|
||||||
|
lon = 1
|
||||||
|
location_id = 1
|
||||||
|
location_ns = 1
|
||||||
created = 142
|
created = 142
|
||||||
modified = 384
|
modified = 384
|
||||||
|
|
||||||
|
@ -519,6 +537,16 @@ modified = 384
|
||||||
canonical = K
|
canonical = K
|
||||||
display = U
|
display = U
|
||||||
|
|
||||||
|
[user_openid_trustroot]
|
||||||
|
trustroot = 130
|
||||||
|
user_id = 129
|
||||||
|
created = 142
|
||||||
|
modified = 384
|
||||||
|
|
||||||
|
[user_openid__keys]
|
||||||
|
trustroot = K
|
||||||
|
user_id = K
|
||||||
|
|
||||||
[user_role]
|
[user_role]
|
||||||
user_id = 129
|
user_id = 129
|
||||||
role = 130
|
role = 130
|
||||||
|
|
|
@ -104,6 +104,10 @@ $config['sphinx']['port'] = 3312;
|
||||||
// $config['site']['timezone'] = 'Pacific/Auckland';
|
// $config['site']['timezone'] = 'Pacific/Auckland';
|
||||||
// $config['site']['language'] = 'en_NZ';
|
// $config['site']['language'] = 'en_NZ';
|
||||||
|
|
||||||
|
// When validating user supplied email addresses, validate if the domain
|
||||||
|
// is running an SMTP server.
|
||||||
|
// $config['mail']['check_domain'] = true;
|
||||||
|
|
||||||
// Email info, used for all outbound email
|
// Email info, used for all outbound email
|
||||||
// $config['mail']['notifyfrom'] = 'microblog@example.net';
|
// $config['mail']['notifyfrom'] = 'microblog@example.net';
|
||||||
// $config['mail']['domain'] = 'microblog.example.net';
|
// $config['mail']['domain'] = 'microblog.example.net';
|
||||||
|
|
5
db/location_namespace.sql
Normal file
5
db/location_namespace.sql
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
insert into location_namespace
|
||||||
|
(id, description, created)
|
||||||
|
values
|
||||||
|
(1, 'Geonames', now()),
|
||||||
|
(2, 'Where on Earth', now());
|
|
@ -1,6 +1,7 @@
|
||||||
/* local and remote users have profiles */
|
/* local and remote users have profiles */
|
||||||
|
|
||||||
create table profile (
|
create table profile (
|
||||||
|
|
||||||
id integer auto_increment primary key comment 'unique identifier',
|
id integer auto_increment primary key comment 'unique identifier',
|
||||||
nickname varchar(64) not null comment 'nickname or username',
|
nickname varchar(64) not null comment 'nickname or username',
|
||||||
fullname varchar(255) comment 'display name',
|
fullname varchar(255) comment 'display name',
|
||||||
|
@ -8,6 +9,11 @@ create table profile (
|
||||||
homepage varchar(255) comment 'identifying URL',
|
homepage varchar(255) comment 'identifying URL',
|
||||||
bio text comment 'descriptive biography',
|
bio text comment 'descriptive biography',
|
||||||
location varchar(255) comment 'physical location',
|
location varchar(255) comment 'physical location',
|
||||||
|
lat decimal(10,7) comment 'latitude',
|
||||||
|
lon decimal(10,7) comment 'longitude',
|
||||||
|
location_id integer comment 'location id if possible',
|
||||||
|
location_ns integer comment 'namespace for location',
|
||||||
|
|
||||||
created datetime not null comment 'date this record was created',
|
created datetime not null comment 'date this record was created',
|
||||||
modified timestamp comment 'date this record was modified',
|
modified timestamp comment 'date this record was modified',
|
||||||
|
|
||||||
|
@ -119,6 +125,10 @@ create table notice (
|
||||||
is_local tinyint default 0 comment 'notice was generated by a user',
|
is_local tinyint default 0 comment 'notice was generated by a user',
|
||||||
source varchar(32) comment 'source of comment, like "web", "im", or "clientname"',
|
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),
|
conversation integer comment 'id of root notice in this conversation' references notice (id),
|
||||||
|
lat decimal(10,7) comment 'latitude',
|
||||||
|
lon decimal(10,7) comment 'longitude',
|
||||||
|
location_id integer comment 'location id if possible',
|
||||||
|
location_ns integer comment 'namespace for location',
|
||||||
|
|
||||||
index notice_profile_id_idx (profile_id),
|
index notice_profile_id_idx (profile_id),
|
||||||
index notice_conversation_idx (conversation),
|
index notice_conversation_idx (conversation),
|
||||||
|
@ -556,3 +566,12 @@ create table user_role (
|
||||||
constraint primary key (user_id, role)
|
constraint primary key (user_id, role)
|
||||||
|
|
||||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||||
|
|
||||||
|
create table location_namespace (
|
||||||
|
|
||||||
|
id integer primary key comment 'identity for this namespace',
|
||||||
|
description varchar(255) comment 'description of the namespace',
|
||||||
|
created datetime not null comment 'date the record was created',
|
||||||
|
modified timestamp comment 'date this record was modified'
|
||||||
|
|
||||||
|
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||||
|
|
|
@ -2,4 +2,4 @@ A bookmarklet is a small piece of javascript code used as a bookmark. This one w
|
||||||
|
|
||||||
Drag-and-drop the following link to your bookmarks bar or right-click it and add it to your browser favorites to keep it handy.
|
Drag-and-drop the following link to your bookmarks bar or right-click it and add it to your browser favorites to keep it handy.
|
||||||
|
|
||||||
<a href="javascript:var%20d=document,w=window,e=w.getSelection,k=d.getSelection,x=d.selection,s=(e?e():(k)?k():(x?x.createRange().text:0)),f='http://%%site.server%%/%%site.path%%/index.php?action=newnotice',l=d.location,e=encodeURIComponent,g=f+'&status_textarea=%22'+((e(s))?e(s):e(document.title))+'%22 from '+l.href;function%20a(){if(!w.open(g,'t','toolbar=0,resizable=0,scrollbars=1,status=1,width=800,height=570')){l.href=g;}}a();void(0);">Post to %%site.name%%</a>
|
<a href="javascript:(function(){var%20d=document,w=window,e=w.getSelection,k=d.getSelection,x=d.selection,s=(e?e():(k)?k():(x?x.createRange().text:0)),f='http://%%site.server%%/%%site.path%%/index.php?action=bookmarklet',l=d.location,e=encodeURIComponent,g=f+'&status_textarea=%22'+((e(s))?e(s):e(document.title))+'%22%20%E2%80%94%20'+l.href;function%20a(){if(!w.open(g,'t','toolbar=0,resizable=0,scrollbars=1,status=1,width=450,height=200')){l.href=g;}}a();})()">Post to %%site.name%%</a>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
/**
|
/**
|
||||||
* The library version string
|
* The library version string
|
||||||
*/
|
*/
|
||||||
define('Auth_OpenID_VERSION', '2.1.2');
|
define('Auth_OpenID_VERSION', '2.1.3');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Require the fetcher code.
|
* Require the fetcher code.
|
||||||
|
|
|
@ -376,7 +376,7 @@ function Auth_OpenID_detectMathLibrary($exts)
|
||||||
// Try to load dynamic modules.
|
// Try to load dynamic modules.
|
||||||
if (!$loaded) {
|
if (!$loaded) {
|
||||||
foreach ($extension['modules'] as $module) {
|
foreach ($extension['modules'] as $module) {
|
||||||
if (function_exists('dl') && ini_get('enable_dl') && !ini_get('safe_mode') && @dl($module . "." . PHP_SHLIB_SUFFIX)) {
|
if (@dl($module . "." . PHP_SHLIB_SUFFIX)) {
|
||||||
$loaded = true;
|
$loaded = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1295,7 +1295,8 @@ class Auth_OpenID_GenericConsumer {
|
||||||
Auth_OpenID_OPENID2_NS => array_merge($basic_sig_fields,
|
Auth_OpenID_OPENID2_NS => array_merge($basic_sig_fields,
|
||||||
array('response_nonce',
|
array('response_nonce',
|
||||||
'claimed_id',
|
'claimed_id',
|
||||||
'assoc_handle')),
|
'assoc_handle',
|
||||||
|
'op_endpoint')),
|
||||||
Auth_OpenID_OPENID1_NS => array_merge($basic_sig_fields,
|
Auth_OpenID_OPENID1_NS => array_merge($basic_sig_fields,
|
||||||
array('nonce'))
|
array('nonce'))
|
||||||
);
|
);
|
||||||
|
|
|
@ -887,6 +887,11 @@ class Auth_OpenID_Message {
|
||||||
|
|
||||||
function getAliasedArg($aliased_key, $default = null)
|
function getAliasedArg($aliased_key, $default = null)
|
||||||
{
|
{
|
||||||
|
if ($aliased_key == 'ns') {
|
||||||
|
// Return the namespace URI for the OpenID namespace
|
||||||
|
return $this->getOpenIDNamespace();
|
||||||
|
}
|
||||||
|
|
||||||
$parts = explode('.', $aliased_key, 2);
|
$parts = explode('.', $aliased_key, 2);
|
||||||
|
|
||||||
if (count($parts) != 2) {
|
if (count($parts) != 2) {
|
||||||
|
|
|
@ -138,7 +138,7 @@ class Auth_Yadis_HTTPFetcher {
|
||||||
* pass the URLHasAllowedScheme check or if the server's response
|
* pass the URLHasAllowedScheme check or if the server's response
|
||||||
* is malformed.
|
* is malformed.
|
||||||
*/
|
*/
|
||||||
function get($url, $headers)
|
function get($url, $headers = null)
|
||||||
{
|
{
|
||||||
trigger_error("not implemented", E_USER_ERROR);
|
trigger_error("not implemented", E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,8 +127,6 @@ class Auth_Yadis_ParanoidHTTPFetcher extends Auth_Yadis_HTTPFetcher {
|
||||||
Auth_OpenID_USER_AGENT.' '.$curl_user_agent);
|
Auth_OpenID_USER_AGENT.' '.$curl_user_agent);
|
||||||
curl_setopt($c, CURLOPT_TIMEOUT, $off);
|
curl_setopt($c, CURLOPT_TIMEOUT, $off);
|
||||||
curl_setopt($c, CURLOPT_URL, $url);
|
curl_setopt($c, CURLOPT_URL, $url);
|
||||||
curl_setopt($c, CURLOPT_RANGE,
|
|
||||||
"0-".(1024 * Auth_OpenID_FETCHER_MAX_RESPONSE_KB));
|
|
||||||
|
|
||||||
curl_exec($c);
|
curl_exec($c);
|
||||||
|
|
||||||
|
|
|
@ -83,8 +83,6 @@ class Auth_Yadis_PlainHTTPFetcher extends Auth_Yadis_HTTPFetcher {
|
||||||
"User-Agent: $user_agent",
|
"User-Agent: $user_agent",
|
||||||
"Host: ".$parts['host'].
|
"Host: ".$parts['host'].
|
||||||
($specify_port ? ":".$parts['port'] : ""),
|
($specify_port ? ":".$parts['port'] : ""),
|
||||||
"Range: 0-".
|
|
||||||
(1024*Auth_OpenID_FETCHER_MAX_RESPONSE_KB),
|
|
||||||
"Port: ".$parts['port']);
|
"Port: ".$parts['port']);
|
||||||
|
|
||||||
$errno = 0;
|
$errno = 0;
|
||||||
|
|
|
@ -91,7 +91,7 @@ class Auth_Yadis_XMLParser {
|
||||||
* @return array $node_list An array of matching opaque node
|
* @return array $node_list An array of matching opaque node
|
||||||
* objects to be used with other methods of this parser class.
|
* objects to be used with other methods of this parser class.
|
||||||
*/
|
*/
|
||||||
function evalXPath($xpath, $node = null)
|
function &evalXPath($xpath, $node = null)
|
||||||
{
|
{
|
||||||
// Not implemented.
|
// Not implemented.
|
||||||
}
|
}
|
||||||
|
@ -349,7 +349,7 @@ function &Auth_Yadis_getXMLParser()
|
||||||
foreach ($extensions as $name => $params) {
|
foreach ($extensions as $name => $params) {
|
||||||
if (!extension_loaded($name)) {
|
if (!extension_loaded($name)) {
|
||||||
foreach ($params['libname'] as $libname) {
|
foreach ($params['libname'] as $libname) {
|
||||||
if (function_exists('dl') && ini_get('enable_dl') && !ini_get('safe_mode') && @dl($libname)) {
|
if (@dl($libname)) {
|
||||||
$classname = $params['classname'];
|
$classname = $params['classname'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,7 +235,7 @@ class DB_DataObject extends DB_DataObject_Overload
|
||||||
* @access private
|
* @access private
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
var $_DB_DataObject_version = "1.8.11";
|
var $_DB_DataObject_version = "1.8.12";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Database table (used by table extends)
|
* The Database table (used by table extends)
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
*
|
*
|
||||||
* PHP versions 4 and 5
|
* PHP versions 4 and 5
|
||||||
*
|
*
|
||||||
* LICENSE: This source file is subject to version 3.0 of the PHP license
|
* LICENSE: This source file is subject to version 3.01 of the PHP license
|
||||||
* that is available through the world-wide-web at the following URI:
|
* that is available through the world-wide-web at the following URI:
|
||||||
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
* http://www.php.net/license/3_01.txt. If you did not receive a copy of
|
||||||
* the PHP License and are unable to obtain it through the web, please
|
* the PHP License and are unable to obtain it through the web, please
|
||||||
* send a note to license@php.net so we can mail you a copy immediately.
|
* send a note to license@php.net so we can mail you a copy immediately.
|
||||||
*
|
*
|
||||||
|
@ -16,8 +16,8 @@
|
||||||
* @package DB_DataObject
|
* @package DB_DataObject
|
||||||
* @author Alan Knowles <alan@akbkhome.com>
|
* @author Alan Knowles <alan@akbkhome.com>
|
||||||
* @copyright 1997-2008 The PHP Group
|
* @copyright 1997-2008 The PHP Group
|
||||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
* @license http://www.php.net/license/3_01.txt PHP License 3.01
|
||||||
* @version CVS: $Id: Cast.php 264148 2008-08-04 03:44:59Z alan_k $
|
* @version CVS: $Id: Cast.php 287158 2009-08-12 13:58:31Z alan_k $
|
||||||
* @link http://pear.php.net/package/DB_DataObject
|
* @link http://pear.php.net/package/DB_DataObject
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
*
|
*
|
||||||
* PHP versions 4 and 5
|
* PHP versions 4 and 5
|
||||||
*
|
*
|
||||||
* LICENSE: This source file is subject to version 3.0 of the PHP license
|
* LICENSE: This source file is subject to version 3.01 of the PHP license
|
||||||
* that is available through the world-wide-web at the following URI:
|
* that is available through the world-wide-web at the following URI:
|
||||||
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
* http://www.php.net/license/3_01.txt. If you did not receive a copy of
|
||||||
* the PHP License and are unable to obtain it through the web, please
|
* the PHP License and are unable to obtain it through the web, please
|
||||||
* send a note to license@php.net so we can mail you a copy immediately.
|
* send a note to license@php.net so we can mail you a copy immediately.
|
||||||
*
|
*
|
||||||
|
@ -17,8 +17,8 @@
|
||||||
* @package DB_DataObject
|
* @package DB_DataObject
|
||||||
* @author Alan Knowles <alan@akbkhome.com>
|
* @author Alan Knowles <alan@akbkhome.com>
|
||||||
* @copyright 1997-2006 The PHP Group
|
* @copyright 1997-2006 The PHP Group
|
||||||
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
* @license http://www.php.net/license/3_01.txt PHP License 3.01
|
||||||
* @version CVS: $Id: Error.php 277015 2009-03-12 05:51:03Z alan_k $
|
* @version CVS: $Id: Error.php 287158 2009-08-12 13:58:31Z alan_k $
|
||||||
* @link http://pear.php.net/package/DB_DataObject
|
* @link http://pear.php.net/package/DB_DataObject
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
58
extlib/README
Normal file
58
extlib/README
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
DO NOT "FIX" CODE IN THIS DIRECTORY.
|
||||||
|
|
||||||
|
ONLY UPSTREAM VERSIONS OF SOFTWARE GO IN THIS DIRECTORY.
|
||||||
|
|
||||||
|
This directory is provided as a courtesy to our users who might be
|
||||||
|
unable or unwilling to find and install libraries we depend on.
|
||||||
|
|
||||||
|
If we "fix" software in this directory, we hamstring users who do the
|
||||||
|
right thing and keep a single version of upstream libraries in a
|
||||||
|
system-wide library. We introduce subtle and maddening bugs where
|
||||||
|
our code is "accidentally" using the "wrong" library version. We may
|
||||||
|
unwittingly interfere with other software that depends on the
|
||||||
|
canonical release versions of those same libraries!
|
||||||
|
|
||||||
|
Forking upstream software for trivial reasons makes us bad citizens in
|
||||||
|
the Open Source community and adds unnecessary heartache for our
|
||||||
|
users. Don't make us "that" project.
|
||||||
|
|
||||||
|
FAQ:
|
||||||
|
|
||||||
|
Q: What should we do when we find a bug in upstream software?
|
||||||
|
|
||||||
|
A: First and foremost, REPORT THE BUG, and if possible send in a patch.
|
||||||
|
|
||||||
|
Watch for a release of the upstream software and integrate with it
|
||||||
|
when it's released.
|
||||||
|
|
||||||
|
In the meantime, work around the bug, if at all possible. Usually,
|
||||||
|
it's quite possible, if slightly harder or less efficient.
|
||||||
|
|
||||||
|
Q: What if the bug can't be worked around?
|
||||||
|
|
||||||
|
A: If the upstream developers have accepted a bug patch, it's
|
||||||
|
undesirable but acceptable to apply that patch to the library in
|
||||||
|
the extlib dir. Ideally, use a release version for upstream or a
|
||||||
|
version control system snapshot.
|
||||||
|
|
||||||
|
Note that this is a last resort.
|
||||||
|
|
||||||
|
Q: What if upstream is unresponsive or won't accept a patch?
|
||||||
|
|
||||||
|
A: Try again.
|
||||||
|
|
||||||
|
Q: I tried again, and upstream is still unresponsive and nobody's
|
||||||
|
checked on my patch. Now what?
|
||||||
|
|
||||||
|
A: If the upstream project is moribund and there's a way to adopt it,
|
||||||
|
propose having the StatusNet dev team adopt the project. Or, adopt
|
||||||
|
it yourself.
|
||||||
|
|
||||||
|
Q: What if there's no upstream authority and it can't be adopted?
|
||||||
|
|
||||||
|
A: Then we fork it. Make a new name and a new version. Include it in
|
||||||
|
lib/ instead of extlib/, and use the StatusNet_* prefix to change
|
||||||
|
the namespace to avoid collisions.
|
||||||
|
|
||||||
|
This is a last resort; consult with the rest of the dev group
|
||||||
|
before taking this radical step.
|
|
@ -1,3 +1,19 @@
|
||||||
|
2006-02-28 Danilo Šegan <danilo@gnome.org>
|
||||||
|
|
||||||
|
* gettext.php: Added some comments about these workarounds for
|
||||||
|
different PHP versions and architectures.
|
||||||
|
|
||||||
|
2006-02-28 Danilo Šegan <danilo@gnome.org>
|
||||||
|
|
||||||
|
Fixes bug #15923.
|
||||||
|
|
||||||
|
* gettext.php (gettext_reader): make magic check work on 64-bit
|
||||||
|
platforms as well (by Steffen Pingel).
|
||||||
|
|
||||||
|
2006-02-20 Danilo Šegan <danilo@gnome.org>
|
||||||
|
|
||||||
|
* gettext.inc (_bindtextdomain): Use php_uname to detect Windows.
|
||||||
|
|
||||||
2006-02-07 Danilo Šegan <danilo@gnome.org>
|
2006-02-07 Danilo Šegan <danilo@gnome.org>
|
||||||
|
|
||||||
* examples/pigs_dropin.php: comment-out bind_textdomain_codeset
|
* examples/pigs_dropin.php: comment-out bind_textdomain_codeset
|
||||||
|
|
|
@ -129,7 +129,7 @@ function _setlocale($category, $locale) {
|
||||||
$ret = 0;
|
$ret = 0;
|
||||||
if (function_exists('setlocale')) // I don't know if this ever happens ;)
|
if (function_exists('setlocale')) // I don't know if this ever happens ;)
|
||||||
$ret = setlocale($category, $locale);
|
$ret = setlocale($category, $locale);
|
||||||
if (($ret and $locale == '') or ($ret == $locale)) {
|
if ($ret and ($locale == '' or $ret == $locale)) {
|
||||||
$EMULATEGETTEXT = 0;
|
$EMULATEGETTEXT = 0;
|
||||||
$CURRENTLOCALE = $ret;
|
$CURRENTLOCALE = $ret;
|
||||||
} else {
|
} else {
|
||||||
|
@ -148,9 +148,9 @@ function _setlocale($category, $locale) {
|
||||||
*/
|
*/
|
||||||
function _bindtextdomain($domain, $path) {
|
function _bindtextdomain($domain, $path) {
|
||||||
global $text_domains;
|
global $text_domains;
|
||||||
// ensure $path ends with a slash
|
// ensure $path ends with a slash
|
||||||
if ($path[strlen($path) - 1] != '/') $path .= '/';
|
if ($path[strlen($path) - 1] != '/') $path .= '/';
|
||||||
elseif ($path[strlen($path) - 1] != '\\') $path .= '\\';
|
elseif ($path[strlen($path) - 1] != '\\') $path .= '\\';
|
||||||
$text_domains[$domain]->path = $path;
|
$text_domains[$domain]->path = $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,16 +102,16 @@ class gettext_reader {
|
||||||
// Caching can be turned off
|
// Caching can be turned off
|
||||||
$this->enable_cache = $enable_cache;
|
$this->enable_cache = $enable_cache;
|
||||||
|
|
||||||
// $MAGIC1 = (int)0x950412de; //bug in PHP 5
|
// $MAGIC1 = (int)0x950412de; //bug in PHP 5.0.2, see https://savannah.nongnu.org/bugs/?func=detailitem&item_id=10565
|
||||||
$MAGIC1 = (int) - 1794895138;
|
$MAGIC1 = (int) - 1794895138;
|
||||||
// $MAGIC2 = (int)0xde120495; //bug
|
// $MAGIC2 = (int)0xde120495; //bug
|
||||||
$MAGIC2 = (int) - 569244523;
|
$MAGIC2 = (int) - 569244523;
|
||||||
|
|
||||||
$this->STREAM = $Reader;
|
$this->STREAM = $Reader;
|
||||||
$magic = $this->readint();
|
$magic = $this->readint();
|
||||||
if ($magic == $MAGIC1) {
|
if ($magic == ($MAGIC1 & 0xFFFFFFFF)) { // to make sure it works for 64-bit platforms
|
||||||
$this->BYTEORDER = 0;
|
$this->BYTEORDER = 0;
|
||||||
} elseif ($magic == $MAGIC2) {
|
} elseif ($magic == ($MAGIC2 & 0xFFFFFFFF)) {
|
||||||
$this->BYTEORDER = 1;
|
$this->BYTEORDER = 1;
|
||||||
} else {
|
} else {
|
||||||
$this->error = 1; // not MO file
|
$this->error = 1; // not MO file
|
||||||
|
|
|
@ -5,6 +5,14 @@
|
||||||
|
|
||||||
RewriteBase /mublog/
|
RewriteBase /mublog/
|
||||||
|
|
||||||
|
# If your site is private and want to only allow logged-in users to
|
||||||
|
# be able to download file attachments, uncomment this rule.
|
||||||
|
#
|
||||||
|
# If you have a custom attachment path
|
||||||
|
# ($config['attachments']['path']), change "file/" to match.
|
||||||
|
#
|
||||||
|
#RewriteRule ^file/(.*) getfile/$1
|
||||||
|
|
||||||
RewriteCond %{REQUEST_FILENAME} !-f
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
RewriteCond %{REQUEST_FILENAME} !-d
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
RewriteRule (.*) index.php?p=$1 [L,QSA]
|
RewriteRule (.*) index.php?p=$1 [L,QSA]
|
||||||
|
|
|
@ -143,7 +143,7 @@ function checkMirror($action_obj, $args)
|
||||||
|
|
||||||
function isLoginAction($action)
|
function isLoginAction($action)
|
||||||
{
|
{
|
||||||
static $loginActions = array('login', 'recoverpassword', 'api', 'doc', 'register');
|
static $loginActions = array('login', 'recoverpassword', 'api', 'doc', 'register', 'publicxrds');
|
||||||
|
|
||||||
$login = null;
|
$login = null;
|
||||||
|
|
||||||
|
|
|
@ -692,9 +692,7 @@ function writeConf($sitename, $server, $path, $fancy, $db)
|
||||||
// database
|
// database
|
||||||
"\$config['db']['database'] = '{$db['database']}';\n\n".
|
"\$config['db']['database'] = '{$db['database']}';\n\n".
|
||||||
($db['type'] == 'pgsql' ? "\$config['db']['quote_identifiers'] = true;\n\n":'').
|
($db['type'] == 'pgsql' ? "\$config['db']['quote_identifiers'] = true;\n\n":'').
|
||||||
"\$config['db']['type'] = '{$db['type']}';\n\n".
|
"\$config['db']['type'] = '{$db['type']}';\n\n";
|
||||||
|
|
||||||
"?>";
|
|
||||||
// write configuration file out to install directory
|
// write configuration file out to install directory
|
||||||
$res = file_put_contents(INSTALLDIR.'/config.php', $cfg);
|
$res = file_put_contents(INSTALLDIR.'/config.php', $cfg);
|
||||||
|
|
||||||
|
|
711
js/util.js
711
js/util.js
|
@ -14,370 +14,377 @@
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* 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/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category UI interaction
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Sarven Capadisli <csarven@status.net>
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @copyright 2009 StatusNet, Inc.
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
var counterBlackout = false;
|
if ($('body.user_in').length > 0) {
|
||||||
|
$('.'+SN.C.S.FormNotice).each(function() { SN.U.FormNoticeEnhancements($(this)); });
|
||||||
|
|
||||||
// count character on keyup
|
$('.form_user_subscribe').each(function() { SN.U.FormXHR($(this)); });
|
||||||
function counter(event){
|
$('.form_user_unsubscribe').each(function() { SN.U.FormXHR($(this)); });
|
||||||
if (maxLength <= 0) {
|
$('.form_favor').each(function() { SN.U.FormXHR($(this)); });
|
||||||
return;
|
$('.form_disfavor').each(function() { SN.U.FormXHR($(this)); });
|
||||||
}
|
$('.form_group_join').each(function() { SN.U.FormXHR($(this)); });
|
||||||
var currentLength = $("#notice_data-text").val().length;
|
$('.form_group_leave').each(function() { SN.U.FormXHR($(this)); });
|
||||||
var remaining = maxLength - currentLength;
|
$('.form_user_nudge').each(function() { SN.U.FormXHR($(this)); });
|
||||||
var counter = $("#notice_text-count");
|
|
||||||
|
|
||||||
if (remaining.toString() != counter.text()) {
|
SN.U.NoticeReply();
|
||||||
if (!counterBlackout || remaining == 0) {
|
|
||||||
if (counter.text() != String(remaining)) {
|
|
||||||
counter.text(remaining);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remaining < 0) {
|
SN.U.NoticeDataAttach();
|
||||||
$("#form_notice").addClass("warning");
|
|
||||||
} else {
|
|
||||||
$("#form_notice").removeClass("warning");
|
|
||||||
}
|
|
||||||
// Skip updates for the next 500ms.
|
|
||||||
// On slower hardware, updating on every keypress is unpleasant.
|
|
||||||
if (!counterBlackout) {
|
|
||||||
counterBlackout = true;
|
|
||||||
window.setTimeout(clearCounterBlackout, 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearCounterBlackout() {
|
SN.U.NewDirectMessage();
|
||||||
// Allow keyup events to poke the counter again
|
|
||||||
counterBlackout = false;
|
|
||||||
// Check if the string changed since we last looked
|
|
||||||
counter(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
function submitonreturn(event) {
|
|
||||||
if (event.keyCode == 13 || event.keyCode == 10) {
|
|
||||||
// iPhone sends \n not \r for 'return'
|
|
||||||
$("#form_notice").submit();
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
$("#notice_data-text").blur();
|
|
||||||
$("body").focus();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// define maxLength if it wasn't defined already
|
|
||||||
|
|
||||||
if (typeof(maxLength) == "undefined") {
|
|
||||||
maxLength = 140;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($("#notice_data-text").length) {
|
SN.U.NoticeAttachments();
|
||||||
if (maxLength > 0) {
|
|
||||||
$("#notice_data-text").bind("keyup", counter);
|
|
||||||
// run once in case there's something in there
|
|
||||||
counter();
|
|
||||||
}
|
|
||||||
|
|
||||||
$("#notice_data-text").bind("keydown", submitonreturn);
|
|
||||||
|
|
||||||
if($('body')[0].id != 'conversation') {
|
|
||||||
$("#notice_data-text").focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: refactor this code
|
|
||||||
|
|
||||||
var favoptions = { dataType: 'xml',
|
|
||||||
beforeSubmit: function(data, target, options) {
|
|
||||||
$(target).addClass('processing');
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
|
|
||||||
var dis = new_form.id;
|
|
||||||
var fav = dis.replace('disfavor', 'favor');
|
|
||||||
$('form#'+fav).replaceWith(new_form);
|
|
||||||
$('form#'+dis).ajaxForm(disoptions).each(addAjaxHidden);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var disoptions = { dataType: 'xml',
|
|
||||||
beforeSubmit: function(data, target, options) {
|
|
||||||
$(target).addClass('processing');
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
|
|
||||||
var fav = new_form.id;
|
|
||||||
var dis = fav.replace('favor', 'disfavor');
|
|
||||||
$('form#'+dis).replaceWith(new_form);
|
|
||||||
$('form#'+fav).ajaxForm(favoptions).each(addAjaxHidden);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var joinoptions = { dataType: 'xml',
|
|
||||||
success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
|
|
||||||
var leave = new_form.id;
|
|
||||||
var join = leave.replace('leave', 'join');
|
|
||||||
$('form#'+join).replaceWith(new_form);
|
|
||||||
$('form#'+leave).ajaxForm(leaveoptions).each(addAjaxHidden);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var leaveoptions = { dataType: 'xml',
|
|
||||||
success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
|
|
||||||
var join = new_form.id;
|
|
||||||
var leave = join.replace('join', 'leave');
|
|
||||||
$('form#'+leave).replaceWith(new_form);
|
|
||||||
$('form#'+join).ajaxForm(joinoptions).each(addAjaxHidden);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function addAjaxHidden() {
|
|
||||||
var ajax = document.createElement('input');
|
|
||||||
ajax.setAttribute('type', 'hidden');
|
|
||||||
ajax.setAttribute('name', 'ajax');
|
|
||||||
ajax.setAttribute('value', 1);
|
|
||||||
this.appendChild(ajax);
|
|
||||||
}
|
|
||||||
|
|
||||||
$("form.form_favor").ajaxForm(favoptions);
|
|
||||||
$("form.form_disfavor").ajaxForm(disoptions);
|
|
||||||
$("form.form_group_join").ajaxForm(joinoptions);
|
|
||||||
$("form.form_group_leave").ajaxForm(leaveoptions);
|
|
||||||
$("form.form_favor").each(addAjaxHidden);
|
|
||||||
$("form.form_disfavor").each(addAjaxHidden);
|
|
||||||
$("form.form_group_join").each(addAjaxHidden);
|
|
||||||
$("form.form_group_leave").each(addAjaxHidden);
|
|
||||||
|
|
||||||
$("#form_user_nudge").ajaxForm ({ dataType: 'xml',
|
|
||||||
beforeSubmit: function(xml) { $("#form_user_nudge input[type=submit]").attr("disabled", "disabled");
|
|
||||||
$("#form_user_nudge input[type=submit]").addClass("disabled");
|
|
||||||
},
|
|
||||||
success: function(xml) { $("#form_user_nudge").replaceWith(document._importNode($("#nudge_response", xml).get(0),true));
|
|
||||||
$("#form_user_nudge input[type=submit]").removeAttr("disabled");
|
|
||||||
$("#form_user_nudge input[type=submit]").removeClass("disabled");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$("#form_user_nudge").each(addAjaxHidden);
|
|
||||||
|
|
||||||
var Subscribe = { dataType: 'xml',
|
|
||||||
beforeSubmit: function(formData, jqForm, options) { $(".form_user_subscribe input[type=submit]").attr("disabled", "disabled");
|
|
||||||
$(".form_user_subscribe input[type=submit]").addClass("disabled");
|
|
||||||
},
|
|
||||||
success: function(xml) { var form_unsubscribe = document._importNode($('form', xml).get(0), true);
|
|
||||||
var form_unsubscribe_id = form_unsubscribe.id;
|
|
||||||
var form_subscribe_id = form_unsubscribe_id.replace('unsubscribe', 'subscribe');
|
|
||||||
$("form#"+form_subscribe_id).replaceWith(form_unsubscribe);
|
|
||||||
$("form#"+form_unsubscribe_id).ajaxForm(UnSubscribe).each(addAjaxHidden);
|
|
||||||
$("dd.subscribers").text(parseInt($("dd.subscribers").text())+1);
|
|
||||||
$(".form_user_subscribe input[type=submit]").removeAttr("disabled");
|
|
||||||
$(".form_user_subscribe input[type=submit]").removeClass("disabled");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var UnSubscribe = { dataType: 'xml',
|
|
||||||
beforeSubmit: function(formData, jqForm, options) { $(".form_user_unsubscribe input[type=submit]").attr("disabled", "disabled");
|
|
||||||
$(".form_user_unsubscribe input[type=submit]").addClass("disabled");
|
|
||||||
},
|
|
||||||
success: function(xml) { var form_subscribe = document._importNode($('form', xml).get(0), true);
|
|
||||||
var form_subscribe_id = form_subscribe.id;
|
|
||||||
var form_unsubscribe_id = form_subscribe_id.replace('subscribe', 'unsubscribe');
|
|
||||||
$("form#"+form_unsubscribe_id).replaceWith(form_subscribe);
|
|
||||||
$("form#"+form_subscribe_id).ajaxForm(Subscribe).each(addAjaxHidden);
|
|
||||||
$("#profile_send_a_new_message").remove();
|
|
||||||
$("#profile_nudge").remove();
|
|
||||||
$("dd.subscribers").text(parseInt($("dd.subscribers").text())-1);
|
|
||||||
$(".form_user_unsubscribe input[type=submit]").removeAttr("disabled");
|
|
||||||
$(".form_user_unsubscribe input[type=submit]").removeClass("disabled");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$(".form_user_subscribe").ajaxForm(Subscribe);
|
|
||||||
$(".form_user_unsubscribe").ajaxForm(UnSubscribe);
|
|
||||||
$(".form_user_subscribe").each(addAjaxHidden);
|
|
||||||
$(".form_user_unsubscribe").each(addAjaxHidden);
|
|
||||||
|
|
||||||
var PostNotice = { dataType: 'xml',
|
|
||||||
beforeSubmit: function(formData, jqForm, options) { if ($("#notice_data-text").get(0).value.length == 0) {
|
|
||||||
$("#form_notice").addClass("warning");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$("#form_notice").addClass("processing");
|
|
||||||
$("#notice_action-submit").attr("disabled", "disabled");
|
|
||||||
$("#notice_action-submit").addClass("disabled");
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
timeout: '60000',
|
|
||||||
error: function (xhr, textStatus, errorThrown) { $("#form_notice").removeClass("processing");
|
|
||||||
$("#notice_action-submit").removeAttr("disabled");
|
|
||||||
$("#notice_action-submit").removeClass("disabled");
|
|
||||||
if (textStatus == "timeout") {
|
|
||||||
alert ("Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ($(".error", xhr.responseXML).length > 0) {
|
|
||||||
$('#form_notice').append(document._importNode($(".error", xhr.responseXML).get(0), true));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var HTTP20x30x = [200, 201, 202, 203, 204, 205, 206, 300, 301, 302, 303, 304, 305, 306, 307];
|
|
||||||
if(jQuery.inArray(parseInt(xhr.status), HTTP20x30x) < 0) {
|
|
||||||
alert("Sorry! We had trouble sending your notice ("+xhr.status+" "+xhr.statusText+"). Please report the problem to the site administrator if this happens again.");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$("#notice_data-text").val("");
|
|
||||||
if (maxLength > 0) {
|
|
||||||
counter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
success: function(xml) { if ($("#error", xml).length > 0) {
|
|
||||||
var result = document._importNode($("p", xml).get(0), true);
|
|
||||||
result = result.textContent || result.innerHTML;
|
|
||||||
alert(result);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ($("#command_result", xml).length > 0) {
|
|
||||||
var result = document._importNode($("p", xml).get(0), true);
|
|
||||||
result = result.textContent || result.innerHTML;
|
|
||||||
alert(result);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
li = $("li", xml).get(0);
|
|
||||||
if ($("#"+li.id).length == 0) {
|
|
||||||
var notice_irt_value = $('#notice_in-reply-to').val();
|
|
||||||
var notice_irt = '#notices_primary #notice-'+notice_irt_value;
|
|
||||||
if($('body')[0].id == 'conversation') {
|
|
||||||
if(notice_irt_value.length > 0 && $(notice_irt+' .notices').length < 1) {
|
|
||||||
$(notice_irt).append('<ul class="notices"></ul>');
|
|
||||||
}
|
|
||||||
$($(notice_irt+' .notices')[0]).append(document._importNode(li, true));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$("#notices_primary .notices").prepend(document._importNode(li, true));
|
|
||||||
}
|
|
||||||
$('#'+li.id).css({display:'none'});
|
|
||||||
$('#'+li.id).fadeIn(2500);
|
|
||||||
NoticeReply();
|
|
||||||
NoticeAttachments();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$("#notice_data-text").val("");
|
|
||||||
$("#notice_data-attach").val("");
|
|
||||||
$("#notice_in-reply-to").val("");
|
|
||||||
$('#notice_data-attach_selected').remove();
|
|
||||||
if (maxLength > 0) {
|
|
||||||
counter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$("#form_notice").removeClass("processing");
|
|
||||||
$("#notice_action-submit").removeAttr("disabled");
|
|
||||||
$("#notice_action-submit").removeClass("disabled");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$("#form_notice").ajaxForm(PostNotice);
|
|
||||||
$("#form_notice").each(addAjaxHidden);
|
|
||||||
NoticeReply();
|
|
||||||
NoticeAttachments();
|
|
||||||
NoticeDataAttach();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function NoticeReply() {
|
|
||||||
if ($('#notice_data-text').length > 0 && $('#content .notice_reply').length > 0) {
|
var SN = { // StatusNet
|
||||||
$('#content .notice').each(function() {
|
C: { // Config
|
||||||
var notice = $(this)[0];
|
I: { // Init
|
||||||
$($('.notice_reply', notice)[0]).click(function() {
|
CounterBlackout: false,
|
||||||
var nickname = ($('.author .nickname', notice).length > 0) ? $($('.author .nickname', notice)[0]) : $('.author .nickname.uid');
|
MaxLength: 140,
|
||||||
NoticeReplySet(nickname.text(), $($('.notice_id', notice)[0]).text());
|
PatternUsername: /^[0-9a-zA-Z\-_.]*$/,
|
||||||
|
HTTP20x30x: [200, 201, 202, 203, 204, 205, 206, 300, 301, 302, 303, 304, 305, 306, 307]
|
||||||
|
},
|
||||||
|
|
||||||
|
S: { // Selector
|
||||||
|
Disabled: 'disabled',
|
||||||
|
Warning: 'warning',
|
||||||
|
Error: 'error',
|
||||||
|
Success: 'success',
|
||||||
|
Processing: 'processing',
|
||||||
|
CommandResult: 'command_result',
|
||||||
|
FormNotice: 'form_notice',
|
||||||
|
NoticeDataText: 'notice_data-text',
|
||||||
|
NoticeTextCount: 'notice_text-count',
|
||||||
|
NoticeInReplyTo: 'notice_in-reply-to',
|
||||||
|
NoticeDataAttach: 'notice_data-attach',
|
||||||
|
NoticeDataAttachSelected: 'notice_data-attach_selected',
|
||||||
|
NoticeActionSubmit: 'notice_action-submit'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
U: { // Utils
|
||||||
|
FormNoticeEnhancements: function(form) {
|
||||||
|
form_id = form.attr('id');
|
||||||
|
if (maxLength > 0) {
|
||||||
|
$('#'+form_id+' #'+SN.C.S.NoticeDataText).bind('keyup', function(e) {
|
||||||
|
SN.U.Counter(form);
|
||||||
|
});
|
||||||
|
// run once in case there's something in there
|
||||||
|
SN.U.Counter(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#'+form_id+' #'+SN.C.S.NoticeDataText).bind('keydown', function(e) {
|
||||||
|
SN.U.SubmitOnReturn(e, form);
|
||||||
|
});
|
||||||
|
|
||||||
|
if($('body')[0].id != 'conversation') {
|
||||||
|
$('#'+form_id+' textarea').focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
SN.U.FormNoticeXHR(form);
|
||||||
|
},
|
||||||
|
|
||||||
|
SubmitOnReturn: function(event, el) {
|
||||||
|
if (event.keyCode == 13 || event.keyCode == 10) {
|
||||||
|
el.submit();
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
$('#'+el[0].id+' #'+SN.U.NoticeDataText).blur();
|
||||||
|
$('body').focus();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
Counter: function(form) {
|
||||||
|
SN.C.I.FormNoticeCurrent = form;
|
||||||
|
form_id = form.attr('id');
|
||||||
|
if (typeof(maxLength) == "undefined") {
|
||||||
|
maxLength = SN.C.I.MaxLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxLength <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var remaining = maxLength - $('#'+form_id+' #'+SN.C.S.NoticeDataText).val().length;
|
||||||
|
var counter = $('#'+form_id+' #'+SN.C.S.NoticeTextCount);
|
||||||
|
|
||||||
|
if (remaining.toString() != counter.text()) {
|
||||||
|
if (!SN.C.I.CounterBlackout || remaining == 0) {
|
||||||
|
if (counter.text() != String(remaining)) {
|
||||||
|
counter.text(remaining);
|
||||||
|
}
|
||||||
|
if (remaining < 0) {
|
||||||
|
form.addClass(SN.C.S.Warning);
|
||||||
|
} else {
|
||||||
|
form.removeClass(SN.C.S.Warning);
|
||||||
|
}
|
||||||
|
// Skip updates for the next 500ms.
|
||||||
|
// On slower hardware, updating on every keypress is unpleasant.
|
||||||
|
if (!SN.C.I.CounterBlackout) {
|
||||||
|
SN.C.I.CounterBlackout = true;
|
||||||
|
SN.C.I.FormNoticeCurrent = form;
|
||||||
|
window.setTimeout("SN.U.ClearCounterBlackout(SN.C.I.FormNoticeCurrent);", 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ClearCounterBlackout: function(form) {
|
||||||
|
// Allow keyup events to poke the counter again
|
||||||
|
SN.C.I.CounterBlackout = false;
|
||||||
|
// Check if the string changed since we last looked
|
||||||
|
SN.U.Counter(form);
|
||||||
|
},
|
||||||
|
|
||||||
|
FormXHR: function(f) {
|
||||||
|
f.bind('submit', function(e) {
|
||||||
|
form_id = $(this)[0].id;
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
dataType: 'xml',
|
||||||
|
url: $(this)[0].action,
|
||||||
|
data: $(this).serialize() + '&ajax=1',
|
||||||
|
beforeSend: function(xhr) {
|
||||||
|
$('#'+form_id).addClass(SN.C.S.Processing);
|
||||||
|
$('#'+form_id+' .submit').addClass(SN.C.S.Disabled);
|
||||||
|
$('#'+form_id+' .submit').attr(SN.C.S.Disabled, SN.C.S.Disabled);
|
||||||
|
},
|
||||||
|
error: function (xhr, textStatus, errorThrown) {
|
||||||
|
alert(errorThrown || textStatus);
|
||||||
|
},
|
||||||
|
success: function(data, textStatus) {
|
||||||
|
if (typeof($('form', data)[0]) != 'undefined') {
|
||||||
|
form_new = document._importNode($('form', data)[0], true);
|
||||||
|
$('#'+form_id).replaceWith(form_new);
|
||||||
|
$('#'+form_new.id).each(function() { SN.U.FormXHR($(this)); });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('#'+form_id).replaceWith(document._importNode($('p', data)[0], true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
});
|
},
|
||||||
|
|
||||||
|
FormNoticeXHR: function(form) {
|
||||||
|
form_id = form.attr('id');
|
||||||
|
form.append('<input type="hidden" name="ajax" value="1"/>');
|
||||||
|
form.ajaxForm({
|
||||||
|
dataType: 'xml',
|
||||||
|
timeout: '60000',
|
||||||
|
beforeSend: function(xhr) {
|
||||||
|
if ($('#'+form_id+' #'+SN.C.S.NoticeDataText)[0].value.length === 0) {
|
||||||
|
form.addClass(SN.C.S.Warning);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
form.addClass(SN.C.S.Processing);
|
||||||
|
$('#'+form_id+' #'+SN.C.S.NoticeActionSubmit).addClass(SN.C.S.Disabled);
|
||||||
|
$('#'+form_id+' #'+SN.C.S.NoticeActionSubmit).attr(SN.C.S.Disabled, SN.C.S.Disabled);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
error: function (xhr, textStatus, errorThrown) {
|
||||||
|
form.removeClass(SN.C.S.Processing);
|
||||||
|
$('#'+form_id+' #'+SN.C.S.NoticeActionSubmit).removeClass(SN.C.S.Disabled);
|
||||||
|
$('#'+form_id+' #'+SN.C.S.NoticeActionSubmit).removeAttr(SN.C.S.Disabled, SN.C.S.Disabled);
|
||||||
|
if (textStatus == 'timeout') {
|
||||||
|
alert ('Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($('.'+SN.C.S.Error, xhr.responseXML).length > 0) {
|
||||||
|
form.append(document._importNode($('.'+SN.C.S.Error, xhr.responseXML)[0], true));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(jQuery.inArray(parseInt(xhr.status), SN.C.I.HTTP20x30x) < 0) {
|
||||||
|
alert('Sorry! We had trouble sending your notice ('+xhr.status+' '+xhr.statusText+'). Please report the problem to the site administrator if this happens again.');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('#'+form_id+' #'+SN.C.S.NoticeDataText).val('');
|
||||||
|
SN.U.Counter($('#'+SN.C.S.FormNotice));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
success: function(data, textStatus) {
|
||||||
|
if ($('#'+SN.C.S.Error, data).length > 0) {
|
||||||
|
var result = document._importNode($('p', data)[0], true);
|
||||||
|
alert(result.textContent || result.innerHTML);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if($('body')[0].id == 'bookmarklet') {
|
||||||
|
self.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($('#'+SN.C.S.CommandResult, data).length > 0) {
|
||||||
|
var result = document._importNode($('p', data)[0], true);
|
||||||
|
alert(result.textContent || result.innerHTML);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
notice = document._importNode($('li', data)[0], true);
|
||||||
|
if ($('#'+notice.id).length == 0) {
|
||||||
|
var notice_irt_value = $('#'+SN.C.S.NoticeInReplyTo).val();
|
||||||
|
var notice_irt = '#notices_primary #notice-'+notice_irt_value;
|
||||||
|
if($('body')[0].id == 'conversation') {
|
||||||
|
if(notice_irt_value.length > 0 && $(notice_irt+' .notices').length < 1) {
|
||||||
|
$(notice_irt).append('<ul class="notices"></ul>');
|
||||||
|
}
|
||||||
|
$($(notice_irt+' .notices')[0]).append(notice);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$("#notices_primary .notices").prepend(notice);
|
||||||
|
}
|
||||||
|
$('#'+notice.id).css({display:'none'});
|
||||||
|
$('#'+notice.id).fadeIn(2500);
|
||||||
|
SN.U.NoticeAttachments();
|
||||||
|
SN.U.NoticeReply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$('#'+form_id+' #'+SN.C.S.NoticeDataText).val('');
|
||||||
|
$('#'+form_id+' #'+SN.C.S.NoticeDataAttach).val('');
|
||||||
|
$('#'+form_id+' #'+SN.C.S.NoticeInReplyTo).val('');
|
||||||
|
$('#'+form_id+' #'+SN.C.S.NoticeDataAttachSelected).remove();
|
||||||
|
SN.U.Counter($('#'+SN.C.S.FormNotice));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
complete: function(xhr, textStatus) {
|
||||||
|
form.removeClass(SN.C.S.Processing);
|
||||||
|
$('#'+form_id+' #'+SN.C.S.NoticeActionSubmit).removeAttr(SN.C.S.Disabled);
|
||||||
|
$('#'+form_id+' #'+SN.C.S.NoticeActionSubmit).removeClass(SN.C.S.Disabled);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
NoticeReply: function() {
|
||||||
|
if ($('#'+SN.C.S.NoticeDataText).length > 0 && $('#content .notice_reply').length > 0) {
|
||||||
|
$('#content .notice').each(function() {
|
||||||
|
var notice = $(this)[0];
|
||||||
|
$($('.notice_reply', notice)[0]).click(function() {
|
||||||
|
var nickname = ($('.author .nickname', notice).length > 0) ? $($('.author .nickname', notice)[0]) : $('.author .nickname.uid');
|
||||||
|
SN.U.NoticeReplySet(nickname.text(), $($('.notice_id', notice)[0]).text());
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
NoticeReplySet: function(nick,id) {
|
||||||
|
if (nick.match(SN.C.I.PatternUsername)) {
|
||||||
|
var text = $('#'+SN.C.S.NoticeDataText);
|
||||||
|
if (text.length) {
|
||||||
|
replyto = '@' + nick + ' ';
|
||||||
|
text.val(replyto + text.val().replace(RegExp(replyto, 'i'), ''));
|
||||||
|
$('#'+SN.C.S.FormNotice+' input#'+SN.C.S.NoticeInReplyTo).val(id);
|
||||||
|
if (text.get(0).setSelectionRange) {
|
||||||
|
var len = text.val().length;
|
||||||
|
text.get(0).setSelectionRange(len,len);
|
||||||
|
text.get(0).focus();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
NoticeAttachments: function() {
|
||||||
|
$.fn.jOverlay.options = {
|
||||||
|
method : 'GET',
|
||||||
|
data : '',
|
||||||
|
url : '',
|
||||||
|
color : '#000',
|
||||||
|
opacity : '0.6',
|
||||||
|
zIndex : 99,
|
||||||
|
center : false,
|
||||||
|
imgLoading : $('address .url')[0].href+'theme/base/images/illustrations/illu_progress_loading-01.gif',
|
||||||
|
bgClickToClose : true,
|
||||||
|
success : function() {
|
||||||
|
$('#jOverlayContent').append('<button>×</button>');
|
||||||
|
$('#jOverlayContent button').click($.closeOverlay);
|
||||||
|
},
|
||||||
|
timeout : 0,
|
||||||
|
autoHide : true,
|
||||||
|
css : {'max-width':'542px', 'top':'5%', 'left':'32.5%'}
|
||||||
|
};
|
||||||
|
|
||||||
|
$('#content .notice a.attachment').click(function() {
|
||||||
|
$().jOverlay({url: $('address .url')[0].href+'attachment/' + ($(this).attr('id').substring('attachment'.length + 1)) + '/ajax'});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
var t;
|
||||||
|
$("body:not(#shownotice) #content .notice a.thumbnail").hover(
|
||||||
|
function() {
|
||||||
|
var anchor = $(this);
|
||||||
|
$("a.thumbnail").children('img').hide();
|
||||||
|
anchor.closest(".entry-title").addClass('ov');
|
||||||
|
|
||||||
|
if (anchor.children('img').length == 0) {
|
||||||
|
t = setTimeout(function() {
|
||||||
|
$.get($('address .url')[0].href+'attachment/' + (anchor.attr('id').substring('attachment'.length + 1)) + '/thumbnail', null, function(data) {
|
||||||
|
anchor.append(data);
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
anchor.children('img').show();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
clearTimeout(t);
|
||||||
|
$("a.thumbnail").children('img').hide();
|
||||||
|
$(this).closest(".entry-title").removeClass('ov');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
NoticeDataAttach: function() {
|
||||||
|
NDA = $('#'+SN.C.S.NoticeDataAttach);
|
||||||
|
NDA.change(function() {
|
||||||
|
S = '<div id="'+SN.C.S.NoticeDataAttachSelected+'" class="'+SN.C.S.Success+'"><code>'+$(this).val()+'</code> <button>×</button></div>';
|
||||||
|
NDAS = $('#'+SN.C.S.NoticeDataAttachSelected);
|
||||||
|
(NDAS.length > 0) ? NDAS.replaceWith(S) : $('#'+SN.C.S.FormNotice).append(S);
|
||||||
|
$('#'+SN.C.S.NoticeDataAttachSelected+' button').click(function(){
|
||||||
|
$('#'+SN.C.S.NoticeDataAttachSelected).remove();
|
||||||
|
NDA.val('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
NewDirectMessage: function() {
|
||||||
|
NDM = $('.entity_send-a-message a');
|
||||||
|
NDM.attr({'href':NDM.attr('href')+'&ajax=1'});
|
||||||
|
NDM.click(function() {
|
||||||
|
var NDMF = $('.entity_send-a-message form');
|
||||||
|
if (NDMF.length == 0) {
|
||||||
|
$.get(NDM.attr('href'), null, function(data) {
|
||||||
|
$('.entity_send-a-message').append(document._importNode($('form', data).get(0), true));
|
||||||
|
NDMF = $('.entity_send-a-message .form_notice');
|
||||||
|
SN.U.FormNoticeEnhancements(NDMF);
|
||||||
|
NDMF.append('<button>×</button>');
|
||||||
|
$('.entity_send-a-message button').click(function(){
|
||||||
|
NDMF.hide();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NDMF.show();
|
||||||
|
$('.entity_send-a-message textarea').focus();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function NoticeReplySet(nick,id) {
|
|
||||||
rgx_username = /^[0-9a-zA-Z\-_.]*$/;
|
|
||||||
if (nick.match(rgx_username)) {
|
|
||||||
var text = $("#notice_data-text");
|
|
||||||
if (text.length) {
|
|
||||||
replyto = "@" + nick + " ";
|
|
||||||
text.val(replyto + text.val().replace(RegExp(replyto, 'i'), ''));
|
|
||||||
$("#form_notice input#notice_in-reply-to").val(id);
|
|
||||||
if (text.get(0).setSelectionRange) {
|
|
||||||
var len = text.val().length;
|
|
||||||
text.get(0).setSelectionRange(len,len);
|
|
||||||
text.get(0).focus();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function NoticeAttachments() {
|
|
||||||
$.fn.jOverlay.options = {
|
|
||||||
method : 'GET',
|
|
||||||
data : '',
|
|
||||||
url : '',
|
|
||||||
color : '#000',
|
|
||||||
opacity : '0.6',
|
|
||||||
zIndex : 99,
|
|
||||||
center : false,
|
|
||||||
imgLoading : $('address .url')[0].href+'theme/base/images/illustrations/illu_progress_loading-01.gif',
|
|
||||||
bgClickToClose : true,
|
|
||||||
success : function() {
|
|
||||||
$('#jOverlayContent').append('<button>×</button>');
|
|
||||||
$('#jOverlayContent button').click($.closeOverlay);
|
|
||||||
},
|
|
||||||
timeout : 0,
|
|
||||||
autoHide : true,
|
|
||||||
css : {'max-width':'542px', 'top':'5%', 'left':'32.5%'}
|
|
||||||
};
|
|
||||||
|
|
||||||
$('#content .notice a.attachment').click(function() {
|
|
||||||
$().jOverlay({url: $('address .url')[0].href+'attachment/' + ($(this).attr('id').substring('attachment'.length + 1)) + '/ajax'});
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
var t;
|
|
||||||
$("body:not(#shownotice) #content .notice a.thumbnail").hover(
|
|
||||||
function() {
|
|
||||||
var anchor = $(this);
|
|
||||||
$("a.thumbnail").children('img').hide();
|
|
||||||
anchor.closest(".entry-title").addClass('ov');
|
|
||||||
|
|
||||||
if (anchor.children('img').length == 0) {
|
|
||||||
t = setTimeout(function() {
|
|
||||||
$.get($('address .url')[0].href+'attachment/' + (anchor.attr('id').substring('attachment'.length + 1)) + '/thumbnail', null, function(data) {
|
|
||||||
anchor.append(data);
|
|
||||||
});
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
anchor.children('img').show();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function() {
|
|
||||||
clearTimeout(t);
|
|
||||||
$("a.thumbnail").children('img').hide();
|
|
||||||
$(this).closest(".entry-title").removeClass('ov');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function NoticeDataAttach() {
|
|
||||||
NDA = $('#notice_data-attach');
|
|
||||||
NDA.change(function() {
|
|
||||||
S = '<div id="notice_data-attach_selected" class="success"><code>'+$(this).val()+'</code> <button>×</button></div>';
|
|
||||||
NDAS = $('#notice_data-attach_selected');
|
|
||||||
(NDAS.length > 0) ? NDAS.replaceWith(S) : $('#form_notice').append(S);
|
|
||||||
$('#notice_data-attach_selected button').click(function(){
|
|
||||||
$('#notice_data-attach_selected').remove();
|
|
||||||
NDA.val('');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
20
lib/api.php
20
lib/api.php
|
@ -134,11 +134,19 @@ class ApiAction extends Action
|
||||||
$twitter_user['protected'] = false; # not supported by StatusNet yet
|
$twitter_user['protected'] = false; # not supported by StatusNet yet
|
||||||
$twitter_user['followers_count'] = $profile->subscriberCount();
|
$twitter_user['followers_count'] = $profile->subscriberCount();
|
||||||
|
|
||||||
// To be supported soon...
|
// Need to pull up the user for some of this
|
||||||
$twitter_user['profile_background_color'] = '';
|
$user = $profile->getUser();
|
||||||
$twitter_user['profile_text_color'] = '';
|
$design = $user->getDesign();
|
||||||
$twitter_user['profile_link_color'] = '';
|
$defaultDesign = Design::siteDesign();
|
||||||
$twitter_user['profile_sidebar_fill_color'] = '';
|
if (!$design) $design = $defaultDesign;
|
||||||
|
$color = Design::toWebColor(empty($design->backgroundcolor) ? $defaultDesign->backgroundcolor : $design->backgroundcolor);
|
||||||
|
$twitter_user['profile_background_color'] = ($color == null) ? '' : '#'.$color->hexValue();
|
||||||
|
$color = Design::toWebColor(empty($design->textcolor) ? $defaultDesign->textcolor : $design->textcolor);
|
||||||
|
$twitter_user['profile_text_color'] = ($color == null) ? '' : '#'.$color->hexValue();
|
||||||
|
$color = Design::toWebColor(empty($design->linkcolor) ? $defaultDesign->linkcolor : $design->linkcolor);
|
||||||
|
$twitter_user['profile_link_color'] = ($color == null) ? '' : '#'.$color->hexValue();
|
||||||
|
$color = Design::toWebColor(empty($design->sidebarcolor) ? $defaultDesign->sidebarcolor : $design->sidebarcolor);
|
||||||
|
$twitter_user['profile_sidebar_fill_color'] = ($color == null) ? '' : '#'.$color->hexValue();
|
||||||
$twitter_user['profile_sidebar_border_color'] = '';
|
$twitter_user['profile_sidebar_border_color'] = '';
|
||||||
|
|
||||||
$twitter_user['friends_count'] = $profile->subscriptionCount();
|
$twitter_user['friends_count'] = $profile->subscriptionCount();
|
||||||
|
@ -147,8 +155,6 @@ class ApiAction extends Action
|
||||||
|
|
||||||
$twitter_user['favourites_count'] = $profile->faveCount(); // British spelling!
|
$twitter_user['favourites_count'] = $profile->faveCount(); // British spelling!
|
||||||
|
|
||||||
// Need to pull up the user for some of this
|
|
||||||
$user = User::staticGet($profile->id);
|
|
||||||
|
|
||||||
$timezone = 'UTC';
|
$timezone = 'UTC';
|
||||||
|
|
||||||
|
|
124
lib/command.php
124
lib/command.php
|
@ -73,7 +73,7 @@ class UntrackCommand extends UnimplementedCommand
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NudgeCommand extends UnimplementedCommand
|
class NudgeCommand extends Command
|
||||||
{
|
{
|
||||||
var $other = null;
|
var $other = null;
|
||||||
function __construct($user, $other)
|
function __construct($user, $other)
|
||||||
|
@ -81,6 +81,26 @@ class NudgeCommand extends UnimplementedCommand
|
||||||
parent::__construct($user);
|
parent::__construct($user);
|
||||||
$this->other = $other;
|
$this->other = $other;
|
||||||
}
|
}
|
||||||
|
function execute($channel)
|
||||||
|
{
|
||||||
|
$recipient = User::staticGet('nickname', $this->other);
|
||||||
|
if(! $recipient){
|
||||||
|
$channel->error($this->user, sprintf(_('Could not find a user with nickname %s'),
|
||||||
|
$this->other));
|
||||||
|
}else{
|
||||||
|
if ($recipient->id == $this->user->id) {
|
||||||
|
$channel->error($this->user, _('It does not make a lot of sense to nudge yourself!'));
|
||||||
|
}else{
|
||||||
|
if ($recipient->email && $recipient->emailnotifynudge) {
|
||||||
|
mail_notify_nudge($this->user, $recipient);
|
||||||
|
}
|
||||||
|
// XXX: notify by IM
|
||||||
|
// XXX: notify by SMS
|
||||||
|
$channel->output($this->user, sprintf(_('Nudge sent to %s'),
|
||||||
|
$recipient->nickname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InviteCommand extends UnimplementedCommand
|
class InviteCommand extends UnimplementedCommand
|
||||||
|
@ -124,18 +144,30 @@ class FavCommand extends Command
|
||||||
|
|
||||||
function execute($channel)
|
function execute($channel)
|
||||||
{
|
{
|
||||||
|
if(substr($this->other,0,1)=='#'){
|
||||||
|
//favoriting a specific notice_id
|
||||||
|
|
||||||
$recipient =
|
$notice = Notice::staticGet(substr($this->other,1));
|
||||||
common_relative_profile($this->user, common_canonical_nickname($this->other));
|
if (!$notice) {
|
||||||
|
$channel->error($this->user, _('Notice with that id does not exist'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$recipient = $notice->getProfile();
|
||||||
|
}else{
|
||||||
|
//favoriting a given user's last notice
|
||||||
|
|
||||||
if (!$recipient) {
|
$recipient =
|
||||||
$channel->error($this->user, _('No such user.'));
|
common_relative_profile($this->user, common_canonical_nickname($this->other));
|
||||||
return;
|
|
||||||
}
|
if (!$recipient) {
|
||||||
$notice = $recipient->getCurrentNotice();
|
$channel->error($this->user, _('No such user.'));
|
||||||
if (!$notice) {
|
return;
|
||||||
$channel->error($this->user, _('User has no last notice'));
|
}
|
||||||
return;
|
$notice = $recipient->getCurrentNotice();
|
||||||
|
if (!$notice) {
|
||||||
|
$channel->error($this->user, _('User has no last notice'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$fave = Fave::addNew($this->user, $notice);
|
$fave = Fave::addNew($this->user, $notice);
|
||||||
|
@ -347,6 +379,71 @@ class MessageCommand extends Command
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ReplyCommand extends Command
|
||||||
|
{
|
||||||
|
var $other = null;
|
||||||
|
var $text = null;
|
||||||
|
function __construct($user, $other, $text)
|
||||||
|
{
|
||||||
|
parent::__construct($user);
|
||||||
|
$this->other = $other;
|
||||||
|
$this->text = $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
function execute($channel)
|
||||||
|
{
|
||||||
|
if(substr($this->other,0,1)=='#'){
|
||||||
|
//replying to a specific notice_id
|
||||||
|
|
||||||
|
$notice = Notice::staticGet(substr($this->other,1));
|
||||||
|
if (!$notice) {
|
||||||
|
$channel->error($this->user, _('Notice with that id does not exist'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$recipient = $notice->getProfile();
|
||||||
|
}else{
|
||||||
|
//replying to a given user's last notice
|
||||||
|
|
||||||
|
$recipient =
|
||||||
|
common_relative_profile($this->user, common_canonical_nickname($this->other));
|
||||||
|
|
||||||
|
if (!$recipient) {
|
||||||
|
$channel->error($this->user, _('No such user.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$notice = $recipient->getCurrentNotice();
|
||||||
|
if (!$notice) {
|
||||||
|
$channel->error($this->user, _('User has no last notice'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$len = mb_strlen($this->text);
|
||||||
|
|
||||||
|
if ($len == 0) {
|
||||||
|
$channel->error($this->user, _('No content!'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->text = common_shorten_links($this->text);
|
||||||
|
|
||||||
|
if (Notice::contentTooLong($this->text)) {
|
||||||
|
$channel->error($this->user, sprintf(_('Notice too long - maximum is %d characters, you sent %d'),
|
||||||
|
Notice::maxContent(), mb_strlen($this->text)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$notice = Notice::saveNew($this->user->id, $this->text, $channel->source(), 1,
|
||||||
|
$notice->id);
|
||||||
|
if ($notice) {
|
||||||
|
$channel->output($this->user, sprintf(_('Reply to %s sent'), $recipient->nickname));
|
||||||
|
} else {
|
||||||
|
$channel->error($this->user, _('Error saving notice.'));
|
||||||
|
}
|
||||||
|
common_broadcast_notice($notice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class GetCommand extends Command
|
class GetCommand extends Command
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -497,6 +594,9 @@ class HelpCommand extends Command
|
||||||
"get <nickname> - get last notice from user\n".
|
"get <nickname> - get last notice from user\n".
|
||||||
"whois <nickname> - get profile info on user\n".
|
"whois <nickname> - get profile info on user\n".
|
||||||
"fav <nickname> - add user's last notice as a 'fave'\n".
|
"fav <nickname> - add user's last notice as a 'fave'\n".
|
||||||
|
"fav #<notice_id> - add notice with the given id as a 'fave'\n".
|
||||||
|
"reply #<notice_id> - reply to notice with a given id\n".
|
||||||
|
"reply <nickname> - reply to the last notice from user\n".
|
||||||
"join <group> - join group\n".
|
"join <group> - join group\n".
|
||||||
"drop <group> - leave group\n".
|
"drop <group> - leave group\n".
|
||||||
"stats - get your stats\n".
|
"stats - get your stats\n".
|
||||||
|
@ -507,7 +607,7 @@ class HelpCommand extends Command
|
||||||
"last <nickname> - same as 'get'\n".
|
"last <nickname> - same as 'get'\n".
|
||||||
"on <nickname> - not yet implemented.\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".
|
"nudge <nickname> - remind a user to update.\n".
|
||||||
"invite <phone number> - not yet implemented.\n".
|
"invite <phone number> - not yet implemented.\n".
|
||||||
"track <word> - not yet implemented.\n".
|
"track <word> - not yet implemented.\n".
|
||||||
"untrack <word> - not yet implemented.\n".
|
"untrack <word> - not yet implemented.\n".
|
||||||
|
|
|
@ -134,6 +134,17 @@ class CommandInterpreter
|
||||||
} else {
|
} else {
|
||||||
return new MessageCommand($user, $other, $extra);
|
return new MessageCommand($user, $other, $extra);
|
||||||
}
|
}
|
||||||
|
case 'r':
|
||||||
|
case 'reply':
|
||||||
|
if (!$arg) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
list($other, $extra) = $this->split_arg($arg);
|
||||||
|
if (!$extra) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return new ReplyCommand($user, $other, $extra);
|
||||||
|
}
|
||||||
case 'whois':
|
case 'whois':
|
||||||
if (!$arg) {
|
if (!$arg) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -185,7 +185,14 @@ function _have_config()
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: Throw a conniption if database not installed
|
// XXX: Throw a conniption if database not installed
|
||||||
|
// XXX: Find a way to use htmlwriter for this instead of handcoded markup
|
||||||
|
if (!_have_config()) {
|
||||||
|
echo '<p>'. _('No configuation file found. ') .'</p>';
|
||||||
|
echo '<p>'. _('I looked for configuration files in the following places: ') .'<br/> '. implode($_config_files, '<br/>');
|
||||||
|
echo '<p>'. _('You may wish to run the installer to fix this.') .'</p>';
|
||||||
|
echo '<a href="install.php">'. _('Go to the installer.') .'</a>';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
// Fixup for statusnet.ini
|
// Fixup for statusnet.ini
|
||||||
|
|
||||||
$_db_name = substr($config['db']['database'], strrpos($config['db']['database'], '/') + 1);
|
$_db_name = substr($config['db']['database'], strrpos($config['db']['database'], '/') + 1);
|
||||||
|
@ -223,7 +230,6 @@ require_once INSTALLDIR.'/lib/theme.php';
|
||||||
require_once INSTALLDIR.'/lib/mail.php';
|
require_once INSTALLDIR.'/lib/mail.php';
|
||||||
require_once INSTALLDIR.'/lib/subs.php';
|
require_once INSTALLDIR.'/lib/subs.php';
|
||||||
require_once INSTALLDIR.'/lib/Shorturl_api.php';
|
require_once INSTALLDIR.'/lib/Shorturl_api.php';
|
||||||
require_once INSTALLDIR.'/lib/twitter.php';
|
|
||||||
|
|
||||||
require_once INSTALLDIR.'/lib/clientexception.php';
|
require_once INSTALLDIR.'/lib/clientexception.php';
|
||||||
require_once INSTALLDIR.'/lib/serverexception.php';
|
require_once INSTALLDIR.'/lib/serverexception.php';
|
||||||
|
|
|
@ -98,34 +98,37 @@ class ConnectSettingsNav extends Widget
|
||||||
|
|
||||||
function show()
|
function show()
|
||||||
{
|
{
|
||||||
# action => array('prompt', 'title')
|
|
||||||
$menu = array();
|
|
||||||
if (common_config('xmpp', 'enabled')) {
|
|
||||||
$menu['imsettings'] =
|
|
||||||
array(_('IM'),
|
|
||||||
_('Updates by instant messenger (IM)'));
|
|
||||||
}
|
|
||||||
if (common_config('sms', 'enabled')) {
|
|
||||||
$menu['smssettings'] =
|
|
||||||
array(_('SMS'),
|
|
||||||
_('Updates by SMS'));
|
|
||||||
}
|
|
||||||
if (common_config('twitter', 'enabled')) {
|
|
||||||
$menu['twittersettings'] =
|
|
||||||
array(_('Twitter'),
|
|
||||||
_('Twitter integration options'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$action_name = $this->action->trimmed('action');
|
$action_name = $this->action->trimmed('action');
|
||||||
$this->action->elementStart('ul', array('class' => 'nav'));
|
$this->action->elementStart('ul', array('class' => 'nav'));
|
||||||
|
|
||||||
foreach ($menu as $menuaction => $menudesc) {
|
if (Event::handle('StartConnectSettingsNav', array(&$this->action))) {
|
||||||
$this->action->menuItem(common_local_url($menuaction),
|
|
||||||
$menudesc[0],
|
# action => array('prompt', 'title')
|
||||||
$menudesc[1],
|
$menu = array();
|
||||||
$action_name === $menuaction);
|
if (common_config('xmpp', 'enabled')) {
|
||||||
|
$menu['imsettings'] =
|
||||||
|
array(_('IM'),
|
||||||
|
_('Updates by instant messenger (IM)'));
|
||||||
|
}
|
||||||
|
if (common_config('sms', 'enabled')) {
|
||||||
|
$menu['smssettings'] =
|
||||||
|
array(_('SMS'),
|
||||||
|
_('Updates by SMS'));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($menu as $menuaction => $menudesc) {
|
||||||
|
$this->action->menuItem(common_local_url($menuaction),
|
||||||
|
$menudesc[0],
|
||||||
|
$menudesc[1],
|
||||||
|
$action_name === $menuaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::handle('EndConnectSettingsNav', array(&$this->action));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->action->elementEnd('ul');
|
$this->action->elementEnd('ul');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
n<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* StatusNet, the distributed open-source microblogging tool
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
*
|
*
|
||||||
|
|
|
@ -84,7 +84,8 @@ $default =
|
||||||
'image' => 'http://i.creativecommons.org/l/by/3.0/80x15.png'),
|
'image' => 'http://i.creativecommons.org/l/by/3.0/80x15.png'),
|
||||||
'mail' =>
|
'mail' =>
|
||||||
array('backend' => 'mail',
|
array('backend' => 'mail',
|
||||||
'params' => null),
|
'params' => null,
|
||||||
|
'domain_check' => true),
|
||||||
'nickname' =>
|
'nickname' =>
|
||||||
array('blacklist' => array(),
|
array('blacklist' => array(),
|
||||||
'featured' => array()),
|
'featured' => array()),
|
||||||
|
@ -140,21 +141,21 @@ $default =
|
||||||
array('enabled' => true),
|
array('enabled' => true),
|
||||||
'sms' =>
|
'sms' =>
|
||||||
array('enabled' => true),
|
array('enabled' => true),
|
||||||
'twitterbridge' =>
|
'twitterimport' =>
|
||||||
array('enabled' => false),
|
array('enabled' => false),
|
||||||
'integration' =>
|
'integration' =>
|
||||||
array('source' => 'StatusNet', # source attribute for Twitter
|
array('source' => 'StatusNet', # source attribute for Twitter
|
||||||
'taguri' => $_server.',2009'), # base for tag URIs
|
'taguri' => $_server.',2009'), # base for tag URIs
|
||||||
'twitter' =>
|
'twitter' =>
|
||||||
array('enabled' => true,
|
array('enabled' => true,
|
||||||
'consumer_key' => null,
|
'consumer_key' => null,
|
||||||
'consumer_secret' => null),
|
'consumer_secret' => null),
|
||||||
'memcached' =>
|
'memcached' =>
|
||||||
array('enabled' => false,
|
array('enabled' => false,
|
||||||
'server' => 'localhost',
|
'server' => 'localhost',
|
||||||
'base' => null,
|
'base' => null,
|
||||||
'port' => 11211),
|
'port' => 11211),
|
||||||
'ping' =>
|
'ping' =>
|
||||||
array('notify' => array()),
|
array('notify' => array()),
|
||||||
'inboxes' =>
|
'inboxes' =>
|
||||||
array('enabled' => true), # ignored after 0.9.x
|
array('enabled' => true), # ignored after 0.9.x
|
||||||
|
@ -200,12 +201,12 @@ $default =
|
||||||
'video/mp4',
|
'video/mp4',
|
||||||
'video/quicktime',
|
'video/quicktime',
|
||||||
'video/mpeg'),
|
'video/mpeg'),
|
||||||
'file_quota' => 5000000,
|
'file_quota' => 5000000,
|
||||||
'user_quota' => 50000000,
|
'user_quota' => 50000000,
|
||||||
'monthly_quota' => 15000000,
|
'monthly_quota' => 15000000,
|
||||||
'uploads' => true,
|
'uploads' => true,
|
||||||
'filecommand' => '/usr/bin/file',
|
'filecommand' => '/usr/bin/file',
|
||||||
),
|
),
|
||||||
'group' =>
|
'group' =>
|
||||||
array('maxaliases' => 3,
|
array('maxaliases' => 3,
|
||||||
'desclimit' => null),
|
'desclimit' => null),
|
||||||
|
@ -229,4 +230,6 @@ $default =
|
||||||
array('contentlimit' => null),
|
array('contentlimit' => null),
|
||||||
'http' =>
|
'http' =>
|
||||||
array('client' => 'curl'), // XXX: should this be the default?
|
array('client' => 'curl'), // XXX: should this be the default?
|
||||||
|
'location' =>
|
||||||
|
array('namespace' => 1), // 1 = geonames, 2 = Yahoo Where on Earth
|
||||||
);
|
);
|
||||||
|
|
|
@ -48,7 +48,7 @@ if (!defined('STATUSNET')) {
|
||||||
class HTTPResponse
|
class HTTPResponse
|
||||||
{
|
{
|
||||||
public $code = null;
|
public $code = null;
|
||||||
public $headers = null;
|
public $headers = array();
|
||||||
public $body = null;
|
public $body = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -176,6 +176,7 @@ function jabber_format_entry($profile, $notice)
|
||||||
$xs = new XMLStringer();
|
$xs = new XMLStringer();
|
||||||
$xs->elementStart('html', array('xmlns' => 'http://jabber.org/protocol/xhtml-im'));
|
$xs->elementStart('html', array('xmlns' => 'http://jabber.org/protocol/xhtml-im'));
|
||||||
$xs->elementStart('body', array('xmlns' => 'http://www.w3.org/1999/xhtml'));
|
$xs->elementStart('body', array('xmlns' => 'http://www.w3.org/1999/xhtml'));
|
||||||
|
$xs->element("img", array('src'=> $profile->avatarUrl(AVATAR_MINI_SIZE) , 'alt' => $profile->nickname));
|
||||||
$xs->element('a', array('href' => $profile->profileurl),
|
$xs->element('a', array('href' => $profile->profileurl),
|
||||||
$profile->nickname);
|
$profile->nickname);
|
||||||
$xs->text(": ");
|
$xs->text(": ");
|
||||||
|
@ -184,6 +185,11 @@ function jabber_format_entry($profile, $notice)
|
||||||
} else {
|
} else {
|
||||||
$xs->raw(common_render_content($notice->content, $notice));
|
$xs->raw(common_render_content($notice->content, $notice));
|
||||||
}
|
}
|
||||||
|
$xs->raw(" ");
|
||||||
|
$xs->element('a', array(
|
||||||
|
'href'=>common_local_url('conversation',
|
||||||
|
array('id' => $notice->conversation)).'#notice-'.$notice->id
|
||||||
|
),sprintf(_('notice id: %s'),$notice->id));
|
||||||
$xs->elementEnd('body');
|
$xs->elementEnd('body');
|
||||||
$xs->elementEnd('html');
|
$xs->elementEnd('html');
|
||||||
|
|
||||||
|
|
|
@ -101,35 +101,36 @@ function get_nice_language_list()
|
||||||
*/
|
*/
|
||||||
function get_all_languages() {
|
function get_all_languages() {
|
||||||
return array(
|
return array(
|
||||||
'bg' => array('q' => 0.8, 'lang' => 'bg_BG', 'name' => 'Bulgarian', 'direction' => 'ltr'),
|
'bg' => array('q' => 0.8, 'lang' => 'bg', 'name' => 'Bulgarian', 'direction' => 'ltr'),
|
||||||
'ca' => array('q' => 0.5, 'lang' => 'ca_ES', 'name' => 'Catalan', 'direction' => 'ltr'),
|
'ca' => array('q' => 0.5, 'lang' => 'ca', 'name' => 'Catalan', 'direction' => 'ltr'),
|
||||||
'cs' => array('q' => 0.5, 'lang' => 'cs_CZ', 'name' => 'Czech', 'direction' => 'ltr'),
|
'cs' => array('q' => 0.5, 'lang' => 'cs', 'name' => 'Czech', 'direction' => 'ltr'),
|
||||||
'de' => array('q' => 0.8, 'lang' => 'de_DE', 'name' => 'German', 'direction' => 'ltr'),
|
'de' => array('q' => 0.8, 'lang' => 'de', 'name' => 'German', 'direction' => 'ltr'),
|
||||||
'el' => array('q' => 0.1, 'lang' => 'el', 'name' => 'Greek', 'direction' => 'ltr'),
|
'el' => array('q' => 0.1, 'lang' => 'el', 'name' => 'Greek', 'direction' => 'ltr'),
|
||||||
'en-us' => array('q' => 1, 'lang' => 'en_US', 'name' => 'English (US)', 'direction' => 'ltr'),
|
'en-us' => array('q' => 1, 'lang' => 'en', 'name' => 'English (US)', 'direction' => 'ltr'),
|
||||||
'en-gb' => array('q' => 1, 'lang' => 'en_GB', 'name' => 'English (British)', 'direction' => 'ltr'),
|
'en-gb' => array('q' => 1, 'lang' => 'en_GB', 'name' => 'English (British)', 'direction' => 'ltr'),
|
||||||
'en' => array('q' => 1, 'lang' => 'en_US', 'name' => 'English (US)', 'direction' => 'ltr'),
|
'en' => array('q' => 1, 'lang' => 'en', 'name' => 'English (US)', 'direction' => 'ltr'),
|
||||||
'es' => array('q' => 1, 'lang' => 'es', 'name' => 'Spanish', 'direction' => 'ltr'),
|
'es' => array('q' => 1, 'lang' => 'es', 'name' => 'Spanish', 'direction' => 'ltr'),
|
||||||
'fi' => array('q' => 1, 'lang' => 'fi', 'name' => 'Finnish', 'direction' => 'ltr'),
|
'fi' => array('q' => 1, 'lang' => 'fi', 'name' => 'Finnish', 'direction' => 'ltr'),
|
||||||
'fr-fr' => array('q' => 1, 'lang' => 'fr_FR', 'name' => 'French', 'direction' => 'ltr'),
|
'fr-fr' => array('q' => 1, 'lang' => 'fr', 'name' => 'French', 'direction' => 'ltr'),
|
||||||
'he' => array('q' => 0.5, 'lang' => 'he_IL', 'name' => 'Hebrew', 'direction' => 'rtl'),
|
'ga' => array('q' => 0.5, 'lang' => 'ga', 'name' => 'Galician', 'direction' => 'ltr'),
|
||||||
'it' => array('q' => 1, 'lang' => 'it_IT', 'name' => 'Italian', 'direction' => 'ltr'),
|
'he' => array('q' => 0.5, 'lang' => 'he', 'name' => 'Hebrew', 'direction' => 'rtl'),
|
||||||
'jp' => array('q' => 0.5, 'lang' => 'ja_JP', 'name' => 'Japanese', 'direction' => 'ltr'),
|
'it' => array('q' => 1, 'lang' => 'it', 'name' => 'Italian', 'direction' => 'ltr'),
|
||||||
'ko' => array('q' => 0.9, 'lang' => 'ko_KR', 'name' => 'Korean', 'direction' => 'ltr'),
|
'jp' => array('q' => 0.5, 'lang' => 'ja', 'name' => 'Japanese', 'direction' => 'ltr'),
|
||||||
'mk' => array('q' => 0.5, 'lang' => 'mk_MK', 'name' => 'Macedonian', 'direction' => 'ltr'),
|
'ko' => array('q' => 0.9, 'lang' => 'ko', 'name' => 'Korean', 'direction' => 'ltr'),
|
||||||
'nb' => array('q' => 0.1, 'lang' => 'nb_NO', 'name' => 'Norwegian (Bokmål)', 'direction' => 'ltr'),
|
'mk' => array('q' => 0.5, 'lang' => 'mk', 'name' => 'Macedonian', 'direction' => 'ltr'),
|
||||||
'no' => array('q' => 0.1, 'lang' => 'nb_NO', 'name' => 'Norwegian (Bokmål)', 'direction' => 'ltr'),
|
'nb' => array('q' => 0.1, 'lang' => 'nb', 'name' => 'Norwegian (Bokmål)', 'direction' => 'ltr'),
|
||||||
'nn' => array('q' => 1, 'lang' => 'nn_NO', 'name' => 'Norwegian (Nynorsk)', 'direction' => 'ltr'),
|
'no' => array('q' => 0.1, 'lang' => 'nb', 'name' => 'Norwegian (Bokmål)', 'direction' => 'ltr'),
|
||||||
'nl' => array('q' => 0.5, 'lang' => 'nl_NL', 'name' => 'Dutch', 'direction' => 'ltr'),
|
'nn' => array('q' => 1, 'lang' => 'nn', 'name' => 'Norwegian (Nynorsk)', 'direction' => 'ltr'),
|
||||||
'pl' => array('q' => 0.5, 'lang' => 'pl_PL', 'name' => 'Polish', 'direction' => 'ltr'),
|
'nl' => array('q' => 0.5, 'lang' => 'nl', 'name' => 'Dutch', 'direction' => 'ltr'),
|
||||||
|
'pl' => array('q' => 0.5, 'lang' => 'pl', 'name' => 'Polish', 'direction' => 'ltr'),
|
||||||
'pt' => array('q' => 0.1, 'lang' => 'pt', 'name' => 'Portuguese', 'direction' => 'ltr'),
|
'pt' => array('q' => 0.1, 'lang' => 'pt', 'name' => 'Portuguese', 'direction' => 'ltr'),
|
||||||
'pt-br' => array('q' => 0.9, 'lang' => 'pt_BR', 'name' => 'Portuguese Brazil', 'direction' => 'ltr'),
|
'pt-br' => array('q' => 0.9, 'lang' => 'pt_BR', 'name' => 'Portuguese Brazil', 'direction' => 'ltr'),
|
||||||
'ru' => array('q' => 0.9, 'lang' => 'ru_RU', 'name' => 'Russian', 'direction' => 'ltr'),
|
'ru' => array('q' => 0.9, 'lang' => 'ru', 'name' => 'Russian', 'direction' => 'ltr'),
|
||||||
'sv' => array('q' => 0.8, 'lang' => 'sv_SE', 'name' => 'Swedish', 'direction' => 'ltr'),
|
'sv' => array('q' => 0.8, 'lang' => 'sv', 'name' => 'Swedish', 'direction' => 'ltr'),
|
||||||
'te' => array('q' => 0.3, 'lang' => 'te_IN', 'name' => 'Telugu', 'direction' => 'ltr'),
|
'te' => array('q' => 0.3, 'lang' => 'te', 'name' => 'Telugu', 'direction' => 'ltr'),
|
||||||
'tr' => array('q' => 0.5, 'lang' => 'tr_TR', 'name' => 'Turkish', 'direction' => 'ltr'),
|
'tr' => array('q' => 0.5, 'lang' => 'tr', 'name' => 'Turkish', 'direction' => 'ltr'),
|
||||||
'uk' => array('q' => 1, 'lang' => 'uk_UA', 'name' => 'Ukrainian', 'direction' => 'ltr'),
|
'uk' => array('q' => 1, 'lang' => 'uk', 'name' => 'Ukrainian', 'direction' => 'ltr'),
|
||||||
'vi' => array('q' => 0.8, 'lang' => 'vi_VN', 'name' => 'Vietnamese', 'direction' => 'ltr'),
|
'vi' => array('q' => 0.8, 'lang' => 'vi', 'name' => 'Vietnamese', 'direction' => 'ltr'),
|
||||||
'zh-cn' => array('q' => 0.9, 'lang' => 'zh_CN', 'name' => 'Chinese (Simplified)', 'direction' => 'ltr'),
|
'zh-cn' => array('q' => 0.9, 'lang' => 'zh_CN', 'name' => 'Chinese (Simplified)', 'direction' => 'ltr'),
|
||||||
'zh-hant' => array('q' => 0.2, 'lang' => 'zh_TW', 'name' => 'Chinese (Taiwanese)', 'direction' => 'ltr'),
|
'zh-hant' => array('q' => 0.2, 'lang' => 'zh_TW', 'name' => 'Chinese (Taiwanese)', 'direction' => 'ltr'),
|
||||||
);
|
);
|
||||||
|
|
188
lib/location.php
Normal file
188
lib/location.php
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Class for locations
|
||||||
|
*
|
||||||
|
* 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 Location
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @copyright 2009 StatusNet, Inc.
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class for locations
|
||||||
|
*
|
||||||
|
* These are stored in the DB as part of notice and profile records,
|
||||||
|
* but since they're about the same in both, we have a separate class
|
||||||
|
* for them.
|
||||||
|
*
|
||||||
|
* @category Location
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Location
|
||||||
|
{
|
||||||
|
public $lat;
|
||||||
|
public $lon;
|
||||||
|
public $location_id;
|
||||||
|
public $location_ns;
|
||||||
|
private $_url;
|
||||||
|
|
||||||
|
var $names = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor that makes a Location from a string name
|
||||||
|
*
|
||||||
|
* @param string $name Human-readable name (any kind)
|
||||||
|
* @param string $language Language, default = common_language()
|
||||||
|
*
|
||||||
|
* @return Location Location with that name (or null if not found)
|
||||||
|
*/
|
||||||
|
|
||||||
|
static function fromName($name, $language=null)
|
||||||
|
{
|
||||||
|
if (is_null($language)) {
|
||||||
|
$language = common_language();
|
||||||
|
}
|
||||||
|
|
||||||
|
$location = null;
|
||||||
|
|
||||||
|
// Let a third-party handle it
|
||||||
|
|
||||||
|
Event::handle('LocationFromName', array($name, $language, &$location));
|
||||||
|
|
||||||
|
return $location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor that makes a Location from an ID
|
||||||
|
*
|
||||||
|
* @param integer $id Identifier ID
|
||||||
|
* @param integer $ns Namespace of the identifier
|
||||||
|
* @param string $language Language to return name in (default is common)
|
||||||
|
*
|
||||||
|
* @return Location The location with this ID (or null if none)
|
||||||
|
*/
|
||||||
|
|
||||||
|
static function fromId($id, $ns, $language=null)
|
||||||
|
{
|
||||||
|
if (is_null($language)) {
|
||||||
|
$language = common_language();
|
||||||
|
}
|
||||||
|
|
||||||
|
$location = null;
|
||||||
|
|
||||||
|
// Let a third-party handle it
|
||||||
|
|
||||||
|
Event::handle('LocationFromId', array($id, $ns, $language, &$location));
|
||||||
|
|
||||||
|
return $location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor that finds the nearest location to a lat/lon pair
|
||||||
|
*
|
||||||
|
* @param float $lat Latitude
|
||||||
|
* @param float $lon Longitude
|
||||||
|
* @param string $language Language for results, default = current
|
||||||
|
*
|
||||||
|
* @return Location the location found, or null if none found
|
||||||
|
*/
|
||||||
|
|
||||||
|
static function fromLatLon($lat, $lon, $language=null)
|
||||||
|
{
|
||||||
|
if (is_null($language)) {
|
||||||
|
$language = common_language();
|
||||||
|
}
|
||||||
|
|
||||||
|
$location = null;
|
||||||
|
|
||||||
|
// Let a third-party handle it
|
||||||
|
|
||||||
|
if (Event::handle('LocationFromLatLon',
|
||||||
|
array($lat, $lon, $language, &$location))) {
|
||||||
|
// Default is just the lat/lon pair
|
||||||
|
|
||||||
|
$location = new Location();
|
||||||
|
|
||||||
|
$location->lat = $lat;
|
||||||
|
$location->lon = $lon;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name for this location in the given language
|
||||||
|
*
|
||||||
|
* @param string $language language to use, default = current
|
||||||
|
*
|
||||||
|
* @return string location name or null if not found
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getName($language=null)
|
||||||
|
{
|
||||||
|
if (is_null($language)) {
|
||||||
|
$language = common_language();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists($language, $this->names)) {
|
||||||
|
return $this->names[$language];
|
||||||
|
} else {
|
||||||
|
$name = null;
|
||||||
|
Event::handle('LocationNameLanguage', array($this, $language, &$name));
|
||||||
|
if (!empty($name)) {
|
||||||
|
$this->names[$language] = $name;
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an URL suitable for this location
|
||||||
|
*
|
||||||
|
* @return string URL for this location or NULL
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getURL()
|
||||||
|
{
|
||||||
|
// Keep one cached
|
||||||
|
|
||||||
|
if (is_string($this->_url)) {
|
||||||
|
return $this->_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = null;
|
||||||
|
|
||||||
|
Event::handle('LocationUrl', array($this, &$url));
|
||||||
|
|
||||||
|
$this->_url = $url;
|
||||||
|
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
}
|
72
lib/mail.php
72
lib/mail.php
|
@ -640,75 +640,3 @@ function mail_notify_attn($user, $notice)
|
||||||
mail_to_user($user, $subject, $body);
|
mail_to_user($user, $subject, $body);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a mail message to notify a user that her Twitter bridge link
|
|
||||||
* has stopped working, and therefore has been removed. This can
|
|
||||||
* happen when the user changes her Twitter password, or otherwise
|
|
||||||
* revokes access.
|
|
||||||
*
|
|
||||||
* @param User $user user whose Twitter bridge link has been removed
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
|
|
||||||
function mail_twitter_bridge_removed($user)
|
|
||||||
{
|
|
||||||
common_init_locale($user->language);
|
|
||||||
|
|
||||||
$profile = $user->getProfile();
|
|
||||||
|
|
||||||
$subject = sprintf(_('Your Twitter bridge has been disabled.'));
|
|
||||||
|
|
||||||
$site_name = common_config('site', 'name');
|
|
||||||
|
|
||||||
$body = sprintf(_('Hi, %1$s. We\'re sorry to inform you that your ' .
|
|
||||||
'link to Twitter has been disabled. We no longer seem to have ' .
|
|
||||||
'permission to update your Twitter status. (Did you revoke ' .
|
|
||||||
'%3$s\'s access?)' . "\n\n" .
|
|
||||||
'You can re-enable your Twitter bridge by visiting your ' .
|
|
||||||
"Twitter settings page:\n\n\t%2\$s\n\n" .
|
|
||||||
"Regards,\n%3\$s\n"),
|
|
||||||
$profile->getBestName(),
|
|
||||||
common_local_url('twittersettings'),
|
|
||||||
common_config('site', 'name'));
|
|
||||||
|
|
||||||
common_init_locale();
|
|
||||||
return mail_to_user($user, $subject, $body);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a mail message to notify a user that her Facebook Application
|
|
||||||
* access has been removed.
|
|
||||||
*
|
|
||||||
* @param User $user user whose Facebook app link has been removed
|
|
||||||
*
|
|
||||||
* @return boolean success flag
|
|
||||||
*/
|
|
||||||
|
|
||||||
function mail_facebook_app_removed($user)
|
|
||||||
{
|
|
||||||
common_init_locale($user->language);
|
|
||||||
|
|
||||||
$profile = $user->getProfile();
|
|
||||||
|
|
||||||
$site_name = common_config('site', 'name');
|
|
||||||
|
|
||||||
$subject = sprintf(
|
|
||||||
_('Your %1$s Facebook application access has been disabled.',
|
|
||||||
$site_name));
|
|
||||||
|
|
||||||
$body = sprintf(_("Hi, %1\$s. We're sorry to inform you that we are " .
|
|
||||||
'unable to update your Facebook status from %2$s, and have disabled ' .
|
|
||||||
'the Facebook application for your account. This may be because ' .
|
|
||||||
'you have removed the Facebook application\'s authorization, or ' .
|
|
||||||
'have deleted your Facebook account. You can re-enable the ' .
|
|
||||||
'Facebook application and automatic status updating by ' .
|
|
||||||
"re-installing the %2\$s Facebook application.\n\nRegards,\n\n%2\$s"),
|
|
||||||
$user->nickname, $site_name);
|
|
||||||
|
|
||||||
common_init_locale();
|
|
||||||
return mail_to_user($user, $subject, $body);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
284
lib/mediafile.php
Normal file
284
lib/mediafile.php
Normal file
|
@ -0,0 +1,284 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Abstraction for media files in general
|
||||||
|
*
|
||||||
|
* TODO: combine with ImageFile?
|
||||||
|
*
|
||||||
|
* 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 Media
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Robin Millette <robin@millette.info>
|
||||||
|
* @author Zach Copley <zach@status.net>
|
||||||
|
* @copyright 2008-2009 StatusNet, Inc.
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
class MediaFile
|
||||||
|
{
|
||||||
|
|
||||||
|
var $filename = null;
|
||||||
|
var $fileRecord = null;
|
||||||
|
var $user = null;
|
||||||
|
var $fileurl = null;
|
||||||
|
var $short_fileurl = null;
|
||||||
|
var $mimetype = null;
|
||||||
|
|
||||||
|
function __construct($user = null, $filename = null, $mimetype = null)
|
||||||
|
{
|
||||||
|
if ($user == null) {
|
||||||
|
$this->user = common_current_user();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->filename = $filename;
|
||||||
|
$this->mimetype = $mimetype;
|
||||||
|
$this->fileRecord = $this->storeFile();
|
||||||
|
|
||||||
|
$this->fileurl = common_local_url('attachment',
|
||||||
|
array('attachment' => $this->fileRecord->id));
|
||||||
|
|
||||||
|
$this->maybeAddRedir($this->fileRecord->id, $this->fileurl);
|
||||||
|
$this->short_fileurl = common_shorten_url($this->fileurl);
|
||||||
|
$this->maybeAddRedir($this->fileRecord->id, $this->short_fileurl);
|
||||||
|
}
|
||||||
|
|
||||||
|
function attachToNotice($notice)
|
||||||
|
{
|
||||||
|
File_to_post::processNew($this->fileRecord->id, $notice->id);
|
||||||
|
$this->maybeAddRedir($this->fileRecord->id,
|
||||||
|
common_local_url('file', array('notice' => $notice->id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function shortUrl()
|
||||||
|
{
|
||||||
|
return $this->short_fileurl;
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete()
|
||||||
|
{
|
||||||
|
$filepath = File::path($this->filename);
|
||||||
|
@unlink($filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
function storeFile() {
|
||||||
|
|
||||||
|
$file = new File;
|
||||||
|
|
||||||
|
$file->filename = $this->filename;
|
||||||
|
$file->url = File::url($this->filename);
|
||||||
|
$filepath = File::path($this->filename);
|
||||||
|
$file->size = filesize($filepath);
|
||||||
|
$file->date = time();
|
||||||
|
$file->mimetype = $this->mimetype;
|
||||||
|
|
||||||
|
$file_id = $file->insert();
|
||||||
|
|
||||||
|
if (!$file_id) {
|
||||||
|
common_log_db_error($file, "INSERT", __FILE__);
|
||||||
|
throw new ClientException(_('There was a database error while saving your file. Please try again.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rememberFile($file, $short)
|
||||||
|
{
|
||||||
|
$this->maybeAddRedir($file->id, $short);
|
||||||
|
}
|
||||||
|
|
||||||
|
function maybeAddRedir($file_id, $url)
|
||||||
|
{
|
||||||
|
$file_redir = File_redirection::staticGet('url', $url);
|
||||||
|
|
||||||
|
if (empty($file_redir)) {
|
||||||
|
|
||||||
|
$file_redir = new File_redirection;
|
||||||
|
$file_redir->url = $url;
|
||||||
|
$file_redir->file_id = $file_id;
|
||||||
|
|
||||||
|
$result = $file_redir->insert();
|
||||||
|
|
||||||
|
if (!$result) {
|
||||||
|
common_log_db_error($file_redir, "INSERT", __FILE__);
|
||||||
|
throw new ClientException(_('There was a database error while saving your file. Please try again.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static function fromUpload($param = 'media', $user = null)
|
||||||
|
{
|
||||||
|
if (empty($user)) {
|
||||||
|
$user = common_current_user();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_FILES[$param]['error'])){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($_FILES[$param]['error']) {
|
||||||
|
case UPLOAD_ERR_OK: // success, jump out
|
||||||
|
break;
|
||||||
|
case UPLOAD_ERR_INI_SIZE:
|
||||||
|
throw new ClientException(_('The uploaded file exceeds the ' .
|
||||||
|
'upload_max_filesize directive in php.ini.'));
|
||||||
|
return;
|
||||||
|
case UPLOAD_ERR_FORM_SIZE:
|
||||||
|
throw new ClientException(
|
||||||
|
_('The uploaded file exceeds the MAX_FILE_SIZE directive' .
|
||||||
|
' that was specified in the HTML form.'));
|
||||||
|
return;
|
||||||
|
case UPLOAD_ERR_PARTIAL:
|
||||||
|
@unlink($_FILES[$param]['tmp_name']);
|
||||||
|
throw new ClientException(_('The uploaded file was only' .
|
||||||
|
' partially uploaded.'));
|
||||||
|
return;
|
||||||
|
case UPLOAD_ERR_NO_TMP_DIR:
|
||||||
|
throw new ClientException(_('Missing a temporary folder.'));
|
||||||
|
return;
|
||||||
|
case UPLOAD_ERR_CANT_WRITE:
|
||||||
|
throw new ClientException(_('Failed to write file to disk.'));
|
||||||
|
return;
|
||||||
|
case UPLOAD_ERR_EXTENSION:
|
||||||
|
throw new ClientException(_('File upload stopped by extension.'));
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
throw new ClientException(_('System error uploading file.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MediaFile::respectsQuota($user, $_FILES['attach']['size'])) {
|
||||||
|
|
||||||
|
// Should never actually get here
|
||||||
|
|
||||||
|
@unlink($_FILES[$param]['tmp_name']);
|
||||||
|
throw new ClientException(_('File exceeds user\'s quota!'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$mimetype = MediaFile::getUploadedFileType($_FILES[$param]['tmp_name']);
|
||||||
|
|
||||||
|
$filename = null;
|
||||||
|
|
||||||
|
if (isset($mimetype)) {
|
||||||
|
|
||||||
|
$basename = basename($_FILES[$param]['name']);
|
||||||
|
$filename = File::filename($user->getProfile(), $basename, $mimetype);
|
||||||
|
$filepath = File::path($filename);
|
||||||
|
|
||||||
|
$result = move_uploaded_file($_FILES[$param]['tmp_name'], $filepath);
|
||||||
|
|
||||||
|
if (!$result) {
|
||||||
|
throw new ClientException(_('File could not be moved to destination directory.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new ClientException(_('Could not determine file\'s mime-type!'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MediaFile($user, $filename, $mimetype);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function fromFilehandle($fh, $user) {
|
||||||
|
|
||||||
|
$stream = stream_get_meta_data($fh);
|
||||||
|
|
||||||
|
if (!MediaFile::respectsQuota($user, filesize($stream['uri']))) {
|
||||||
|
|
||||||
|
// Should never actually get here
|
||||||
|
|
||||||
|
throw new ClientException(_('File exceeds user\'s quota!'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$mimetype = MediaFile::getUploadedFileType($fh);
|
||||||
|
|
||||||
|
$filename = null;
|
||||||
|
|
||||||
|
if (isset($mimetype)) {
|
||||||
|
|
||||||
|
$filename = File::filename($user->getProfile(), "email", $mimetype);
|
||||||
|
|
||||||
|
$filepath = File::path($filename);
|
||||||
|
|
||||||
|
$result = copy($stream['uri'], $filepath) && chmod($filepath, 0664);
|
||||||
|
|
||||||
|
if (!$result) {
|
||||||
|
throw new ClientException(_('File could not be moved to destination directory.' .
|
||||||
|
$stream['uri'] . ' ' . $filepath));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new ClientException(_('Could not determine file\'s mime-type!'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MediaFile($user, $filename, $mimetype);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function getUploadedFileType($f) {
|
||||||
|
require_once 'MIME/Type.php';
|
||||||
|
|
||||||
|
$cmd = &PEAR::getStaticProperty('MIME_Type', 'fileCmd');
|
||||||
|
$cmd = common_config('attachments', 'filecommand');
|
||||||
|
|
||||||
|
$filetype = null;
|
||||||
|
|
||||||
|
if (is_string($f)) {
|
||||||
|
|
||||||
|
// assuming a filename
|
||||||
|
|
||||||
|
$filetype = MIME_Type::autoDetect($f);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// assuming a filehandle
|
||||||
|
|
||||||
|
$stream = stream_get_meta_data($f);
|
||||||
|
$filetype = MIME_Type::autoDetect($stream['uri']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($filetype, common_config('attachments', 'supported'))) {
|
||||||
|
return $filetype;
|
||||||
|
}
|
||||||
|
$media = MIME_Type::getMedia($filetype);
|
||||||
|
if ('application' !== $media) {
|
||||||
|
$hint = sprintf(_(' Try using another %s format.'), $media);
|
||||||
|
} else {
|
||||||
|
$hint = '';
|
||||||
|
}
|
||||||
|
throw new ClientException(sprintf(
|
||||||
|
_('%s is not a supported filetype on this server.'), $filetype) . $hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function respectsQuota($user, $filesize)
|
||||||
|
{
|
||||||
|
$file = new File;
|
||||||
|
$result = $file->isRespectsQuota($user, $filesize);
|
||||||
|
if ($result === true) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw new ClientException($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -80,10 +80,21 @@ class MessageForm extends Form
|
||||||
/**
|
/**
|
||||||
* ID of the form
|
* ID of the form
|
||||||
*
|
*
|
||||||
* @return int ID of the form
|
* @return string ID of the form
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function id()
|
function id()
|
||||||
|
{
|
||||||
|
return 'form_notice-direct';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class of the form
|
||||||
|
*
|
||||||
|
* @return string class of the form
|
||||||
|
*/
|
||||||
|
|
||||||
|
function formClass()
|
||||||
{
|
{
|
||||||
return 'form_notice';
|
return 'form_notice';
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ class NoticeForm extends Form
|
||||||
/**
|
/**
|
||||||
* ID of the form
|
* ID of the form
|
||||||
*
|
*
|
||||||
* @return int ID of the form
|
* @return string ID of the form
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function id()
|
function id()
|
||||||
|
@ -113,6 +113,17 @@ class NoticeForm extends Form
|
||||||
return 'form_notice';
|
return 'form_notice';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class of the form
|
||||||
|
*
|
||||||
|
* @return string class of the form
|
||||||
|
*/
|
||||||
|
|
||||||
|
function formClass()
|
||||||
|
{
|
||||||
|
return 'form_notice';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action of the form
|
* Action of the form
|
||||||
*
|
*
|
||||||
|
|
|
@ -199,6 +199,7 @@ class NoticeListItem extends Widget
|
||||||
{
|
{
|
||||||
$this->out->elementStart('div', 'entry-content');
|
$this->out->elementStart('div', 'entry-content');
|
||||||
$this->showNoticeLink();
|
$this->showNoticeLink();
|
||||||
|
$this->showNoticeLocation();
|
||||||
$this->showNoticeSource();
|
$this->showNoticeSource();
|
||||||
$this->showContext();
|
$this->showContext();
|
||||||
$this->out->elementEnd('div');
|
$this->out->elementEnd('div');
|
||||||
|
@ -369,6 +370,44 @@ class NoticeListItem extends Widget
|
||||||
$this->out->elementEnd('a');
|
$this->out->elementEnd('a');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* show the notice location
|
||||||
|
*
|
||||||
|
* shows the notice location in the correct language.
|
||||||
|
*
|
||||||
|
* If an URL is available, makes a link. Otherwise, just a span.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
function showNoticeLocation()
|
||||||
|
{
|
||||||
|
$id = $this->notice->id;
|
||||||
|
|
||||||
|
$location = $this->notice->getLocation();
|
||||||
|
|
||||||
|
if (empty($location)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = $location->getName();
|
||||||
|
|
||||||
|
if (empty($name)) {
|
||||||
|
// XXX: Could be a translation issue. Fall back to... something?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = $location->getUrl();
|
||||||
|
|
||||||
|
if (empty($url)) {
|
||||||
|
$this->out->element('span', array('class' => 'location'), $name);
|
||||||
|
} else {
|
||||||
|
$this->out->element('a', array('class' => 'location',
|
||||||
|
'href' => $url),
|
||||||
|
$name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the source of the notice
|
* Show the source of the notice
|
||||||
*
|
*
|
||||||
|
|
|
@ -87,7 +87,7 @@ function omb_broadcast_notice($notice)
|
||||||
common_debug('Posting to ' . $rp->postnoticeurl, __FILE__);
|
common_debug('Posting to ' . $rp->postnoticeurl, __FILE__);
|
||||||
|
|
||||||
/* Post notice. */
|
/* Post notice. */
|
||||||
$service = new Laconica_OMB_Service_Consumer(
|
$service = new StatusNet_OMB_Service_Consumer(
|
||||||
array(OMB_ENDPOINT_POSTNOTICE => $rp->postnoticeurl));
|
array(OMB_ENDPOINT_POSTNOTICE => $rp->postnoticeurl));
|
||||||
try {
|
try {
|
||||||
$service->setToken($rp->token, $rp->secret);
|
$service->setToken($rp->token, $rp->secret);
|
||||||
|
|
|
@ -62,9 +62,15 @@ class ProfileList extends Widget
|
||||||
|
|
||||||
function show()
|
function show()
|
||||||
{
|
{
|
||||||
$this->startList();
|
$cnt = 0;
|
||||||
$cnt = $this->showProfiles();
|
|
||||||
$this->endList();
|
if (Event::handle('StartProfileList', array($this))) {
|
||||||
|
$this->startList();
|
||||||
|
$cnt = $this->showProfiles();
|
||||||
|
$this->endList();
|
||||||
|
Event::handle('EndProfileList', array($this));
|
||||||
|
}
|
||||||
|
|
||||||
return $cnt;
|
return $cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,10 +123,19 @@ class ProfileListItem extends Widget
|
||||||
|
|
||||||
function show()
|
function show()
|
||||||
{
|
{
|
||||||
$this->startItem();
|
if (Event::handle('StartProfileListItem', array($this))) {
|
||||||
$this->showProfile();
|
$this->startItem();
|
||||||
$this->showActions();
|
if (Event::handle('StartProfileListItemProfile', array($this))) {
|
||||||
$this->endItem();
|
$this->showProfile();
|
||||||
|
Event::handle('EndProfileListItemProfile', array($this));
|
||||||
|
}
|
||||||
|
if (Event::handle('StartProfileListItemActions', array($this))) {
|
||||||
|
$this->showActions();
|
||||||
|
Event::handle('EndProfileListItemActions', array($this));
|
||||||
|
}
|
||||||
|
$this->endItem();
|
||||||
|
Event::handle('EndProfileListItem', array($this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function startItem()
|
function startItem()
|
||||||
|
@ -132,11 +147,29 @@ class ProfileListItem extends Widget
|
||||||
function showProfile()
|
function showProfile()
|
||||||
{
|
{
|
||||||
$this->startProfile();
|
$this->startProfile();
|
||||||
$this->showAvatar();
|
if (Event::handle('StartProfileListItemProfileElements', array($this))) {
|
||||||
$this->showFullName();
|
if (Event::handle('StartProfileListItemAvatar', array($this))) {
|
||||||
$this->showLocation();
|
$this->showAvatar();
|
||||||
$this->showHomepage();
|
Event::handle('EndProfileListItemAvatar', array($this));
|
||||||
$this->showBio();
|
}
|
||||||
|
if (Event::handle('StartProfileListItemFullName', array($this))) {
|
||||||
|
$this->showFullName();
|
||||||
|
Event::handle('EndProfileListItemFullName', array($this));
|
||||||
|
}
|
||||||
|
if (Event::handle('StartProfileListItemLocation', array($this))) {
|
||||||
|
$this->showLocation();
|
||||||
|
Event::handle('EndProfileListItemLocation', array($this));
|
||||||
|
}
|
||||||
|
if (Event::handle('StartProfileListItemHomepage', array($this))) {
|
||||||
|
$this->showHomepage();
|
||||||
|
Event::handle('EndProfileListItemHomepage', array($this));
|
||||||
|
}
|
||||||
|
if (Event::handle('StartProfileListItemBio', array($this))) {
|
||||||
|
$this->showBio();
|
||||||
|
Event::handle('EndProfileListItemBio', array($this));
|
||||||
|
}
|
||||||
|
Event::handle('EndProfileListItemProfileElements', array($this));
|
||||||
|
}
|
||||||
$this->endProfile();
|
$this->endProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +258,10 @@ class ProfileListItem extends Widget
|
||||||
function showActions()
|
function showActions()
|
||||||
{
|
{
|
||||||
$this->startActions();
|
$this->startActions();
|
||||||
$this->showSubscribeButton();
|
if (Event::handle('StartProfileListItemActionElements', array($this))) {
|
||||||
|
$this->showSubscribeButton();
|
||||||
|
Event::handle('EndProfileListItemActionElements', array($this));
|
||||||
|
}
|
||||||
$this->endActions();
|
$this->endActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,22 @@ define('CLAIM_TIMEOUT', 1200);
|
||||||
define('QUEUE_HANDLER_MISS_IDLE', 10);
|
define('QUEUE_HANDLER_MISS_IDLE', 10);
|
||||||
define('QUEUE_HANDLER_HIT_IDLE', 0);
|
define('QUEUE_HANDLER_HIT_IDLE', 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for queue handlers.
|
||||||
|
*
|
||||||
|
* As extensions of the Daemon class, each queue handler has the ability
|
||||||
|
* to launch itself in the background, at which point it'll pass control
|
||||||
|
* to the configured QueueManager class to poll for updates.
|
||||||
|
*
|
||||||
|
* Subclasses must override at least the following methods:
|
||||||
|
* - transport
|
||||||
|
* - start
|
||||||
|
* - finish
|
||||||
|
* - handle_notice
|
||||||
|
*
|
||||||
|
* Some subclasses will also want to override the idle handler:
|
||||||
|
* - idle
|
||||||
|
*/
|
||||||
class QueueHandler extends Daemon
|
class QueueHandler extends Daemon
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -39,6 +55,14 @@ class QueueHandler extends Daemon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many seconds a polling-based queue manager should wait between
|
||||||
|
* checks for new items to handle.
|
||||||
|
*
|
||||||
|
* Defaults to 60 seconds; override to speed up or slow down.
|
||||||
|
*
|
||||||
|
* @return int timeout in seconds
|
||||||
|
*/
|
||||||
function timeout()
|
function timeout()
|
||||||
{
|
{
|
||||||
return 60;
|
return 60;
|
||||||
|
@ -54,24 +78,69 @@ class QueueHandler extends Daemon
|
||||||
return strtolower($this->class_name().'.'.$this->get_id());
|
return strtolower($this->class_name().'.'.$this->get_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return transport keyword which identifies items this queue handler
|
||||||
|
* services; must be defined for all subclasses.
|
||||||
|
*
|
||||||
|
* Must be 8 characters or less to fit in the queue_item database.
|
||||||
|
* ex "email", "jabber", "sms", "irc", ...
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
function transport()
|
function transport()
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialization, run when the queue handler starts.
|
||||||
|
* If this function indicates failure, the handler run will be aborted.
|
||||||
|
*
|
||||||
|
* @fixme run() will abort if this doesn't return true,
|
||||||
|
* but some subclasses don't bother.
|
||||||
|
* @return boolean true on success, false on failure
|
||||||
|
*/
|
||||||
function start()
|
function start()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup, run when the queue handler ends.
|
||||||
|
* If this function indicates failure, a warning will be logged.
|
||||||
|
*
|
||||||
|
* @fixme run() will throw warnings if this doesn't return true,
|
||||||
|
* but many subclasses don't bother.
|
||||||
|
* @return boolean true on success, false on failure
|
||||||
|
*/
|
||||||
function finish()
|
function finish()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Here's the meat of your queue handler -- you're handed a Notice
|
||||||
|
* object, which you may do as you will with.
|
||||||
|
*
|
||||||
|
* If this function indicates failure, a warning will be logged
|
||||||
|
* and the item is placed back in the queue to be re-run.
|
||||||
|
*
|
||||||
|
* @param Notice $notice
|
||||||
|
* @return boolean true on success, false on failure
|
||||||
|
*/
|
||||||
function handle_notice($notice)
|
function handle_notice($notice)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup and start of run loop for this queue handler as a daemon.
|
||||||
|
* Most of the heavy lifting is passed on to the QueueManager's service()
|
||||||
|
* method, which passes control back to our handle_notice() method for
|
||||||
|
* each notice that comes in on the queue.
|
||||||
|
*
|
||||||
|
* Most of the time this won't need to be overridden in a subclass.
|
||||||
|
*
|
||||||
|
* @return boolean true on success, false on failure
|
||||||
|
*/
|
||||||
function run()
|
function run()
|
||||||
{
|
{
|
||||||
if (!$this->start()) {
|
if (!$this->start()) {
|
||||||
|
@ -100,6 +169,14 @@ class QueueHandler extends Daemon
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by QueueHandler after each handled item or empty polling cycle.
|
||||||
|
* This is a good time to e.g. service your XMPP connection.
|
||||||
|
*
|
||||||
|
* Doesn't need to be overridden if there's no maintenance to do.
|
||||||
|
*
|
||||||
|
* @param int $timeout seconds to sleep if there's nothing to do
|
||||||
|
*/
|
||||||
function idle($timeout=0)
|
function idle($timeout=0)
|
||||||
{
|
{
|
||||||
if ($timeout > 0) {
|
if ($timeout > 0) {
|
||||||
|
|
937
lib/router.php
937
lib/router.php
File diff suppressed because it is too large
Load Diff
|
@ -48,17 +48,6 @@ class UnQueueManager
|
||||||
jabber_public_notice($notice);
|
jabber_public_notice($notice);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'twitter':
|
|
||||||
if ($this->_isLocal($notice)) {
|
|
||||||
broadcast_twitter($notice);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'facebook':
|
|
||||||
if ($this->_isLocal($notice)) {
|
|
||||||
require_once INSTALLDIR . '/lib/facebookutil.php';
|
|
||||||
return facebookBroadcastNotice($notice);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'ping':
|
case 'ping':
|
||||||
if ($this->_isLocal($notice)) {
|
if ($this->_isLocal($notice)) {
|
||||||
require_once INSTALLDIR . '/lib/ping.php';
|
require_once INSTALLDIR . '/lib/ping.php';
|
||||||
|
@ -77,7 +66,7 @@ class UnQueueManager
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (Event::handle('UnqueueHandleNotice', array(&$notice, $queue))) {
|
if (Event::handle('UnqueueHandleNotice', array(&$notice, $queue))) {
|
||||||
throw ServerException("UnQueueManager: Unknown queue: $queue");
|
throw new ServerException("UnQueueManager: Unknown queue: $queue");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
30
lib/util.php
30
lib/util.php
|
@ -51,13 +51,23 @@ function common_init_locale($language=null)
|
||||||
function common_init_language()
|
function common_init_language()
|
||||||
{
|
{
|
||||||
mb_internal_encoding('UTF-8');
|
mb_internal_encoding('UTF-8');
|
||||||
|
|
||||||
|
// gettext seems very picky... We first need to setlocale()
|
||||||
|
// to a locale which _does_ exist on the system, and _then_
|
||||||
|
// we can set in another locale that may not be set up
|
||||||
|
// (say, ga_ES for Galego/Galician) it seems to take it.
|
||||||
|
common_init_locale("en_US");
|
||||||
|
|
||||||
$language = common_language();
|
$language = common_language();
|
||||||
// So we don't have to make people install the gettext locales
|
|
||||||
$locale_set = common_init_locale($language);
|
$locale_set = common_init_locale($language);
|
||||||
bindtextdomain("statusnet", common_config('site','locale_path'));
|
setlocale(LC_CTYPE, 'C');
|
||||||
|
|
||||||
|
// So we don't have to make people install the gettext locales
|
||||||
|
$path = common_config('site','locale_path');
|
||||||
|
bindtextdomain("statusnet", $path);
|
||||||
bind_textdomain_codeset("statusnet", "UTF-8");
|
bind_textdomain_codeset("statusnet", "UTF-8");
|
||||||
textdomain("statusnet");
|
textdomain("statusnet");
|
||||||
setlocale(LC_CTYPE, 'C');
|
|
||||||
if(!$locale_set) {
|
if(!$locale_set) {
|
||||||
common_log(LOG_INFO, 'Language requested:' . $language . ' - locale could not be set. Perhaps that system locale is not installed.', __FILE__);
|
common_log(LOG_INFO, 'Language requested:' . $language . ' - locale could not be set. Perhaps that system locale is not installed.', __FILE__);
|
||||||
}
|
}
|
||||||
|
@ -391,7 +401,7 @@ function common_render_content($text, $notice)
|
||||||
{
|
{
|
||||||
$r = common_render_text($text);
|
$r = common_render_text($text);
|
||||||
$id = $notice->profile_id;
|
$id = $notice->profile_id;
|
||||||
$r = preg_replace('/(^|[\s\.\,\:\;]+)@([A-Za-z0-9]{1,64})/e', "'\\1@'.common_at_link($id, '\\2')", $r);
|
$r = preg_replace('/(^|\s+)@(['.NICKNAME_FMT.']{1,64})/e', "'\\1@'.common_at_link($id, '\\2')", $r);
|
||||||
$r = preg_replace('/^T ([A-Z0-9]{1,64}) /e', "'T '.common_at_link($id, '\\1').' '", $r);
|
$r = preg_replace('/^T ([A-Z0-9]{1,64}) /e', "'T '.common_at_link($id, '\\1').' '", $r);
|
||||||
$r = preg_replace('/(^|[\s\.\,\:\;]+)@#([A-Za-z0-9]{1,64})/e', "'\\1@#'.common_at_hash_link($id, '\\2')", $r);
|
$r = preg_replace('/(^|[\s\.\,\:\;]+)@#([A-Za-z0-9]{1,64})/e', "'\\1@#'.common_at_hash_link($id, '\\2')", $r);
|
||||||
$r = preg_replace('/(^|[\s\.\,\:\;]+)!([A-Za-z0-9]{1,64})/e', "'\\1!'.common_group_link($id, '\\2')", $r);
|
$r = preg_replace('/(^|[\s\.\,\:\;]+)!([A-Za-z0-9]{1,64})/e', "'\\1!'.common_group_link($id, '\\2')", $r);
|
||||||
|
@ -771,12 +781,18 @@ function common_path($relative, $ssl=false)
|
||||||
if (is_string(common_config('site', 'sslserver')) &&
|
if (is_string(common_config('site', 'sslserver')) &&
|
||||||
mb_strlen(common_config('site', 'sslserver')) > 0) {
|
mb_strlen(common_config('site', 'sslserver')) > 0) {
|
||||||
$serverpart = common_config('site', 'sslserver');
|
$serverpart = common_config('site', 'sslserver');
|
||||||
} else {
|
} else if (common_config('site', 'server')) {
|
||||||
$serverpart = common_config('site', 'server');
|
$serverpart = common_config('site', 'server');
|
||||||
|
} else {
|
||||||
|
common_log(LOG_ERR, 'Site Sever not configured, unable to determine site name.');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$proto = 'http';
|
$proto = 'http';
|
||||||
$serverpart = common_config('site', 'server');
|
if (common_config('site', 'server')) {
|
||||||
|
$serverpart = common_config('site', 'server');
|
||||||
|
} else {
|
||||||
|
common_log(LOG_ERR, 'Site Sever not configured, unable to determine site name.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $proto.'://'.$serverpart.'/'.$pathpart.$relative;
|
return $proto.'://'.$serverpart.'/'.$pathpart.$relative;
|
||||||
|
@ -896,8 +912,6 @@ function common_broadcast_notice($notice, $remote=false)
|
||||||
function common_enqueue_notice($notice)
|
function common_enqueue_notice($notice)
|
||||||
{
|
{
|
||||||
static $localTransports = array('omb',
|
static $localTransports = array('omb',
|
||||||
'twitter',
|
|
||||||
'facebook',
|
|
||||||
'ping');
|
'ping');
|
||||||
|
|
||||||
static $allTransports = array('sms', 'plugin');
|
static $allTransports = array('sms', 'plugin');
|
||||||
|
|
|
@ -1,21 +1,12 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public XRDS for OpenID
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Low-level generator for HTML
|
||||||
*
|
*
|
||||||
* PHP version 5
|
* PHP version 5
|
||||||
*
|
*
|
||||||
* @category Action
|
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||||
* @package StatusNet
|
|
||||||
* @author Evan Prodromou <evan@status.net>
|
|
||||||
* @author Robin Millette <millette@status.net>
|
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
|
||||||
* @link http://status.net/
|
|
||||||
*
|
|
||||||
* StatusNet - the distributed open-source microblogging tool
|
|
||||||
* Copyright (C) 2008, 2009, StatusNet, 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
|
* 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
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
|
@ -27,60 +18,44 @@
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* 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/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category Output
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Craig Andrews <candrews@integralblue.com>
|
||||||
|
* @copyright 2008 StatusNet, Inc.
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once INSTALLDIR.'/plugins/OpenID/openid.php';
|
require_once INSTALLDIR.'/lib/xmloutputter.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public XRDS for OpenID
|
* Low-level generator for XRDS XML
|
||||||
*
|
*
|
||||||
* @category Action
|
* @category Output
|
||||||
* @package StatusNet
|
* @package StatusNet
|
||||||
* @author Evan Prodromou <evan@status.net>
|
* @author Craig Andrews <candrews@integralblue.com>
|
||||||
* @author Robin Millette <millette@status.net>
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
|
||||||
* @link http://status.net/
|
* @link http://status.net/
|
||||||
*
|
*
|
||||||
* @todo factor out similarities with XrdsAction
|
* @see Action
|
||||||
|
* @see XMLOutputter
|
||||||
*/
|
*/
|
||||||
class PublicxrdsAction extends Action
|
class XRDSOutputter extends XMLOutputter
|
||||||
{
|
{
|
||||||
/**
|
public function startXRDS()
|
||||||
* Is read only?
|
|
||||||
*
|
|
||||||
* @return boolean true
|
|
||||||
*/
|
|
||||||
function isReadOnly($args)
|
|
||||||
{
|
{
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class handler.
|
|
||||||
*
|
|
||||||
* @param array $args array of arguments
|
|
||||||
*
|
|
||||||
* @return nothing
|
|
||||||
*/
|
|
||||||
function handle($args)
|
|
||||||
{
|
|
||||||
parent::handle($args);
|
|
||||||
header('Content-Type: application/xrds+xml');
|
header('Content-Type: application/xrds+xml');
|
||||||
$this->startXML();
|
$this->startXML();
|
||||||
$this->elementStart('XRDS', array('xmlns' => 'xri://$xrds'));
|
$this->elementStart('XRDS', array('xmlns' => 'xri://$xrds'));
|
||||||
$this->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
|
}
|
||||||
'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
|
|
||||||
'version' => '2.0'));
|
public function endXRDS()
|
||||||
$this->element('Type', null, 'xri://$xrds*simple');
|
{
|
||||||
foreach (array('finishopenidlogin', 'finishaddopenid') as $finish) {
|
|
||||||
$this->showService(Auth_OpenID_RP_RETURN_TO_URL_TYPE,
|
|
||||||
common_local_url($finish));
|
|
||||||
}
|
|
||||||
$this->elementEnd('XRD');
|
|
||||||
$this->elementEnd('XRDS');
|
$this->elementEnd('XRDS');
|
||||||
$this->endXML();
|
$this->endXML();
|
||||||
}
|
}
|
||||||
|
@ -96,7 +71,7 @@ class PublicxrdsAction extends Action
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
function showService($type, $uri, $params=null, $sigs=null, $localId=null)
|
function showXrdsService($type, $uri, $params=null, $sigs=null, $localId=null)
|
||||||
{
|
{
|
||||||
$this->elementStart('Service');
|
$this->elementStart('Service');
|
||||||
if ($uri) {
|
if ($uri) {
|
||||||
|
@ -119,4 +94,3 @@ class PublicxrdsAction extends Action
|
||||||
$this->elementEnd('Service');
|
$this->elementEnd('Service');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
BIN
locale/bg/LC_MESSAGES/statusnet.mo
Normal file
BIN
locale/bg/LC_MESSAGES/statusnet.mo
Normal file
Binary file not shown.
Binary file not shown.
BIN
locale/cs/LC_MESSAGES/statusnet.mo
Normal file
BIN
locale/cs/LC_MESSAGES/statusnet.mo
Normal file
Binary file not shown.
Binary file not shown.
BIN
locale/de/LC_MESSAGES/statusnet.mo
Normal file
BIN
locale/de/LC_MESSAGES/statusnet.mo
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
locale/fr/LC_MESSAGES/statusnet.mo
Normal file
BIN
locale/fr/LC_MESSAGES/statusnet.mo
Normal file
Binary file not shown.
Binary file not shown.
BIN
locale/ga/LC_MESSAGES/statusnet.mo
Normal file
BIN
locale/ga/LC_MESSAGES/statusnet.mo
Normal file
Binary file not shown.
4713
locale/ga/LC_MESSAGES/statusnet.po
Normal file
4713
locale/ga/LC_MESSAGES/statusnet.po
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user