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…
x
Reference in New Issue
Block a user