forked from GNUsocial/gnu-social
Merge branch '0.9.x' of gitorious.org:statusnet/mainline into 0.9.x
This commit is contained in:
commit
cd29d3d646
28
EVENTS.txt
28
EVENTS.txt
@ -141,7 +141,7 @@ StartLogout: Before logging out
|
||||
EndLogout: After logging out
|
||||
- $action: the logout action
|
||||
|
||||
ArgsInitialized: After the argument array has been initialized
|
||||
ArgsInitialize: After the argument array has been initialized
|
||||
- $args: associative array of arguments, can be modified
|
||||
|
||||
StartAddressData: Allows the site owner to provide additional information about themselves for contact (e.g., tagline, email, location)
|
||||
@ -363,6 +363,14 @@ EndProfileRemoteSubscribe: After showing the link to remote subscription
|
||||
- $userprofile: UserProfile widget
|
||||
- &$profile: the profile being shown
|
||||
|
||||
StartGroupSubscribe: Before showing the link to remote subscription
|
||||
- $action: the current action
|
||||
- $group: the group being shown
|
||||
|
||||
EndGroupSubscribe: After showing the link to remote subscription
|
||||
- $action: the current action
|
||||
- $group: the group being shown
|
||||
|
||||
StartProfilePageProfileSection: Starting to show the section of the
|
||||
profile page with the actual profile data;
|
||||
hook to prevent showing the profile (e.g.)
|
||||
@ -770,12 +778,30 @@ StartShowSubscriptionsContent: before showing the subscriptions content
|
||||
EndShowSubscriptionsContent: after showing the subscriptions content
|
||||
- $action: the current action
|
||||
|
||||
StartShowUserGroupsContent: before showing the user groups content
|
||||
- $action: the current action
|
||||
|
||||
EndShowUserGroupsContent: after showing the user groups content
|
||||
- $action: the current action
|
||||
|
||||
StartShowAllContent: before showing the all (you and friends) content
|
||||
- $action: the current action
|
||||
|
||||
EndShowAllContent: after showing the all (you and friends) content
|
||||
- $action: the current action
|
||||
|
||||
StartShowSubscriptionsMiniList: at the start of subscriptions mini list
|
||||
- $action: the current action
|
||||
|
||||
EndShowSubscriptionsMiniList: at the end of subscriptions mini list
|
||||
- $action: the current action
|
||||
|
||||
StartShowGroupsMiniList: at the start of groups mini list
|
||||
- $action: the current action
|
||||
|
||||
EndShowGroupsMiniList: at the end of groups mini list
|
||||
- $action: the current action
|
||||
|
||||
StartDeleteUserForm: starting the data in the form for deleting a user
|
||||
- $action: action being shown
|
||||
- $user: user being deleted
|
||||
|
470
README
470
README
@ -2,33 +2,33 @@
|
||||
README
|
||||
------
|
||||
|
||||
StatusNet 0.9.0 ("Stand") Beta 5
|
||||
1 Feb 2010
|
||||
StatusNet 0.9.3 ("Half a World Away")
|
||||
29 June 2010
|
||||
|
||||
This is the README file for StatusNet (formerly Laconica), the Open
|
||||
Source microblogging platform. It includes installation instructions,
|
||||
descriptions of options you can set, warnings, tips, and general info
|
||||
for administrators. Information on using StatusNet can be found in the
|
||||
This is the README file for StatusNet, the Open Source microblogging
|
||||
platform. It includes installation instructions, descriptions of
|
||||
options you can set, warnings, tips, and general info for
|
||||
administrators. Information on using StatusNet can be found in the
|
||||
"doc" subdirectory or in the "help" section on-line.
|
||||
|
||||
About
|
||||
=====
|
||||
|
||||
StatusNet (formerly Laconica) is a Free and Open Source microblogging
|
||||
platform. It helps people in a community, company or group to exchange
|
||||
short (140 characters, by default) messages over the Web. Users can
|
||||
choose which people to "follow" and receive only their friends' or
|
||||
colleagues' status messages. It provides a similar service to sites
|
||||
like Twitter, Jaiku, Yammer, and Plurk.
|
||||
StatusNet is a Free and Open Source microblogging platform. It helps
|
||||
people in a community, company or group to exchange short (140
|
||||
characters, by default) messages over the Web. Users can choose which
|
||||
people to "follow" and receive only their friends' or colleagues'
|
||||
status messages. It provides a similar service to sites like Twitter,
|
||||
Google Buzz, or Yammer.
|
||||
|
||||
With a little work, status messages can be sent to mobile phones,
|
||||
instant messenger programs (GTalk/Jabber), and specially-designed
|
||||
desktop clients that support the Twitter API.
|
||||
|
||||
StatusNet supports an open standard called OpenMicroBlogging
|
||||
<http://openmicroblogging.org/> that lets users on different Web sites
|
||||
or in different companies subscribe to each others' notices. It
|
||||
enables a distributed social network spread all across the Web.
|
||||
StatusNet supports an open standard called OStatus
|
||||
<http://ostatus.org/> that lets users in different networks follow
|
||||
each other. It enables a distributed social network spread all across
|
||||
the Web.
|
||||
|
||||
StatusNet was originally developed for the Open Software Service,
|
||||
Identi.ca <http://identi.ca/>. It is shared with you in hope that you
|
||||
@ -77,203 +77,27 @@ for additional terms.
|
||||
New this version
|
||||
================
|
||||
|
||||
This is a major feature release since version 0.8.2, released Nov 1 2009.
|
||||
It is also a security release since 0.9.0beta4 January 27 2010. Beta
|
||||
users are strongly encouraged to upgrade to deal with a security alert.
|
||||
This is a minor bug and feature release since version 0.9.2 released on
|
||||
4 May 2010.
|
||||
|
||||
http://status.net/wiki/Security_alert_0000002
|
||||
For best compatibility with client software and site federation, and a lot of
|
||||
bug fixes, it is highly recommended that all public sites upgrade to the new
|
||||
version.
|
||||
|
||||
Notable changes this version:
|
||||
|
||||
- Records of deleted notices are stored without the notice content.
|
||||
- Much of the optional core featureset has been moved to plugins.
|
||||
- OpenID support moved from core to a plugin. Helps test the strength of
|
||||
our plugin architecture and makes it easy to disable this
|
||||
functionality for e.g. intranet sites.
|
||||
- Many additional hook events (see EVENTS.txt for details).
|
||||
- OMB 0.1 support re-implemented using libomb.
|
||||
- Re-structure database so notices, messages, bios and group
|
||||
descriptions can be over 140 characters. Limit defined by
|
||||
site administrator as configuration option; can be unlimited.
|
||||
- Configuration data now optionally stored in the database, which
|
||||
overrides any settings in config files.
|
||||
- Twitter integration re-implemented as a plugin.
|
||||
- Facebook integration re-implemented as a plugin.
|
||||
- Role-based authorization framework. Users can have named roles, and
|
||||
roles can have rights (e.g., to delete notices, change configuration
|
||||
data, or ban uncooperative users). Default roles 'admin' (for
|
||||
configuration) and 'moderator' (for community management) added.
|
||||
- Plugin for PubSubHubBub (PuSH) support.
|
||||
- Considerable code style cleanup to meet PEAR code standards.
|
||||
- Made a common library for HTTP-client access which uses available
|
||||
HTTP libraries where possible.
|
||||
- Added statuses/home_timeline method to API.
|
||||
- Hooks for plugins to handle notices offline, either by defining
|
||||
their own queue handler scripts or to use a default plugin queue
|
||||
handler script.
|
||||
- Plugins can now modify the database schema, adding their own tables
|
||||
or modifying existing ones.
|
||||
- Groups API.
|
||||
- Twitter API supports Web caching for some methods.
|
||||
- Twitter API refactored into one-action-per-method.
|
||||
- Realtime plugin supports a tear-off window.
|
||||
- FOAF for groups.
|
||||
- Moved all JavaScript tags to just before </body> by default,
|
||||
significantly speeding up apparent page load time.
|
||||
- Added a Realtime plugin for Orbited server.
|
||||
- Added a mobile plugin to give a more mobile-phone-friendly layout
|
||||
when a mobile browser is detected.
|
||||
- Use CSS sprites for most common icons.
|
||||
- Fixes for images and buttons on Web output.
|
||||
- New plugin requires that users validate their email before posting.
|
||||
- New plugin UserFlag lets users flag other profiles for review.
|
||||
- Considerably better i18n support. Use TranslateWiki to update
|
||||
translations.
|
||||
- Notices and profiles now store location information.
|
||||
- New plugin, Geonames, for turning location names and lat/long pairs
|
||||
into structured IDs and vice versa. Architecture reusable for other
|
||||
systems.
|
||||
- Better check of license compatibility between site licenses.
|
||||
- Some improvements in XMPP output.
|
||||
- Media upload in the API.
|
||||
- Replies appear in the user's inbox.
|
||||
- Improved the UI on the bookmarklet.
|
||||
- StatusNet identities can be used as OpenID identities.
|
||||
- Script to register a user.
|
||||
- Script to make someone a group admin.
|
||||
- Script to make someone a site admin or moderator.
|
||||
- 'login' command.
|
||||
- Pluggable authentication.
|
||||
- LDAP authentication plugin.
|
||||
- Script for console interaction with the site (!).
|
||||
- Users don't see group posts from people they've blocked.
|
||||
- Admin panel interface for changing site configuration.
|
||||
- Users can be sandboxed (limited contributions) or silenced
|
||||
(no contributions) by moderators.
|
||||
- Many changes to make language usage more consistent.
|
||||
- Sphinx search moved to a plugin.
|
||||
- GeoURL plugin.
|
||||
- Profile and group lists support hAtom.
|
||||
- Massive refactoring of util.js.
|
||||
- Mapstraction plugin to show maps on inbox and profile pages.
|
||||
- Play/pause buttons for realtime notices.
|
||||
- Support for geo microformat.
|
||||
- Partial support for feed subscriptions, RSSCloud, PubSubHubBub.
|
||||
- Support for geolocation in browser (Chrome, Firefox).
|
||||
- Quit trying to negotiate HTML format. Always use text/html.
|
||||
We lose, and so do Web standards. Boo.
|
||||
- Better logging of request info.
|
||||
- Better output for errors in Web interface.
|
||||
- No longer store .mo files; these need to be generated.
|
||||
- Minify plugin.
|
||||
- Events to allow pluginizing logger.
|
||||
- New framework for plugin localization.
|
||||
- Gravatar plugin.
|
||||
- Add support for "repeats" (similar to Twitter's "retweets").
|
||||
- Support for repeats in Twitter API.
|
||||
- Better notification of direct messages.
|
||||
- New plugin to add "powered by StatusNet" to logo.
|
||||
- Returnto works for private sites.
|
||||
- Localisation updates, including new Persian translation.
|
||||
- CAS authentication plugin
|
||||
- Get rid of DB_DataObject native cache (big memory leaker)
|
||||
- setconfig.php script to set configuration variables
|
||||
- Blacklist plugin, to blacklist URLs and nicknames
|
||||
- Users can set flag whether they want to share location
|
||||
both in notice form (for one notice) and profile settings
|
||||
(any notice)
|
||||
- notice inboxes moved from normalized notice_inbox table to
|
||||
denormalized inbox table
|
||||
- Automatic compression of Memcache
|
||||
- Memory caching pluginized
|
||||
- Memcache, XCache, APC and Diskcache plugins
|
||||
- A script to update user locations
|
||||
- cache empty query results
|
||||
- A sample plugin to show best plugin practices
|
||||
- CacheLog plugin to debug cache accesses
|
||||
- Require users to login to view attachments on private sites
|
||||
- Plugin to use Mollom spam detection service
|
||||
- Plugin for RSSCloud
|
||||
- Add an array of default plugins
|
||||
- A version action to give credit to contributors and plugin
|
||||
developers
|
||||
- Daemon to read IMAP mailbox instead of using a mailbox script
|
||||
- Pass session information between SSL and non-SSL server
|
||||
when SSL set to 'sometimes'
|
||||
- Major refactoring of queue handlers to manage very
|
||||
large hosting site (like status.net)
|
||||
- SubscriptionThrottle plugin to prevent subscription spamming
|
||||
- Don't enqueue into plugin or SMS queues when disabled (breaks unqueuehandler if SMS queue isn't attached)
|
||||
- Improve name validation checks on local File references
|
||||
- fix local file include vulnerability in doc.php
|
||||
- Reusing fixed selector name for 'processing' in util.js
|
||||
- Removed hAtom pattern from registration page.
|
||||
- restructuring of User::registerNew() lost password munging
|
||||
- Add a script to clear the cache for a given key
|
||||
- buggy fetch for site owner
|
||||
- Added missing concat of </li> in Realtime response
|
||||
- Updated XHR binded events to work better in jQuery 1.4.1. Using .live() for event delegation instead of jQuery.data() and checking to see if an element was previously binded.
|
||||
- Updated jQuery Form Plugin from v2.17 to v2.36
|
||||
- Updated jQuery JavaScript Library from v1.3.2 to v1.4.1
|
||||
- move schema.type.php to typeschema.php like other files
|
||||
- Add Really Simple Discovery (RSD) support
|
||||
- Add a robots.txt URL to the site root
|
||||
- error clearing tags for profiles from memcached
|
||||
- on exceptions, stomp logs the error and reenqueues
|
||||
- add lat, lon, location and remove closing tag from geocode.php
|
||||
- Use passed-in lat long in geocode.php
|
||||
- better handling of null responses from geonames.org
|
||||
- Globalized form notice data geo values
|
||||
- Using jQuery chaining in FormNoticeXHR
|
||||
- Using form object instead of form_id and find(). Slightly faster and easier to read.
|
||||
- removed describeTable from base class, and fixed it up in pgsql
|
||||
- getTableDef() mostly working in postgres
|
||||
- move the schema DDL sql off into seperate files for each db we support
|
||||
- plugin to limit number of registered users
|
||||
- add hooks for user registration
|
||||
- live fast, die young in bash scripts
|
||||
- for single-user mode, retrieve either site owner or defined nickname
|
||||
- method to get the site owner
|
||||
- define a constant for the 'owner' role of a site
|
||||
- add simple cache getter/setter static functions to Memcached_DataObject
|
||||
- Adds notice author's name to @title in Realtime response
|
||||
- Hides .author from XHR response in showstream
|
||||
- Hides .author from XHR response in showstream
|
||||
- Fix more fatal errors in queue edge cases
|
||||
- Don't attempt to resend XMPP messages that can't be broadcast due to the profile being deleted.
|
||||
- Wrap each bit of distrib queue handler's saving operation in a try/catch; log exceptions but let everything else continue.
|
||||
- Log exceptions from queuedaemon.php if they're not already caught
|
||||
- Move sessions settings to its own panel
|
||||
- Fixes for status_network db object .ini and tag setter script
|
||||
- Add a script to set tags for sites
|
||||
- Adjust API authentication to also check for OAuth protocol params in the HTTP Authorization header, as defined in OAuth HTTP Authorization Scheme.
|
||||
- Last-chance distribution if enqueueing fails
|
||||
- Manual failover for stomp queues.
|
||||
- lost config in index.php made all traffic go to master
|
||||
- "Revert "move RW setup above user get in index.php so remember_me works""
|
||||
- Revert "move RW setup above user get in index.php so remember_me works"
|
||||
- move RW setup above user get in index.php so remember_me works
|
||||
- hide most DB_DataObject errors
|
||||
- always set up database_rw, regardless, so cached sessions work
|
||||
- update mysqltimestamps on insert and update
|
||||
- additional debugging data for Sessions
|
||||
- 'Sign in with Twitter' button img
|
||||
- Update to biz theme
|
||||
- Remove redundant session token field from form (was already being added by base class).
|
||||
- 'Sign in with Twitter' button img
|
||||
- Can now set $config['queue']['stomp_persistent'] = false; to explicitly disable persistence when we queue items
|
||||
- Showing processing indicator for form_repeat on submit instead of form
|
||||
- Removed avatar from repeat of username (matches noticelist)
|
||||
- Removed unused variable assignment for avatar URL and added missing fn
|
||||
- Don't preemptively close existing DB connections for web views (needed to keep # of conns from going insane on multi-site queue daemons, so just doing for CLI) May, or may not, help with mystery session problems
|
||||
- dropping the setcookie() call from common_ensure_session() since we're pretty sure it's unnecessary
|
||||
- append '/' on cookie path for now (may still need some refactoring)
|
||||
- set session cookie correctly
|
||||
- Fix for Mapstraction plugin's zoomed map links
|
||||
- debug log line for control channel sub
|
||||
- Move faceboookapp.js to the Facebook plugin
|
||||
- fix for fix for bad realtime JS load
|
||||
- default 24-hour expiry on Memcached objects where not specified.
|
||||
- Enhanced API output to aid StatusNet-specific clients
|
||||
- Many updates to user interface translation from TranslateWiki
|
||||
- OStatus now works subscribing to SSL-protected sites by default
|
||||
- OpenID now works on PHP 5.3, supports closer site integration.
|
||||
- Numerous API and FOAF output fixes.
|
||||
- Fixes to Facebook integration for FB API behavior changes
|
||||
- PostgreSQL support updates
|
||||
- Initial version of a custom theme uploader (disabled by default)
|
||||
- LDAP auth plugins cleanup
|
||||
- Many other bugfixes
|
||||
|
||||
A full changelog is available at http://status.net/wiki/StatusNet_0.9.3.
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
@ -283,7 +107,9 @@ run correctly.
|
||||
|
||||
- PHP 5.2.3+. It may be possible to run this software on earlier
|
||||
versions of PHP, but many of the functions used are only available
|
||||
in PHP 5.2 or above.
|
||||
in PHP 5.2 or above. 5.2.6 or later is needed for XMPP background
|
||||
daemons on 64-bit platforms. PHP 5.3.x should work correctly in this
|
||||
release, but problems with some plugins are possible.
|
||||
- MySQL 5.x. The StatusNet database is stored, by default, in a MySQL
|
||||
server. It has been primarily tested on 5.x servers, although it may
|
||||
be possible to install on earlier (or later!) versions. The server
|
||||
@ -312,6 +138,8 @@ For some functionality, you will also need the following extensions:
|
||||
- Sphinx Search. A client for the sphinx server, an alternative
|
||||
to MySQL or Postgresql fulltext search. You will also need a
|
||||
Sphinx server to serve the search queries.
|
||||
- bcmath or gmp. For Salmon signatures (part of OStatus). Needed
|
||||
if you have OStatus configured.
|
||||
|
||||
You will almost definitely get 2-3 times better performance from your
|
||||
site if you install a PHP bytecode cache/accelerator. Some well-known
|
||||
@ -361,6 +189,9 @@ and the URLs are listed here for your convenience.
|
||||
- PEAR Validate is an oEmbed dependency.
|
||||
- PEAR Net_URL2 is an oEmbed dependency.
|
||||
- Console_GetOpt for parsing command-line options.
|
||||
- libomb. a library for implementing OpenMicroBlogging 0.1, the
|
||||
predecessor to OStatus.
|
||||
- HTTP_Request2, a library for making HTTP requests.
|
||||
|
||||
A design goal of StatusNet is that the basic Web functionality should
|
||||
work on even the most restrictive commercial hosting services.
|
||||
@ -378,9 +209,9 @@ especially if you've previously installed PHP/MySQL packages.
|
||||
1. Unpack the tarball you downloaded on your Web server. Usually a
|
||||
command like this will work:
|
||||
|
||||
tar zxf statusnet-0.8.2.tar.gz
|
||||
tar zxf statusnet-0.9.2.tar.gz
|
||||
|
||||
...which will make a statusnet-0.8.2 subdirectory in your current
|
||||
...which will make a statusnet-0.9.2 subdirectory in your current
|
||||
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
|
||||
files to the server.)
|
||||
@ -388,34 +219,34 @@ especially if you've previously installed PHP/MySQL packages.
|
||||
2. Move the tarball to a directory of your choosing in your Web root
|
||||
directory. Usually something like this will work:
|
||||
|
||||
mv statusnet-0.8.2 /var/www/mublog
|
||||
mv statusnet-0.9.2 /var/www/statusnet
|
||||
|
||||
This will make your StatusNet instance available in the mublog path of
|
||||
your server, like "http://example.net/mublog". "microblog" or
|
||||
This will make your StatusNet instance available in the statusnet path of
|
||||
your server, like "http://example.net/statusnet". "microblog" or
|
||||
"statusnet" might also be good path names. If you know how to
|
||||
configure virtual hosts on your web server, you can try setting up
|
||||
"http://micro.example.net/" or the like.
|
||||
|
||||
3. Make your target directory writeable by the Web server.
|
||||
|
||||
chmod a+w /var/www/mublog/
|
||||
chmod a+w /var/www/statusnet/
|
||||
|
||||
On some systems, this will probably work:
|
||||
|
||||
chgrp www-data /var/www/mublog/
|
||||
chmod g+w /var/www/mublog/
|
||||
chgrp www-data /var/www/statusnet/
|
||||
chmod g+w /var/www/statusnet/
|
||||
|
||||
If your Web server runs as another user besides "www-data", try
|
||||
that user's default group instead. As a last resort, you can create
|
||||
a new group like "mublog" and add the Web server's user to the group.
|
||||
a new group like "statusnet" and add the Web server's user to the group.
|
||||
|
||||
4. You should also take this moment to make your avatar, background, and
|
||||
file subdirectories writeable by the Web server. An insecure way to do
|
||||
this is:
|
||||
|
||||
chmod a+w /var/www/mublog/avatar
|
||||
chmod a+w /var/www/mublog/background
|
||||
chmod a+w /var/www/mublog/file
|
||||
chmod a+w /var/www/statusnet/avatar
|
||||
chmod a+w /var/www/statusnet/background
|
||||
chmod a+w /var/www/statusnet/file
|
||||
|
||||
You can also make the avatar, background, and file directories
|
||||
writeable by the Web server group, as noted above.
|
||||
@ -438,16 +269,16 @@ especially if you've previously installed PHP/MySQL packages.
|
||||
MySQL shell:
|
||||
|
||||
GRANT ALL on statusnet.*
|
||||
TO 'lacuser'@'localhost'
|
||||
IDENTIFIED BY 'lacpassword';
|
||||
TO 'statusnetuser'@'localhost'
|
||||
IDENTIFIED BY 'statusnetpassword';
|
||||
|
||||
You should change 'lacuser' and 'lacpassword' to your preferred new
|
||||
You should change 'statusnetuser' and 'statusnetpassword' to your preferred new
|
||||
username and password. You may want to test logging in to MySQL as
|
||||
this new user.
|
||||
|
||||
7. In a browser, navigate to the StatusNet install script; something like:
|
||||
|
||||
http://yourserver.example.com/mublog/install.php
|
||||
http://yourserver.example.com/statusnet/install.php
|
||||
|
||||
Enter the database connection information and your site name. The
|
||||
install program will configure your site and install the initial,
|
||||
@ -467,16 +298,16 @@ By default, StatusNet will use URLs that include the main PHP program's
|
||||
name in them. For example, a user's home profile might be
|
||||
found at:
|
||||
|
||||
http://example.org/mublog/index.php/mublog/fred
|
||||
http://example.org/statusnet/index.php/statusnet/fred
|
||||
|
||||
On certain systems that don't support this kind of syntax, they'll
|
||||
look like this:
|
||||
|
||||
http://example.org/mublog/index.php?p=mublog/fred
|
||||
http://example.org/statusnet/index.php?p=statusnet/fred
|
||||
|
||||
It's possible to configure the software so it looks like this instead:
|
||||
|
||||
http://example.org/mublog/fred
|
||||
http://example.org/statusnet/fred
|
||||
|
||||
These "fancy URLs" are more readable and memorable for users. To use
|
||||
fancy URLs, you must either have Apache 2.x with .htaccess enabled and
|
||||
@ -501,7 +332,7 @@ your server.
|
||||
You should now be able to navigate to a "fancy" URL on your server,
|
||||
like:
|
||||
|
||||
http://example.net/mublog/main/register
|
||||
http://example.net/statusnet/main/register
|
||||
|
||||
If you changed your HTTP server configuration, you may need to restart
|
||||
the server first.
|
||||
@ -553,7 +384,7 @@ For this to work, there *must* be a domain or sub-domain for which all
|
||||
1. Run the SQL script carrier.sql in your StatusNet database. This will
|
||||
usually work:
|
||||
|
||||
mysql -u "lacuser" --password="lacpassword" statusnet < db/carrier.sql
|
||||
mysql -u "statusnetuser" --password="statusnetpassword" statusnet < db/carrier.sql
|
||||
|
||||
This will populate your database with a list of wireless carriers
|
||||
that support email SMS gateways.
|
||||
@ -643,7 +474,7 @@ consider setting up queues and daemons.
|
||||
Queues and daemons
|
||||
------------------
|
||||
|
||||
Some activities that StatusNet needs to do, like broadcast OMB, SMS,
|
||||
Some activities that StatusNet needs to do, like broadcast OStatus, SMS,
|
||||
and XMPP messages, can be 'queued' and done by off-line bots instead.
|
||||
For this to work, you must be able to run long-running offline
|
||||
processes, either on your main Web server or on another server you
|
||||
@ -669,14 +500,12 @@ server is probably a good idea for high-volume sites.
|
||||
options, you'll need to create that user and/or group by hand.
|
||||
They're not created automatically.
|
||||
|
||||
4. On the queues server, run the command scripts/startdaemons.sh. It
|
||||
needs as a parameter the install path; if you run it from the
|
||||
StatusNet dir, "." should suffice.
|
||||
4. On the queues server, run the command scripts/startdaemons.sh.
|
||||
|
||||
This will run the queue handlers:
|
||||
|
||||
* queuedaemon.php - polls for queued items for inbox processing and
|
||||
pushing out to OMB, SMS, XMPP, etc.
|
||||
pushing out to OStatus, SMS, XMPP, etc.
|
||||
* xmppdaemon.php - listens for new XMPP messages from users and stores
|
||||
them as notices in the database; also pulls queued XMPP output from
|
||||
queuedaemon.php to push out to clients.
|
||||
@ -685,6 +514,9 @@ These two daemons will automatically restart in most cases of failure
|
||||
including memory leaks (if a memory_limit is set), but may still die
|
||||
or behave oddly if they lose connections to the XMPP or queue servers.
|
||||
|
||||
Additional daemons may be also started by this script for certain
|
||||
plugins, such as the Twitter bridge.
|
||||
|
||||
It may be a good idea to use a daemon-monitoring service, like 'monit',
|
||||
to check their status and keep them running.
|
||||
|
||||
@ -693,46 +525,11 @@ default. This can be useful for starting, stopping, and monitoring the
|
||||
daemons.
|
||||
|
||||
Since version 0.8.0, it's now possible to use a STOMP server instead of
|
||||
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
|
||||
writing, the software has been tested with ActiveMQ.
|
||||
our kind of hacky home-grown DB-based queue solution. This is strongly
|
||||
recommended for best response time, especially when using XMPP.
|
||||
|
||||
Sitemaps
|
||||
--------
|
||||
|
||||
Sitemap files <http://sitemaps.org/> are a very nice way of telling
|
||||
search engines and other interested bots what's available on your site
|
||||
and what's changed recently. You can generate sitemap files for your
|
||||
StatusNet instance.
|
||||
|
||||
1. Choose your sitemap URL layout. StatusNet creates a number of
|
||||
sitemap XML files for different parts of your site. You may want to
|
||||
put these in a sub-directory of your StatusNet directory to avoid
|
||||
clutter. The sitemap index file tells the search engines and other
|
||||
bots where to find all the sitemap files; it *must* be in the main
|
||||
installation directory or higher. Both types of file must be
|
||||
available through HTTP.
|
||||
|
||||
2. To generate your sitemaps, run the following command on your server:
|
||||
|
||||
php scripts/sitemap.php -f index-file-path -d sitemap-directory -u URL-prefix-for-sitemaps
|
||||
|
||||
Here, index-file-path is the full path to the sitemap index file,
|
||||
like './sitemapindex.xml'. sitemap-directory is the directory where
|
||||
you want the sitemaps stored, like './sitemaps/' (make sure the dir
|
||||
exists). URL-prefix-for-sitemaps is the full URL for the sitemap dir,
|
||||
typically something like <http://example.net/mublog/sitemaps/>.
|
||||
|
||||
You can use several methods for submitting your sitemap index to
|
||||
search engines to get your site indexed. One is to add a line like the
|
||||
following to your robots.txt file:
|
||||
|
||||
Sitemap: /mublog/sitemapindex.xml
|
||||
|
||||
This is a good idea for letting *all* Web spiders know about your
|
||||
sitemap. You can also submit sitemap files to major search engines
|
||||
using their respective "Webmaster centres"; see sitemaps.org for links
|
||||
to these resources.
|
||||
See the "queues" config section below for how to configure to use STOMP.
|
||||
As of this writing, the software has been tested with ActiveMQ 5.3.
|
||||
|
||||
Themes
|
||||
------
|
||||
@ -803,30 +600,26 @@ not visible to non-logged-in users. This might be useful for
|
||||
workgroups who want to share a microblogging site for project
|
||||
management, but host it on a public server.
|
||||
|
||||
Note that this is an experimental feature; total privacy is not
|
||||
guaranteed or ensured. Also, privacy is all-or-nothing for a site; you
|
||||
can't have some accounts or notices private, and others public.
|
||||
Finally, the interaction of private sites with OpenMicroBlogging is
|
||||
undefined. Remote users won't be able to subscribe to users on a
|
||||
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
|
||||
"proper behaviour" hasn't been defined here, so handle with care.
|
||||
Total privacy is not guaranteed or ensured. Also, privacy is
|
||||
all-or-nothing for a site; you can't have some accounts or notices
|
||||
private, and others public. The interaction of private sites
|
||||
with OStatus is undefined.
|
||||
|
||||
Access to file attachments can also be restricted to logged-in users only.
|
||||
1. Add a directory outside the web root where your file uploads will be
|
||||
stored. Usually a command like this will work:
|
||||
|
||||
mkdir /var/www/mublog-files
|
||||
mkdir /var/www/statusnet-files
|
||||
|
||||
2. Make the file uploads directory writeable by the web server. An
|
||||
insecure way to do this is:
|
||||
|
||||
chmod a+x /var/www/mublog-files
|
||||
chmod a+x /var/www/statusnet-files
|
||||
|
||||
3. Tell StatusNet to use this directory for file uploads. Add a line
|
||||
like this to your config.php:
|
||||
|
||||
$config['attachments']['dir'] = '/var/www/mublog-files';
|
||||
$config['attachments']['dir'] = '/var/www/statusnet-files';
|
||||
|
||||
Upgrading
|
||||
=========
|
||||
@ -841,7 +634,7 @@ with this situation.
|
||||
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
|
||||
want to upgrade and keep your existing data. There is no automated
|
||||
upgrade procedure in StatusNet 0.8.2. Try these step-by-step
|
||||
upgrade procedure in StatusNet 0.9.2. Try these step-by-step
|
||||
instructions; read to the end first before trying them.
|
||||
|
||||
0. Download StatusNet and set up all the prerequisites as if you were
|
||||
@ -861,24 +654,24 @@ instructions; read to the end first before trying them.
|
||||
maildaemon.php file, and running something like "newaliases".
|
||||
5. Once all writing processes to your site are turned off, make a
|
||||
final backup of the Web directory and database.
|
||||
6. Move your StatusNet directory to a backup spot, like "mublog.bak".
|
||||
7. Unpack your StatusNet 0.8.2 tarball and move it to "mublog" or
|
||||
6. Move your StatusNet directory to a backup spot, like "statusnet.bak".
|
||||
7. Unpack your StatusNet 0.9.2 tarball and move it to "statusnet" or
|
||||
wherever your code used to be.
|
||||
8. Copy the config.php file and avatar directory from your old
|
||||
directory to your new directory.
|
||||
9. Copy htaccess.sample to .htaccess in the new directory. Change the
|
||||
RewriteBase to use the correct path.
|
||||
10. Rebuild the database. (You can safely skip this step and go to #12
|
||||
if you're upgrading from another 0.8.x version).
|
||||
if you're upgrading from another 0.9.x version).
|
||||
|
||||
NOTE: this step is destructive and cannot be
|
||||
reversed. YOU CAN EASILY DESTROY YOUR SITE WITH THIS STEP. Don't
|
||||
do it without a known-good backup!
|
||||
|
||||
If your database is at version 0.7.4, you can run a special upgrade
|
||||
script:
|
||||
If your database is at version 0.8.0 or above, you can run a
|
||||
special upgrade script:
|
||||
|
||||
mysql -u<rootuser> -p<rootpassword> <database> db/074to080.sql
|
||||
mysql -u<rootuser> -p<rootpassword> <database> db/08to09.sql
|
||||
|
||||
Otherwise, go to your StatusNet directory and AFTER YOU MAKE A
|
||||
BACKUP run the rebuilddb.sh script like this:
|
||||
@ -943,10 +736,17 @@ Configuration options
|
||||
|
||||
The main configuration file for StatusNet (excepting configurations for
|
||||
dependency software) is config.php in your StatusNet directory. If you
|
||||
edit any other file in the directory, like lib/common.php (where most
|
||||
edit any other file in the directory, like lib/default.php (where most
|
||||
of the defaults are defined), you will lose your configuration options
|
||||
in any upgrade, and you will wish that you had been more careful.
|
||||
|
||||
Starting with version 0.9.0, a Web based configuration panel has been
|
||||
added to StatusNet. The preferred method for changing config options is
|
||||
to use this panel.
|
||||
|
||||
A command-line script, setconfig.php, can be used to set individual
|
||||
configuration options. It's in the scripts/ directory.
|
||||
|
||||
Starting with version 0.7.1, you can put config files in the
|
||||
/etc/statusnet/ directory on your server, if it exists. Config files
|
||||
will be included in this order:
|
||||
@ -972,7 +772,7 @@ This section is a catch-all for site-wide variables.
|
||||
|
||||
name: the name of your site, like 'YourCompany Microblog'.
|
||||
server: the server part of your site's URLs, like 'example.net'.
|
||||
path: The path part of your site's URLs, like 'mublog' or ''
|
||||
path: The path part of your site's URLs, like 'statusnet' or ''
|
||||
(installed in root).
|
||||
fancy: whether or not your site uses fancy URLs (see Fancy URLs
|
||||
section above). Default is false.
|
||||
@ -1124,11 +924,71 @@ stomp_server: "broker URI" for stomp server. Something like
|
||||
possible; see your stomp server's documentation for
|
||||
details.
|
||||
queue_basename: a root name to use for queues (stomp only). Typically
|
||||
something like '/queue/sitename/' makes sense.
|
||||
something like '/queue/sitename/' makes sense. If running
|
||||
multiple instances on the same server, make sure that
|
||||
either this setting or $config['site']['nickname'] are
|
||||
unique for each site to keep them separate.
|
||||
|
||||
stomp_username: username for connecting to the stomp server; defaults
|
||||
to null.
|
||||
stomp_password: password for connecting to the stomp server; defaults
|
||||
to null.
|
||||
|
||||
stomp_persistent: keep items across queue server restart, if enabled.
|
||||
Under ActiveMQ, the server configuration determines if and how
|
||||
persistent storage is actually saved.
|
||||
|
||||
If using a message queue server other than ActiveMQ, you may
|
||||
need to disable this if it does not support persistence.
|
||||
|
||||
stomp_transactions: use transactions to aid in error detection.
|
||||
A broken transaction will be seen quickly, allowing a message
|
||||
to be redelivered immediately if a daemon crashes.
|
||||
|
||||
If using a message queue server other than ActiveMQ, you may
|
||||
need to disable this if it does not support transactions.
|
||||
|
||||
stomp_acks: send acknowledgements to aid in flow control.
|
||||
An acknowledgement of successful processing tells the server
|
||||
we're ready for more and can help keep things moving smoothly.
|
||||
|
||||
This should *not* be turned off when running with ActiveMQ, but
|
||||
if using another message queue server that does not support
|
||||
acknowledgements you might need to disable this.
|
||||
|
||||
softlimit: an absolute or relative "soft memory limit"; daemons will
|
||||
restart themselves gracefully when they find they've hit
|
||||
this amount of memory usage. Defaults to 90% of PHP's global
|
||||
memory_limit setting.
|
||||
|
||||
inboxes: delivery of messages to receiver's inboxes can be delayed to
|
||||
queue time for best interactive performance on the sender.
|
||||
This may however be annoyingly slow when using the DB queues,
|
||||
so you can set this to false if it's causing trouble.
|
||||
|
||||
breakout: for stomp, individual queues are by default grouped up for
|
||||
best scalability. If some need to be run by separate daemons,
|
||||
etc they can be manually adjusted here.
|
||||
|
||||
Default will share all queues for all sites within each group.
|
||||
Specify as <group>/<queue> or <group>/<queue>/<site>,
|
||||
using nickname identifier as site.
|
||||
|
||||
'main/distrib' separate "distrib" queue covering all sites
|
||||
'xmpp/xmppout/mysite' separate "xmppout" queue covering just 'mysite'
|
||||
|
||||
max_retries: for stomp, drop messages after N failed attempts to process.
|
||||
Defaults to 10.
|
||||
|
||||
dead_letter_dir: for stomp, optional directory to dump data on failed
|
||||
queue processing events after discarding them.
|
||||
|
||||
stomp_no_transactions: for stomp, the server does not support transactions,
|
||||
so do not try to user them. This is needed for http://www.morbidq.com/.
|
||||
|
||||
stomp_no_acks: for stomp, the server does not support acknowledgements.
|
||||
so do not try to user them. This is needed for http://www.morbidq.com/.
|
||||
|
||||
license
|
||||
-------
|
||||
|
||||
@ -1371,10 +1231,6 @@ profile
|
||||
|
||||
Profile management.
|
||||
|
||||
banned: an array of usernames and/or profile IDs of 'banned' profiles.
|
||||
The site will reject any notices by these users -- they will
|
||||
not be accepted at all. (Compare with blacklisted users above,
|
||||
whose posts just won't show up in the public stream.)
|
||||
biolimit: max character length of bio; 0 means no limit; null means to use
|
||||
the site text limit default.
|
||||
|
||||
@ -1662,7 +1518,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
|
||||
conflicts in your code.
|
||||
|
||||
If you upgraded to StatusNet 0.8.2 without reading the "Notice
|
||||
If you upgraded to StatusNet 0.9.2 without reading the "Notice
|
||||
inboxes" section above, and all your users' 'Personal' tabs are empty,
|
||||
read the "Notice inboxes" section above.
|
||||
|
||||
@ -1717,16 +1573,16 @@ There are several ways to get more information about StatusNet.
|
||||
* The #statusnet IRC channel on freenode.net <http://www.freenode.net/>.
|
||||
* The StatusNet wiki, http://status.net/wiki/
|
||||
* The StatusNet blog, http://status.net/blog/
|
||||
* The StatusNet status update, <http://status.status.net/status> (!)
|
||||
* The StatusNet status update, <http://status.status.net/> (!)
|
||||
|
||||
Feedback
|
||||
========
|
||||
|
||||
* Microblogging messages to http://identi.ca/evan are very welcome.
|
||||
* StatusNet's Trac server has a bug tracker for any defects you may find,
|
||||
or ideas for making things better. http://status.net/trac/
|
||||
* e-mail to evan@status.net will usually be read and responded to very
|
||||
quickly, unless the question is really hard.
|
||||
* Microblogging messages to http://support.status.net/ are very welcome.
|
||||
* The microblogging group http://identi.ca/group/statusnet is a good
|
||||
place to discuss the software.
|
||||
* StatusNet has a bug tracker for any defects you may find, or ideas for
|
||||
making things better. http://status.net/bugs
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
@ -18,15 +18,19 @@
|
||||
*
|
||||
* @category Actions
|
||||
* @package Actions
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
||||
* @author Robin Millette <millette@controlyourself.ca>
|
||||
* @author Adrian Lang <mail@adrianlang.de>
|
||||
* @author Meitar Moscovitz <meitarm@gmail.com>
|
||||
* @author Sarven Capadisli <csarven@status.net>
|
||||
* @author Brenda Wallace <shiny@cpan.org>
|
||||
* @author Brion Vibber <brion@pobox.com>
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Zach Copley <zach@controlyourself.ca>
|
||||
* @author Meitar Moscovitz <meitarm@gmail.com>
|
||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
||||
* @author Robin Millette <millette@status.net>
|
||||
* @author Sarven Capadisli <csarven@status.net>
|
||||
* @author Siebrand Mazeland <s.mazeland@xs4all.nl>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license GNU Affero General Public License http://www.gnu.org/licenses/
|
||||
* @link http://status.net
|
||||
*/
|
||||
@ -61,7 +65,7 @@ class AllAction extends ProfileAction
|
||||
|
||||
if ($this->page > 1 && $this->notice->N == 0) {
|
||||
// TRANS: Server error when page not found (404)
|
||||
$this->serverError(_('No such page'), $code = 404);
|
||||
$this->serverError(_('No such page.'), $code = 404);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -83,6 +83,7 @@ class AllrssAction extends Rss10Action
|
||||
function getNotices($limit=0)
|
||||
{
|
||||
$cur = common_current_user();
|
||||
$user = $this->user;
|
||||
|
||||
if (!empty($cur) && $cur->id == $user->id) {
|
||||
$notice = $this->user->noticeInbox(0, $limit);
|
||||
@ -90,7 +91,6 @@ class AllrssAction extends Rss10Action
|
||||
$notice = $this->user->noticesWithFriends(0, $limit);
|
||||
}
|
||||
|
||||
$user = $this->user;
|
||||
$notice = $user->noticesWithFriends(0, $limit);
|
||||
$notices = array();
|
||||
|
||||
@ -112,10 +112,12 @@ class AllrssAction extends Rss10Action
|
||||
$c = array('url' => common_local_url('allrss',
|
||||
array('nickname' =>
|
||||
$user->nickname)),
|
||||
// TRANS: Message is used as link title. %s is a user nickname.
|
||||
'title' => sprintf(_('%s and friends'), $user->nickname),
|
||||
'link' => common_local_url('all',
|
||||
array('nickname' =>
|
||||
$user->nickname)),
|
||||
// TRANS: Message is used as link description. %1$s is a username, %2$s is a site name.
|
||||
'description' => sprintf(_('Updates from %1$s and friends on %2$s!'),
|
||||
$user->nickname, common_config('site', 'name')));
|
||||
return $c;
|
||||
|
@ -21,8 +21,10 @@
|
||||
*
|
||||
* @category API
|
||||
* @package StatusNet
|
||||
* @author Brion Vibber <brion@pobox.com>
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Robin Millette <robin@millette.info>
|
||||
* @author Siebrand Mazeland <s.mazeland@xs4all.nl>
|
||||
* @author Zach Copley <zach@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
|
||||
|
@ -21,6 +21,7 @@
|
||||
*
|
||||
* @category API
|
||||
* @package StatusNet
|
||||
* @author Siebrand Mazeland <s.mazeland@xs4all.nl>
|
||||
* @author Zach Copley <zach@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
|
||||
@ -103,7 +104,7 @@ class ApiAccountUpdateDeliveryDeviceAction extends ApiAuthAction
|
||||
$this->clientError(
|
||||
_(
|
||||
'You must specify a parameter named ' .
|
||||
'\'device\' with a value of one of: sms, im, none'
|
||||
'\'device\' with a value of one of: sms, im, none.'
|
||||
)
|
||||
);
|
||||
return;
|
||||
|
@ -75,7 +75,7 @@ class ApiAccountVerifyCredentialsAction extends ApiAuthAction
|
||||
|
||||
if ($this->format == 'xml') {
|
||||
$this->initDocument('xml');
|
||||
$this->showTwitterXmlUser($twitter_user);
|
||||
$this->showTwitterXmlUser($twitter_user, 'user', true);
|
||||
$this->endDocument('xml');
|
||||
} elseif ($this->format == 'json') {
|
||||
$this->initDocument('json');
|
||||
|
@ -23,7 +23,7 @@
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009-2010 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/
|
||||
*/
|
||||
@ -65,7 +65,7 @@ class ApiBlockCreateAction extends ApiAuthAction
|
||||
parent::prepare($args);
|
||||
|
||||
$this->user = $this->auth_user;
|
||||
$this->other = $this->getTargetUser($this->arg('id'));
|
||||
$this->other = $this->getTargetProfile($this->arg('id'));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009-2010 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/
|
||||
*/
|
||||
@ -64,7 +64,7 @@ class ApiBlockDestroyAction extends ApiAuthAction
|
||||
parent::prepare($args);
|
||||
|
||||
$this->user = $this->auth_user;
|
||||
$this->other = $this->getTargetUser($this->arg('id'));
|
||||
$this->other = $this->getTargetProfile($this->arg('id'));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -232,7 +232,8 @@ class ApiDirectMessageAction extends ApiAuthAction
|
||||
function showXmlDirectMessages()
|
||||
{
|
||||
$this->initDocument('xml');
|
||||
$this->elementStart('direct-messages', array('type' => 'array'));
|
||||
$this->elementStart('direct-messages', array('type' => 'array',
|
||||
'xmlns:statusnet' => 'http://status.net/schema/api/1/'));
|
||||
|
||||
foreach ($this->messages as $m) {
|
||||
$dm_array = $this->directMessageArray($m);
|
||||
|
@ -52,7 +52,6 @@ require_once INSTALLDIR . '/lib/apiauth.php';
|
||||
|
||||
class ApiDirectMessageNewAction extends ApiAuthAction
|
||||
{
|
||||
var $source = null;
|
||||
var $other = null;
|
||||
var $content = null;
|
||||
|
||||
@ -76,13 +75,6 @@ class ApiDirectMessageNewAction extends ApiAuthAction
|
||||
return;
|
||||
}
|
||||
|
||||
$this->source = $this->trimmed('source'); // Not supported by Twitter.
|
||||
|
||||
$reserved_sources = array('web', 'omb', 'mail', 'xmpp', 'api');
|
||||
if (empty($this->source) || in_array($this->source, $reserved_sources)) {
|
||||
$source = 'api';
|
||||
}
|
||||
|
||||
$this->content = $this->trimmed('text');
|
||||
|
||||
$this->user = $this->auth_user;
|
||||
|
@ -25,6 +25,7 @@
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -123,7 +124,7 @@ class ApiFavoriteCreateAction extends ApiAuthAction
|
||||
return;
|
||||
}
|
||||
|
||||
$fave = Fave::addNew($this->user, $this->notice);
|
||||
$fave = Fave::addNew($this->user->getProfile(), $this->notice);
|
||||
|
||||
if (empty($fave)) {
|
||||
$this->clientError(
|
||||
|
@ -25,6 +25,7 @@
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
@ -24,7 +24,7 @@
|
||||
* @author Dan Moore <dan@moore.cx>
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009-2010 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/
|
||||
*/
|
||||
@ -67,7 +67,7 @@ class ApiFriendshipsCreateAction extends ApiAuthAction
|
||||
parent::prepare($args);
|
||||
|
||||
$this->user = $this->auth_user;
|
||||
$this->other = $this->getTargetUser($id);
|
||||
$this->other = $this->getTargetProfile($this->arg('id'));
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -106,7 +106,7 @@ class ApiFriendshipsCreateAction extends ApiAuthAction
|
||||
|
||||
if (empty($this->other)) {
|
||||
$this->clientError(
|
||||
_('Could not follow user: User not found.'),
|
||||
_('Could not follow user: profile not found.'),
|
||||
403,
|
||||
$this->format
|
||||
);
|
||||
|
@ -24,7 +24,7 @@
|
||||
* @author Dan Moore <dan@moore.cx>
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009-2010 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/
|
||||
*/
|
||||
@ -67,7 +67,7 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction
|
||||
parent::prepare($args);
|
||||
|
||||
$this->user = $this->auth_user;
|
||||
$this->other = $this->getTargetUser($id);
|
||||
$this->other = $this->getTargetProfile($this->arg('id'));
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -125,8 +125,7 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction
|
||||
}
|
||||
|
||||
// throws an exception on error
|
||||
Subscription::cancel($this->user->getProfile(),
|
||||
$this->other->getProfile());
|
||||
Subscription::cancel($this->user->getProfile(), $this->other);
|
||||
|
||||
$this->initDocument($this->format);
|
||||
$this->showProfile($this->other, $this->format);
|
||||
|
@ -24,7 +24,7 @@
|
||||
* @author Dan Moore <dan@moore.cx>
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009-2010 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/
|
||||
*/
|
||||
@ -50,8 +50,8 @@ require_once INSTALLDIR . '/lib/apiprivateauth.php';
|
||||
|
||||
class ApiFriendshipsExistsAction extends ApiPrivateAuthAction
|
||||
{
|
||||
var $user_a = null;
|
||||
var $user_b = null;
|
||||
var $profile_a = null;
|
||||
var $profile_b = null;
|
||||
|
||||
/**
|
||||
* Take arguments for running
|
||||
@ -66,11 +66,8 @@ class ApiFriendshipsExistsAction extends ApiPrivateAuthAction
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$user_a_id = $this->trimmed('user_a');
|
||||
$user_b_id = $this->trimmed('user_b');
|
||||
|
||||
$this->user_a = $this->getTargetUser($user_a_id);
|
||||
$this->user_b = $this->getTargetUser($user_b_id);
|
||||
$this->profile_a = $this->getTargetProfile($this->trimmed('user_a'));
|
||||
$this->profile_b = $this->getTargetProfile($this->trimmed('user_b'));
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -89,16 +86,16 @@ class ApiFriendshipsExistsAction extends ApiPrivateAuthAction
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if (empty($this->user_a) || empty($this->user_b)) {
|
||||
if (empty($this->profile_a) || empty($this->profile_b)) {
|
||||
$this->clientError(
|
||||
_('Two user ids or screen_names must be supplied.'),
|
||||
_('Two valid IDs or screen_names must be supplied.'),
|
||||
400,
|
||||
$this->format
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$result = $this->user_a->isSubscribed($this->user_b);
|
||||
$result = Subscription::exists($this->profile_a, $this->profile_b);
|
||||
|
||||
switch ($this->format) {
|
||||
case 'xml':
|
||||
|
@ -26,6 +26,7 @@
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -263,7 +264,7 @@ class ApiGroupCreateAction extends ApiAuthAction
|
||||
|
||||
if (!$valid) {
|
||||
$this->clientError(
|
||||
sprintf(_('Invalid alias: "%s"'), $alias),
|
||||
sprintf(_('Invalid alias: "%s".'), $alias),
|
||||
403,
|
||||
$this->format
|
||||
);
|
||||
|
@ -26,6 +26,7 @@
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -92,7 +93,7 @@ class ApiGroupIsMemberAction extends ApiBareAuthAction
|
||||
}
|
||||
|
||||
if (empty($this->group)) {
|
||||
$this->clientError(_('Group not found!'), 404, $this->format);
|
||||
$this->clientError(_('Group not found.'), 404, $this->format);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -101,7 +102,7 @@ class ApiGroupJoinAction extends ApiAuthAction
|
||||
}
|
||||
|
||||
if (empty($this->group)) {
|
||||
$this->clientError(_('Group not found!'), 404, $this->format);
|
||||
$this->clientError(_('Group not found.'), 404, $this->format);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -101,7 +102,7 @@ class ApiGroupLeaveAction extends ApiAuthAction
|
||||
}
|
||||
|
||||
if (empty($this->group)) {
|
||||
$this->clientError(_('Group not found!'), 404, $this->format);
|
||||
$this->clientError(_('Group not found.'), 404, $this->format);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -66,7 +67,13 @@ class ApiGroupListAction extends ApiBareAuthAction
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->user = $this->getTargetUser($id);
|
||||
$this->user = $this->getTargetUser(null);
|
||||
|
||||
if (empty($this->user)) {
|
||||
$this->clientError(_('No such user.'), 404, $this->format);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->groups = $this->getGroups();
|
||||
|
||||
return true;
|
||||
@ -86,12 +93,8 @@ class ApiGroupListAction extends ApiBareAuthAction
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if (empty($this->user)) {
|
||||
$this->clientError(_('No such user.'), 404, $this->format);
|
||||
return;
|
||||
}
|
||||
|
||||
$sitename = common_config('site', 'name');
|
||||
// TRANS: %s is a user name
|
||||
$title = sprintf(_("%s's groups"), $this->user->nickname);
|
||||
$taguribase = TagURI::base();
|
||||
$id = "tag:$taguribase:Groups";
|
||||
@ -99,10 +102,12 @@ class ApiGroupListAction extends ApiBareAuthAction
|
||||
'usergroups',
|
||||
array('nickname' => $this->user->nickname)
|
||||
);
|
||||
|
||||
$subtitle = sprintf(
|
||||
_("Groups %1$s is a member of on %2$s."),
|
||||
$this->user->nickname,
|
||||
$sitename
|
||||
// TRANS: Meant to convey the user %2$s is a member of each of the groups listed on site %1$s
|
||||
_("%1\$s groups %2\$s is a member of."),
|
||||
$sitename,
|
||||
$this->user->nickname
|
||||
);
|
||||
|
||||
switch($this->format) {
|
||||
|
@ -26,6 +26,7 @@
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -66,7 +67,7 @@ class ApiGroupListAllAction extends ApiPrivateAuthAction
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->user = $this->getTargetUser($id);
|
||||
$this->user = $this->getTargetUser(null);
|
||||
$this->groups = $this->getGroups();
|
||||
|
||||
return true;
|
||||
@ -87,6 +88,7 @@ class ApiGroupListAllAction extends ApiPrivateAuthAction
|
||||
parent::handle($args);
|
||||
|
||||
$sitename = common_config('site', 'name');
|
||||
// TRANS: Message is used as a title. %s is a site name.
|
||||
$title = sprintf(_("%s groups"), $sitename);
|
||||
$taguribase = TagURI::base();
|
||||
$id = "tag:$taguribase:Groups";
|
||||
@ -137,11 +139,18 @@ class ApiGroupListAllAction extends ApiPrivateAuthAction
|
||||
$qry = 'SELECT user_group.* '.
|
||||
'from user_group join local_group on user_group.id = local_group.group_id '.
|
||||
'order by created desc ';
|
||||
|
||||
$offset = intval($this->page - 1) * intval($this->count);
|
||||
$limit = intval($this->count);
|
||||
if (common_config('db', 'type') == 'pgsql') {
|
||||
$qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
|
||||
} else {
|
||||
$qry .= ' LIMIT ' . $offset . ', ' . $limit;
|
||||
}
|
||||
$group = new User_group();
|
||||
|
||||
$group->query($qry);
|
||||
|
||||
$groups = array();
|
||||
while ($group->fetch()) {
|
||||
$groups[] = clone($group);
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -88,7 +89,7 @@ class ApiGroupMembershipAction extends ApiPrivateAuthAction
|
||||
parent::handle($args);
|
||||
|
||||
if (empty($this->group)) {
|
||||
$this->clientError(_('Group not found!'), 404, $this->format);
|
||||
$this->clientError(_('Group not found.'), 404, $this->format);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -79,7 +80,7 @@ class ApiGroupShowAction extends ApiPrivateAuthAction
|
||||
common_redirect(common_local_url('ApiGroupShow', $args), 301);
|
||||
} else {
|
||||
$this->clientError(
|
||||
_('Group not found!'),
|
||||
_('Group not found.'),
|
||||
404,
|
||||
$this->format
|
||||
);
|
||||
|
141
actions/apimediaupload.php
Normal file
141
actions/apimediaupload.php
Normal file
@ -0,0 +1,141 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Upload an image via the API
|
||||
*
|
||||
* 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 API
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2010 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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR . '/lib/apiauth.php';
|
||||
require_once INSTALLDIR . '/lib/mediafile.php';
|
||||
|
||||
/**
|
||||
* Upload an image via the API. Returns a shortened URL for the image
|
||||
* to the user.
|
||||
*
|
||||
* @category API
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@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 ApiMediaUploadAction extends ApiAuthAction
|
||||
{
|
||||
/**
|
||||
* Handle the request
|
||||
*
|
||||
* Grab the file from the 'media' param, then store, and shorten
|
||||
*
|
||||
* @todo Upload throttle!
|
||||
*
|
||||
* @param array $args $_REQUEST data (unused)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
|
||||
$this->clientError(
|
||||
_('This method requires a POST.'),
|
||||
400, $this->format
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Workaround for PHP returning empty $_POST and $_FILES when POST
|
||||
// length > post_max_size in php.ini
|
||||
|
||||
if (empty($_FILES)
|
||||
&& empty($_POST)
|
||||
&& ($_SERVER['CONTENT_LENGTH'] > 0)
|
||||
) {
|
||||
$msg = _('The server was unable to handle that much POST ' .
|
||||
'data (%s bytes) due to its current configuration.');
|
||||
|
||||
$this->clientError(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
|
||||
return;
|
||||
}
|
||||
|
||||
$upload = null;
|
||||
|
||||
try {
|
||||
$upload = MediaFile::fromUpload('media', $this->auth_user);
|
||||
} catch (ClientException $ce) {
|
||||
$this->clientError($ce->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($upload)) {
|
||||
$this->showResponse($upload);
|
||||
} else {
|
||||
$this->clientError('Upload failed.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a Twitpic-like response with the ID of the media file
|
||||
* and a (hopefully) shortened URL for it.
|
||||
*
|
||||
* @param File $upload the uploaded file
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showResponse($upload)
|
||||
{
|
||||
$this->initDocument();
|
||||
$this->elementStart('rsp', array('stat' => 'ok'));
|
||||
$this->element('mediaid', null, $upload->fileRecord->id);
|
||||
$this->element('mediaurl', null, $upload->shortUrl());
|
||||
$this->elementEnd('rsp');
|
||||
$this->endDocument();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrided clientError to show a more Twitpic-like error
|
||||
*
|
||||
* @param String $msg an error message
|
||||
*
|
||||
*/
|
||||
function clientError($msg)
|
||||
{
|
||||
$this->initDocument();
|
||||
$this->elementStart('rsp', array('stat' => 'fail'));
|
||||
|
||||
// @todo add in error code
|
||||
$errAttr = array('msg' => $msg);
|
||||
|
||||
$this->element('err', $errAttr, null);
|
||||
$this->elementEnd('rsp');
|
||||
$this->endDocument();
|
||||
}
|
||||
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
* @category Search
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2008-2009 StatusNet, Inc.
|
||||
* @copyright 2008-2010 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/
|
||||
*/
|
||||
@ -31,6 +31,8 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/apiprivateauth.php';
|
||||
|
||||
/**
|
||||
* Action for outputting search results in Twitter compatible Atom
|
||||
* format.
|
||||
@ -44,10 +46,10 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*
|
||||
* @see ApiAction
|
||||
* @see ApiPrivateAuthAction
|
||||
*/
|
||||
|
||||
class TwitapisearchatomAction extends ApiAction
|
||||
class ApiSearchAtomAction extends ApiPrivateAuthAction
|
||||
{
|
||||
|
||||
var $cnt;
|
||||
@ -96,8 +98,11 @@ class TwitapisearchatomAction extends ApiAction
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
common_debug("in apisearchatom prepare()");
|
||||
|
||||
parent::prepare($args);
|
||||
|
||||
|
||||
$this->query = $this->trimmed('q');
|
||||
$this->lang = $this->trimmed('lang');
|
||||
$this->rpp = $this->trimmed('rpp');
|
||||
@ -138,6 +143,7 @@ class TwitapisearchatomAction extends ApiAction
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
common_debug("In apisearchatom handle()");
|
||||
$this->showAtom();
|
||||
}
|
||||
|
||||
@ -342,10 +348,24 @@ class TwitapisearchatomAction extends ApiAction
|
||||
'rel' => 'related',
|
||||
'href' => $profile->avatarUrl()));
|
||||
|
||||
// TODO: Here is where we'd put in a link to an atom feed for threads
|
||||
// @todo: Here is where we'd put in a link to an atom feed for threads
|
||||
|
||||
$this->element("twitter:source", null,
|
||||
htmlentities($this->sourceLink($notice->source)));
|
||||
$source = null;
|
||||
|
||||
$ns = $notice->getSource();
|
||||
if ($ns) {
|
||||
if (!empty($ns->name) && !empty($ns->url)) {
|
||||
$source = '<a href="'
|
||||
. htmlspecialchars($ns->url)
|
||||
. '" rel="nofollow">'
|
||||
. htmlspecialchars($ns->name)
|
||||
. '</a>';
|
||||
} else {
|
||||
$source = $ns->code;
|
||||
}
|
||||
}
|
||||
|
||||
$this->element("twitter:source", null, $source);
|
||||
|
||||
$this->elementStart('author');
|
||||
|
@ -22,7 +22,7 @@
|
||||
* @category Search
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2008-2009 StatusNet, Inc.
|
||||
* @copyright 2008-2010 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/
|
||||
*/
|
||||
@ -31,6 +31,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/apiprivateauth.php';
|
||||
require_once INSTALLDIR.'/lib/jsonsearchresultslist.php';
|
||||
|
||||
/**
|
||||
@ -44,7 +45,7 @@ require_once INSTALLDIR.'/lib/jsonsearchresultslist.php';
|
||||
* @see ApiAction
|
||||
*/
|
||||
|
||||
class TwitapisearchjsonAction extends ApiAction
|
||||
class ApiSearchJSONAction extends ApiPrivateAuthAction
|
||||
{
|
||||
var $query;
|
||||
var $lang;
|
||||
@ -64,6 +65,8 @@ class TwitapisearchjsonAction extends ApiAction
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
common_debug("apisearchjson prepare()");
|
||||
|
||||
parent::prepare($args);
|
||||
|
||||
$this->query = $this->trimmed('q');
|
@ -29,6 +29,7 @@
|
||||
* @author Robin Millette <robin@millette.info>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -99,19 +100,27 @@ class ApiStatusesDestroyAction extends ApiAuthAction
|
||||
parent::handle($args);
|
||||
|
||||
if (!in_array($this->format, array('xml', 'json'))) {
|
||||
$this->clientError(_('API method not found.'), $code = 404);
|
||||
$this->clientError(
|
||||
_('API method not found.'),
|
||||
404
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
|
||||
$this->clientError(_('This method requires a POST or DELETE.'),
|
||||
400, $this->format);
|
||||
$this->clientError(
|
||||
_('This method requires a POST or DELETE.'),
|
||||
400,
|
||||
$this->format
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($this->notice)) {
|
||||
$this->clientError(_('No status found with that ID.'),
|
||||
404, $this->format);
|
||||
$this->clientError(
|
||||
_('No status found with that ID.'),
|
||||
404, $this->format
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -120,18 +129,14 @@ class ApiStatusesDestroyAction extends ApiAuthAction
|
||||
$replies->get('notice_id', $this->notice_id);
|
||||
$replies->delete();
|
||||
$this->notice->delete();
|
||||
|
||||
if ($this->format == 'xml') {
|
||||
$this->showSingleXmlStatus($this->notice);
|
||||
} elseif ($this->format == 'json') {
|
||||
$this->show_single_json_status($this->notice);
|
||||
}
|
||||
} else {
|
||||
$this->clientError(_('You may not delete another user\'s status.'),
|
||||
403, $this->format);
|
||||
}
|
||||
|
||||
$this->showNotice();
|
||||
} else {
|
||||
$this->clientError(
|
||||
_('You may not delete another user\'s status.'),
|
||||
403,
|
||||
$this->format
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,7 +79,7 @@ class ApiStatusesRetweetAction extends ApiAuthAction
|
||||
|
||||
$this->user = $this->auth_user;
|
||||
|
||||
if ($this->user->id == $notice->profile_id) {
|
||||
if ($this->user->id == $this->original->profile_id) {
|
||||
$this->clientError(_('Cannot repeat your own notice.'),
|
||||
400, $this->format);
|
||||
return false;
|
||||
|
@ -29,6 +29,7 @@
|
||||
* @author Robin Millette <robin@millette.info>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
@ -29,10 +29,102 @@
|
||||
* @author Robin Millette <robin@millette.info>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009-2010 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
/* External API usage documentation. Please update when you change how this method works. */
|
||||
|
||||
/*! @page statusesupdate statuses/update
|
||||
|
||||
@section Description
|
||||
Updates the authenticating user's status. Requires the status parameter specified below.
|
||||
Request must be a POST.
|
||||
|
||||
@par URL pattern
|
||||
/api/statuses/update.:format
|
||||
|
||||
@par Formats (:format)
|
||||
xml, json
|
||||
|
||||
@par HTTP Method(s)
|
||||
POST
|
||||
|
||||
@par Requires Authentication
|
||||
Yes
|
||||
|
||||
@param status (Required) The URL-encoded text of the status update.
|
||||
@param source (Optional) The source of the status.
|
||||
@param in_reply_to_status_id (Optional) The ID of an existing status that the update is in reply to.
|
||||
@param lat (Optional) The latitude the status refers to.
|
||||
@param long (Optional) The longitude the status refers to.
|
||||
@param media (Optional) a media upload, such as an image or movie file.
|
||||
|
||||
@sa @ref authentication
|
||||
@sa @ref apiroot
|
||||
|
||||
@subsection usagenotes Usage notes
|
||||
|
||||
@li The URL pattern is relative to the @ref apiroot.
|
||||
@li If the @e source parameter is not supplied the source of the status will default to 'api'.
|
||||
@li The XML response uses <a href="http://georss.org/Main_Page">GeoRSS</a>
|
||||
to encode the latitude and longitude (see example response below <georss:point>).
|
||||
@li Data uploaded via the @e media parameter should be multipart/form-data encoded.
|
||||
|
||||
@subsection exampleusage Example usage
|
||||
|
||||
@verbatim
|
||||
curl -u username:password http://example.com/api/statuses/update.xml -d status='Howdy!' -d lat='30.468' -d long='-94.743'
|
||||
@endverbatim
|
||||
|
||||
@subsection exampleresponse Example response
|
||||
|
||||
@verbatim
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<status>
|
||||
<text>Howdy!</text>
|
||||
<truncated>false</truncated>
|
||||
<created_at>Tue Mar 30 23:28:05 +0000 2010</created_at>
|
||||
<in_reply_to_status_id/>
|
||||
<source>api</source>
|
||||
<id>26668724</id>
|
||||
<in_reply_to_user_id/>
|
||||
<in_reply_to_screen_name/>
|
||||
<geo xmlns:georss="http://www.georss.org/georss">
|
||||
<georss:point>30.468 -94.743</georss:point>
|
||||
</geo>
|
||||
<favorited>false</favorited>
|
||||
<user>
|
||||
<id>25803</id>
|
||||
<name>Jed Sanders</name>
|
||||
<screen_name>jedsanders</screen_name>
|
||||
<location>Hoop and Holler, Texas</location>
|
||||
<description>I like to think of myself as America's Favorite.</description>
|
||||
<profile_image_url>http://avatar.example.com/25803-48-20080924200604.png</profile_image_url>
|
||||
<url>http://jedsanders.net</url>
|
||||
<protected>false</protected>
|
||||
<followers_count>5</followers_count>
|
||||
<profile_background_color/>
|
||||
<profile_text_color/>
|
||||
<profile_link_color/>
|
||||
<profile_sidebar_fill_color/>
|
||||
<profile_sidebar_border_color/>
|
||||
<friends_count>2</friends_count>
|
||||
<created_at>Wed Sep 24 20:04:00 +0000 2008</created_at>
|
||||
<favourites_count>0</favourites_count>
|
||||
<utc_offset>0</utc_offset>
|
||||
<time_zone>UTC</time_zone>
|
||||
<profile_background_image_url/>
|
||||
<profile_background_tile>false</profile_background_tile>
|
||||
<statuses_count>70</statuses_count>
|
||||
<following>true</following>
|
||||
<notifications>true</notifications>
|
||||
</user>
|
||||
</status>
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
@ -64,8 +156,6 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
||||
var $lat = null;
|
||||
var $lon = null;
|
||||
|
||||
static $reserved_sources = array('web', 'omb', 'mail', 'xmpp', 'api');
|
||||
|
||||
/**
|
||||
* Take arguments for running
|
||||
*
|
||||
@ -80,19 +170,9 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
||||
parent::prepare($args);
|
||||
|
||||
$this->status = $this->trimmed('status');
|
||||
$this->source = $this->trimmed('source');
|
||||
$this->lat = $this->trimmed('lat');
|
||||
$this->lon = $this->trimmed('long');
|
||||
|
||||
// try to set the source attr from OAuth app
|
||||
if (empty($this->source)) {
|
||||
$this->source = $this->oauth_source;
|
||||
}
|
||||
|
||||
if (empty($this->source) || in_array($this->source, self::$reserved_sources)) {
|
||||
$this->source = 'api';
|
||||
}
|
||||
|
||||
$this->in_reply_to_status_id
|
||||
= intval($this->trimmed('in_reply_to_status_id'));
|
||||
|
||||
@ -199,7 +279,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
||||
$reply_to = $this->in_reply_to_status_id;
|
||||
} else {
|
||||
$this->clientError(
|
||||
_('Not found'),
|
||||
_('Not found.'),
|
||||
$code = 404,
|
||||
$this->format
|
||||
);
|
||||
@ -244,11 +324,17 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
||||
$options = array_merge($options, $locOptions);
|
||||
}
|
||||
|
||||
$this->notice =
|
||||
Notice::saveNew($this->auth_user->id,
|
||||
try {
|
||||
$this->notice = Notice::saveNew(
|
||||
$this->auth_user->id,
|
||||
$content,
|
||||
$this->source,
|
||||
$options);
|
||||
$options
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
$this->clientError($e->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($upload)) {
|
||||
$upload->attachToNotice($this->notice);
|
||||
|
@ -97,19 +97,25 @@ class ApiStatusnetConfigAction extends ApiAction
|
||||
|
||||
// XXX: check that all sections and settings are legal XML elements
|
||||
|
||||
common_debug(var_export($this->keys, true));
|
||||
|
||||
foreach ($this->keys as $section => $settings) {
|
||||
$this->elementStart($section);
|
||||
foreach ($settings as $setting) {
|
||||
$value = common_config($section, $setting);
|
||||
if (is_array($value)) {
|
||||
$value = implode(',', $value);
|
||||
} else if ($value === false) {
|
||||
} else if ($value === false || $value == '0') {
|
||||
$value = 'false';
|
||||
} else if ($value === true) {
|
||||
} else if ($value === true || $value == '1') {
|
||||
$value = 'true';
|
||||
}
|
||||
|
||||
// return theme logo if there's no site specific one
|
||||
if (empty($value)) {
|
||||
if ($section == 'site' && $setting == 'logo') {
|
||||
$value = Theme::path('logo.png');
|
||||
}
|
||||
}
|
||||
|
||||
$this->element($setting, null, $value);
|
||||
}
|
||||
$this->elementEnd($section);
|
||||
|
@ -206,7 +206,8 @@ class ApiSubscriptionsAction extends ApiBareAuthAction
|
||||
{
|
||||
switch ($this->format) {
|
||||
case 'xml':
|
||||
$this->elementStart('users', array('type' => 'array'));
|
||||
$this->elementStart('users', array('type' => 'array',
|
||||
'xmlns:statusnet' => 'http://status.net/schema/api/1/'));
|
||||
foreach ($this->profiles as $profile) {
|
||||
$this->showProfile(
|
||||
$profile,
|
||||
|
@ -23,7 +23,9 @@
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Zach Copley <zach@status.net> * @copyright 2009 StatusNet, Inc.
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009-2010 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -123,29 +125,33 @@ class ApiTimelineFavoritesAction extends ApiBareAuthAction
|
||||
? $avatar->displayUrl()
|
||||
: Avatar::defaultImage(AVATAR_PROFILE_SIZE);
|
||||
|
||||
$link = common_local_url(
|
||||
'showfavorites',
|
||||
array('nickname' => $this->user->nickname)
|
||||
);
|
||||
|
||||
$self = $this->getSelfUri();
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showXmlTimeline($this->notices);
|
||||
break;
|
||||
case 'rss':
|
||||
$link = common_local_url(
|
||||
'showfavorites',
|
||||
array('nickname' => $this->user->nickname)
|
||||
);
|
||||
$this->showRssTimeline(
|
||||
$this->notices,
|
||||
$title,
|
||||
$link,
|
||||
$subtitle,
|
||||
null,
|
||||
$logo
|
||||
$logo,
|
||||
$self
|
||||
);
|
||||
break;
|
||||
case 'atom':
|
||||
|
||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||
|
||||
$atom = new AtomNoticeFeed();
|
||||
$atom = new AtomNoticeFeed($this->auth_user);
|
||||
|
||||
$atom->setId($id);
|
||||
$atom->setTitle($title);
|
||||
@ -153,23 +159,8 @@ class ApiTimelineFavoritesAction extends ApiBareAuthAction
|
||||
$atom->setLogo($logo);
|
||||
$atom->setUpdated('now');
|
||||
|
||||
$atom->addLink(
|
||||
common_local_url(
|
||||
'showfavorites',
|
||||
array('nickname' => $this->user->nickname)
|
||||
)
|
||||
);
|
||||
|
||||
$id = $this->arg('id');
|
||||
$aargs = array('format' => 'atom');
|
||||
if (!empty($id)) {
|
||||
$aargs['id'] = $id;
|
||||
}
|
||||
|
||||
$atom->addLink(
|
||||
$this->getSelfUri('ApiTimelineFavorites', $aargs),
|
||||
array('rel' => 'self', 'type' => 'application/atom+xml')
|
||||
);
|
||||
$atom->addLink($link);
|
||||
$atom->setSelfLink($self);
|
||||
|
||||
$atom->addEntryFromNotices($this->notices);
|
||||
|
||||
@ -195,17 +186,23 @@ class ApiTimelineFavoritesAction extends ApiBareAuthAction
|
||||
{
|
||||
$notices = array();
|
||||
|
||||
common_debug("since id = " . $this->since_id . " max id = " . $this->max_id);
|
||||
|
||||
if (!empty($this->auth_user) && $this->auth_user->id == $this->user->id) {
|
||||
$notice = $this->user->favoriteNotices(
|
||||
true,
|
||||
($this->page-1) * $this->count,
|
||||
$this->count,
|
||||
true
|
||||
$this->since_id,
|
||||
$this->max_id
|
||||
);
|
||||
} else {
|
||||
$notice = $this->user->favoriteNotices(
|
||||
false,
|
||||
($this->page-1) * $this->count,
|
||||
$this->count,
|
||||
false
|
||||
$this->since_id,
|
||||
$this->max_id
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -28,11 +28,107 @@
|
||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
||||
* @author Robin Millette <robin@millette.info>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009-2010 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
/* External API usage documentation. Please update when you change how this method works. */
|
||||
|
||||
/*! @page friendstimeline statuses/friends_timeline
|
||||
|
||||
@section Description
|
||||
Returns the 20 most recent statuses posted by the authenticating
|
||||
user and that user's friends. This is the equivalent of "You and
|
||||
friends" page in the web interface.
|
||||
|
||||
@par URL patterns
|
||||
@li /api/statuses/friends_timeline.:format
|
||||
@li /api/statuses/friends_timeline/:id.:format
|
||||
|
||||
@par Formats (:format)
|
||||
xml, json, rss, atom
|
||||
|
||||
@par ID (:id)
|
||||
username, user id
|
||||
|
||||
@par HTTP Method(s)
|
||||
GET
|
||||
|
||||
@par Requires Authentication
|
||||
Sometimes (see: @ref authentication)
|
||||
|
||||
@param user_id (Optional) Specifies a user by ID
|
||||
@param screen_name (Optional) Specifies a user by screename (nickname)
|
||||
@param since_id (Optional) Returns only statuses with an ID greater
|
||||
than (that is, more recent than) the specified ID.
|
||||
@param max_id (Optional) Returns only statuses with an ID less than
|
||||
(that is, older than) or equal to the specified ID.
|
||||
@param count (Optional) Specifies the number of statuses to retrieve.
|
||||
@param page (Optional) Specifies the page of results to retrieve.
|
||||
|
||||
@sa @ref authentication
|
||||
@sa @ref apiroot
|
||||
|
||||
@subsection usagenotes Usage notes
|
||||
@li The URL pattern is relative to the @ref apiroot.
|
||||
@li The XML response uses <a href="http://georss.org/Main_Page">GeoRSS</a>
|
||||
to encode the latitude and longitude (see example response below <georss:point>).
|
||||
|
||||
@subsection exampleusage Example usage
|
||||
|
||||
@verbatim
|
||||
curl http://identi.ca/api/statuses/friends_timeline/evan.xml?count=1&page=2
|
||||
@endverbatim
|
||||
|
||||
@subsection exampleresponse Example response
|
||||
|
||||
@verbatim
|
||||
<?xml version="1.0"?>
|
||||
<statuses type="array">
|
||||
<status>
|
||||
<text>back from the !yul !drupal meet with Evolving Web folk, @anarcat, @webchick and others, and an interesting refresher on SQL indexing</text>
|
||||
<truncated>false</truncated>
|
||||
<created_at>Wed Mar 31 01:33:02 +0000 2010</created_at>
|
||||
<in_reply_to_status_id/>
|
||||
<source><a href="http://code.google.com/p/microblog-purple/">mbpidgin</a></source>
|
||||
<id>26674201</id>
|
||||
<in_reply_to_user_id/>
|
||||
<in_reply_to_screen_name/>
|
||||
<geo/>
|
||||
<favorited>false</favorited>
|
||||
<user>
|
||||
<id>246</id>
|
||||
<name>Mark</name>
|
||||
<screen_name>lambic</screen_name>
|
||||
<location>Montreal, Canada</location>
|
||||
<description>Geek</description>
|
||||
<profile_image_url>http://avatar.identi.ca/246-48-20080702141545.png</profile_image_url>
|
||||
<url>http://lambic.co.uk</url>
|
||||
<protected>false</protected>
|
||||
<followers_count>73</followers_count>
|
||||
<profile_background_color>#F0F2F5</profile_background_color>
|
||||
<profile_text_color/>
|
||||
<profile_link_color>#002E6E</profile_link_color>
|
||||
<profile_sidebar_fill_color>#CEE1E9</profile_sidebar_fill_color>
|
||||
<profile_sidebar_border_color/>
|
||||
<friends_count>58</friends_count>
|
||||
<created_at>Wed Jul 02 14:12:15 +0000 2008</created_at>
|
||||
<favourites_count>2</favourites_count>
|
||||
<utc_offset>-14400</utc_offset>
|
||||
<time_zone>US/Eastern</time_zone>
|
||||
<profile_background_image_url/>
|
||||
<profile_background_tile>false</profile_background_tile>
|
||||
<statuses_count>933</statuses_count>
|
||||
<following>false</following>
|
||||
<notifications>false</notifications>
|
||||
</user>
|
||||
</status>
|
||||
</statuses>
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
@ -116,10 +212,19 @@ class ApiTimelineFriendsAction extends ApiBareAuthAction
|
||||
$id = "tag:$taguribase:FriendsTimeline:" . $this->user->id;
|
||||
|
||||
$subtitle = sprintf(
|
||||
// TRANS: Message is used as a subtitle. %1$s is a user nickname, %2$s is a site name.
|
||||
_('Updates from %1$s and friends on %2$s!'),
|
||||
$this->user->nickname, $sitename
|
||||
$this->user->nickname,
|
||||
$sitename
|
||||
);
|
||||
|
||||
$link = common_local_url(
|
||||
'all',
|
||||
array('nickname' => $this->user->nickname)
|
||||
);
|
||||
|
||||
$self = $this->getSelfUri();
|
||||
|
||||
$logo = (!empty($avatar))
|
||||
? $avatar->displayUrl()
|
||||
: Avatar::defaultImage(AVATAR_PROFILE_SIZE);
|
||||
@ -130,50 +235,29 @@ class ApiTimelineFriendsAction extends ApiBareAuthAction
|
||||
break;
|
||||
case 'rss':
|
||||
|
||||
$link = common_local_url(
|
||||
'all', array(
|
||||
'nickname' => $this->user->nickname
|
||||
)
|
||||
);
|
||||
|
||||
$this->showRssTimeline(
|
||||
$this->notices,
|
||||
$title,
|
||||
$link,
|
||||
$subtitle,
|
||||
null,
|
||||
$logo
|
||||
$logo,
|
||||
$self
|
||||
);
|
||||
break;
|
||||
case 'atom':
|
||||
|
||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||
|
||||
$atom = new AtomNoticeFeed();
|
||||
$atom = new AtomNoticeFeed($this->auth_user);
|
||||
|
||||
$atom->setId($id);
|
||||
$atom->setTitle($title);
|
||||
$atom->setSubtitle($subtitle);
|
||||
$atom->setLogo($logo);
|
||||
$atom->setUpdated('now');
|
||||
|
||||
$atom->addLink(
|
||||
common_local_url(
|
||||
'all',
|
||||
array('nickname' => $this->user->nickname)
|
||||
)
|
||||
);
|
||||
|
||||
$id = $this->arg('id');
|
||||
$aargs = array('format' => 'atom');
|
||||
if (!empty($id)) {
|
||||
$aargs['id'] = $id;
|
||||
}
|
||||
|
||||
$atom->addLink(
|
||||
$this->getSelfUri('ApiTimelineFriends', $aargs),
|
||||
array('rel' => 'self', 'type' => 'application/atom+xml')
|
||||
);
|
||||
$atom->addLink($link);
|
||||
$atom->setSelfLink($self);
|
||||
|
||||
$atom->addEntryFromNotices($this->notices);
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -88,7 +89,7 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction
|
||||
parent::handle($args);
|
||||
|
||||
if (empty($this->group)) {
|
||||
$this->clientError(_('Group not found!'), 404, $this->format);
|
||||
$this->clientError(_('Group not found.'), 404, $this->format);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -104,17 +105,10 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction
|
||||
|
||||
function showTimeline()
|
||||
{
|
||||
$sitename = common_config('site', 'name');
|
||||
$avatar = $this->group->homepage_logo;
|
||||
$title = sprintf(_("%s timeline"), $this->group->nickname);
|
||||
// We'll pull common formatting out of this for other formats
|
||||
$atom = new AtomGroupNoticeFeed($this->group, $this->auth_user);
|
||||
|
||||
$subtitle = sprintf(
|
||||
_('Updates from %1$s on %2$s!'),
|
||||
$this->group->nickname,
|
||||
$sitename
|
||||
);
|
||||
|
||||
$logo = ($avatar) ? $avatar : User_group::defaultLogo(AVATAR_PROFILE_SIZE);
|
||||
$self = $this->getSelfUri();
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
@ -123,11 +117,12 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction
|
||||
case 'rss':
|
||||
$this->showRssTimeline(
|
||||
$this->notices,
|
||||
$title,
|
||||
$atom->title,
|
||||
$this->group->homeUrl(),
|
||||
$subtitle,
|
||||
$atom->subtitle,
|
||||
null,
|
||||
$logo
|
||||
$atom->logo,
|
||||
$self
|
||||
);
|
||||
break;
|
||||
case 'atom':
|
||||
@ -135,40 +130,12 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction
|
||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||
|
||||
try {
|
||||
|
||||
$atom = new AtomGroupNoticeFeed($this->group);
|
||||
|
||||
// @todo set all this Atom junk up inside the feed class
|
||||
|
||||
$atom->setId($id);
|
||||
$atom->setTitle($title);
|
||||
$atom->setSubtitle($subtitle);
|
||||
$atom->setLogo($logo);
|
||||
$atom->setUpdated('now');
|
||||
|
||||
$atom->addAuthorRaw($this->group->asAtomAuthor());
|
||||
$atom->setActivitySubject($this->group->asActivitySubject());
|
||||
|
||||
$atom->addLink($this->group->homeUrl());
|
||||
|
||||
$id = $this->arg('id');
|
||||
$aargs = array('format' => 'atom');
|
||||
if (!empty($id)) {
|
||||
$aargs['id'] = $id;
|
||||
}
|
||||
|
||||
$atom->setId($this->getSelfUri('ApiTimelineGroup', $aargs));
|
||||
|
||||
$atom->addLink(
|
||||
$this->getSelfUri('ApiTimelineGroup', $aargs),
|
||||
array('rel' => 'self', 'type' => 'application/atom+xml')
|
||||
);
|
||||
|
||||
$atom->setId($self);
|
||||
$atom->setSelfLink($self);
|
||||
$atom->addEntryFromNotices($this->notices);
|
||||
|
||||
//$this->raw($atom->getString());
|
||||
print $atom->getString(); // temp hack until PuSH feeds are redone cleanly
|
||||
|
||||
$this->raw($atom->getString());
|
||||
} catch (Atom10FeedException $e) {
|
||||
$this->serverError(
|
||||
'Could not generate feed for group - ' . $e->getMessage()
|
||||
|
@ -29,6 +29,7 @@
|
||||
* @author Robin Millette <robin@millette.info>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -72,7 +73,7 @@ class ApiTimelineHomeAction extends ApiBareAuthAction
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
common_debug("api home_timeline");
|
||||
|
||||
$this->user = $this->getTargetUser($this->arg('id'));
|
||||
|
||||
if (empty($this->user)) {
|
||||
@ -117,10 +118,18 @@ class ApiTimelineHomeAction extends ApiBareAuthAction
|
||||
$id = "tag:$taguribase:HomeTimeline:" . $this->user->id;
|
||||
|
||||
$subtitle = sprintf(
|
||||
// TRANS: Message is used as a subtitle. %1$s is a user nickname, %2$s is a site name.
|
||||
_('Updates from %1$s and friends on %2$s!'),
|
||||
$this->user->nickname, $sitename
|
||||
);
|
||||
|
||||
$link = common_local_url(
|
||||
'all',
|
||||
array('nickname' => $this->user->nickname)
|
||||
);
|
||||
|
||||
$self = $this->getSelfUri();
|
||||
|
||||
$logo = (!empty($avatar))
|
||||
? $avatar->displayUrl()
|
||||
: Avatar::defaultImage(AVATAR_PROFILE_SIZE);
|
||||
@ -130,24 +139,21 @@ class ApiTimelineHomeAction extends ApiBareAuthAction
|
||||
$this->showXmlTimeline($this->notices);
|
||||
break;
|
||||
case 'rss':
|
||||
$link = common_local_url(
|
||||
'all',
|
||||
array('nickname' => $this->user->nickname)
|
||||
);
|
||||
$this->showRssTimeline(
|
||||
$this->notices,
|
||||
$title,
|
||||
$link,
|
||||
$subtitle,
|
||||
null,
|
||||
$logo
|
||||
$logo,
|
||||
$self
|
||||
);
|
||||
break;
|
||||
case 'atom':
|
||||
|
||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||
|
||||
$atom = new AtomNoticeFeed();
|
||||
$atom = new AtomNoticeFeed($this->auth_user);
|
||||
|
||||
$atom->setId($id);
|
||||
$atom->setTitle($title);
|
||||
@ -155,23 +161,8 @@ class ApiTimelineHomeAction extends ApiBareAuthAction
|
||||
$atom->setLogo($logo);
|
||||
$atom->setUpdated('now');
|
||||
|
||||
$atom->addLink(
|
||||
common_local_url(
|
||||
'all',
|
||||
array('nickname' => $this->user->nickname)
|
||||
)
|
||||
);
|
||||
|
||||
$id = $this->arg('id');
|
||||
$aargs = array('format' => 'atom');
|
||||
if (!empty($id)) {
|
||||
$aargs['id'] = $id;
|
||||
}
|
||||
|
||||
$atom->addLink(
|
||||
$this->getSelfUri('ApiTimelineHome', $aargs),
|
||||
array('rel' => 'self', 'type' => 'application/atom+xml')
|
||||
);
|
||||
$atom->addLink($link);
|
||||
$atom->setSelfLink($self);
|
||||
|
||||
$atom->addEntryFromNotices($this->notices);
|
||||
$this->raw($atom->getString());
|
||||
|
@ -29,6 +29,7 @@
|
||||
* @author Robin Millette <robin@millette.info>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -123,6 +124,9 @@ class ApiTimelineMentionsAction extends ApiBareAuthAction
|
||||
'replies',
|
||||
array('nickname' => $this->user->nickname)
|
||||
);
|
||||
|
||||
$self = $this->getSelfUri();
|
||||
|
||||
$subtitle = sprintf(
|
||||
_('%1$s updates that reply to updates from %2$s / %3$s.'),
|
||||
$sitename, $this->user->nickname, $profile->getBestName()
|
||||
@ -134,11 +138,21 @@ class ApiTimelineMentionsAction extends ApiBareAuthAction
|
||||
$this->showXmlTimeline($this->notices);
|
||||
break;
|
||||
case 'rss':
|
||||
$this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $logo);
|
||||
$this->showRssTimeline(
|
||||
$this->notices,
|
||||
$title,
|
||||
$link,
|
||||
$subtitle,
|
||||
null,
|
||||
$logo,
|
||||
$self
|
||||
);
|
||||
break;
|
||||
case 'atom':
|
||||
|
||||
$atom = new AtomNoticeFeed();
|
||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||
|
||||
$atom = new AtomNoticeFeed($this->auth_user);
|
||||
|
||||
$atom->setId($id);
|
||||
$atom->setTitle($title);
|
||||
@ -146,23 +160,8 @@ class ApiTimelineMentionsAction extends ApiBareAuthAction
|
||||
$atom->setLogo($logo);
|
||||
$atom->setUpdated('now');
|
||||
|
||||
$atom->addLink(
|
||||
common_local_url(
|
||||
'replies',
|
||||
array('nickname' => $this->user->nickname)
|
||||
)
|
||||
);
|
||||
|
||||
$id = $this->arg('id');
|
||||
$aargs = array('format' => 'atom');
|
||||
if (!empty($id)) {
|
||||
$aargs['id'] = $id;
|
||||
}
|
||||
|
||||
$atom->addLink(
|
||||
$this->getSelfUri('ApiTimelineMentions', $aargs),
|
||||
array('rel' => 'self', 'type' => 'application/atom+xml')
|
||||
);
|
||||
$atom->addLink($link);
|
||||
$atom->setSelfLink($self);
|
||||
|
||||
$atom->addEntryFromNotices($this->notices);
|
||||
$this->raw($atom->getString());
|
||||
|
@ -29,6 +29,7 @@
|
||||
* @author Robin Millette <robin@millette.info>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -55,6 +56,95 @@ require_once INSTALLDIR . '/lib/apiprivateauth.php';
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
/* External API usage documentation. Please update when you change how this method works. */
|
||||
|
||||
/*! @page publictimeline statuses/public_timeline
|
||||
|
||||
@section Description
|
||||
Returns the 20 most recent notices from users throughout the system who have
|
||||
uploaded their own avatars. Depending on configuration, it may or may not
|
||||
not include notices from automatic posting services.
|
||||
|
||||
@par URL patterns
|
||||
@li /api/statuses/public_timeline.:format
|
||||
|
||||
@par Formats (:format)
|
||||
xml, json, rss, atom
|
||||
|
||||
@par HTTP Method(s)
|
||||
GET
|
||||
|
||||
@par Requires Authentication
|
||||
No
|
||||
|
||||
@param since_id (Optional) Returns only statuses with an ID greater
|
||||
than (that is, more recent than) the specified ID.
|
||||
@param max_id (Optional) Returns only statuses with an ID less than
|
||||
(that is, older than) or equal to the specified ID.
|
||||
@param count (Optional) Specifies the number of statuses to retrieve.
|
||||
@param page (Optional) Specifies the page of results to retrieve.
|
||||
|
||||
@sa @ref apiroot
|
||||
|
||||
@subsection usagenotes Usage notes
|
||||
@li The URL pattern is relative to the @ref apiroot.
|
||||
@li The XML response uses <a href="http://georss.org/Main_Page">GeoRSS</a>
|
||||
to encode the latitude and longitude (see example response below <georss:point>).
|
||||
|
||||
@subsection exampleusage Example usage
|
||||
|
||||
@verbatim
|
||||
curl http://identi.ca/api/statuses/friends_timeline/evan.xml?count=1&page=2
|
||||
@endverbatim
|
||||
|
||||
@subsection exampleresponse Example response
|
||||
|
||||
@verbatim
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<statuses type="array">
|
||||
<status>
|
||||
<text>@skwashd oh, commbank reenabled me super quick both times. but disconcerting when you don't expect it though</text>
|
||||
<truncated>false</truncated>
|
||||
<created_at>Sat Apr 17 00:49:12 +0000 2010</created_at>
|
||||
<in_reply_to_status_id>28838393</in_reply_to_status_id>
|
||||
<source>xmpp</source>
|
||||
<id>28838456</id>
|
||||
<in_reply_to_user_id>39303</in_reply_to_user_id>
|
||||
<in_reply_to_screen_name>skwashd</in_reply_to_screen_name>
|
||||
<geo></geo>
|
||||
<favorited>false</favorited>
|
||||
<user>
|
||||
<id>44517</id>
|
||||
<name>joshua may</name>
|
||||
<screen_name>notjosh</screen_name>
|
||||
<location></location>
|
||||
<description></description>
|
||||
<profile_image_url>http://avatar.identi.ca/44517-48-20090321004106.jpeg</profile_image_url>
|
||||
<url></url>
|
||||
<protected>false</protected>
|
||||
<followers_count>17</followers_count>
|
||||
<profile_background_color></profile_background_color>
|
||||
<profile_text_color></profile_text_color>
|
||||
<profile_link_color></profile_link_color>
|
||||
<profile_sidebar_fill_color></profile_sidebar_fill_color>
|
||||
<profile_sidebar_border_color></profile_sidebar_border_color>
|
||||
<friends_count>20</friends_count>
|
||||
<created_at>Sat Mar 21 00:40:25 +0000 2009</created_at>
|
||||
<favourites_count>0</favourites_count>
|
||||
<utc_offset>0</utc_offset>
|
||||
<time_zone>UTC</time_zone>
|
||||
<profile_background_image_url></profile_background_image_url>
|
||||
<profile_background_tile>false</profile_background_tile>
|
||||
<statuses_count>100</statuses_count>
|
||||
<following>false</following>
|
||||
<notifications>false</notifications>
|
||||
</user>
|
||||
</status>
|
||||
[....]
|
||||
</statuses>
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
class ApiTimelinePublicAction extends ApiPrivateAuthAction
|
||||
{
|
||||
|
||||
@ -107,7 +197,8 @@ class ApiTimelinePublicAction extends ApiPrivateAuthAction
|
||||
$title = sprintf(_("%s public timeline"), $sitename);
|
||||
$taguribase = TagURI::base();
|
||||
$id = "tag:$taguribase:PublicTimeline";
|
||||
$link = common_root_url();
|
||||
$link = common_local_url('public');
|
||||
$self = $this->getSelfUri();
|
||||
$subtitle = sprintf(_("%s updates from everyone!"), $sitename);
|
||||
|
||||
switch($this->format) {
|
||||
@ -115,27 +206,29 @@ class ApiTimelinePublicAction extends ApiPrivateAuthAction
|
||||
$this->showXmlTimeline($this->notices);
|
||||
break;
|
||||
case 'rss':
|
||||
$this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $sitelogo);
|
||||
$this->showRssTimeline(
|
||||
$this->notices,
|
||||
$title,
|
||||
$link,
|
||||
$subtitle,
|
||||
null,
|
||||
$sitelogo,
|
||||
$self
|
||||
);
|
||||
break;
|
||||
case 'atom':
|
||||
|
||||
$atom = new AtomNoticeFeed();
|
||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||
|
||||
$atom = new AtomNoticeFeed($this->auth_user);
|
||||
|
||||
$atom->setId($id);
|
||||
$atom->setTitle($title);
|
||||
$atom->setSubtitle($subtitle);
|
||||
$atom->setLogo($sitelogo);
|
||||
$atom->setUpdated('now');
|
||||
|
||||
$atom->addLink(common_local_url('public'));
|
||||
|
||||
$atom->addLink(
|
||||
$this->getSelfUri(
|
||||
'ApiTimelinePublic', array('format' => 'atom')
|
||||
),
|
||||
array('rel' => 'self', 'type' => 'application/atom+xml')
|
||||
);
|
||||
|
||||
$atom->setSelfLink($self);
|
||||
$atom->addEntryFromNotices($this->notices);
|
||||
|
||||
$this->raw($atom->getString());
|
||||
|
@ -69,7 +69,7 @@ class ApiTimelineRetweetedByMeAction extends ApiAuthAction
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->serverError('Unimplemented', 503);
|
||||
$this->serverError('Unimplemented.', 503);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ class ApiTimelineRetweetsOfMeAction extends ApiAuthAction
|
||||
|
||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||
|
||||
$atom = new AtomNoticeFeed();
|
||||
$atom = new AtomNoticeFeed($this->auth_user);
|
||||
|
||||
$atom->setId($id);
|
||||
$atom->setTitle($title);
|
||||
|
@ -25,7 +25,8 @@
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Jeffery To <jeffery.to@gmail.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009-2010 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -67,6 +68,8 @@ class ApiTimelineTagAction extends ApiPrivateAuthAction
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
common_debug("apitimelinetag prepare()");
|
||||
|
||||
$this->tag = $this->arg('tag');
|
||||
$this->notices = $this->getNotices();
|
||||
|
||||
@ -108,29 +111,35 @@ class ApiTimelineTagAction extends ApiPrivateAuthAction
|
||||
$taguribase = TagURI::base();
|
||||
$id = "tag:$taguribase:TagTimeline:".$tag;
|
||||
|
||||
$link = common_local_url(
|
||||
'tag',
|
||||
array('tag' => $this->tag)
|
||||
);
|
||||
|
||||
$self = $this->getSelfUri();
|
||||
|
||||
common_debug("self link is: $self");
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showXmlTimeline($this->notices);
|
||||
break;
|
||||
case 'rss':
|
||||
$link = common_local_url(
|
||||
'tag',
|
||||
array('tag' => $this->tag)
|
||||
);
|
||||
$this->showRssTimeline(
|
||||
$this->notices,
|
||||
$title,
|
||||
$link,
|
||||
$subtitle,
|
||||
null,
|
||||
$sitelogo
|
||||
$sitelogo,
|
||||
$self
|
||||
);
|
||||
break;
|
||||
case 'atom':
|
||||
|
||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||
|
||||
$atom = new AtomNoticeFeed();
|
||||
$atom = new AtomNoticeFeed($this->auth_user);
|
||||
|
||||
$atom->setId($id);
|
||||
$atom->setTitle($title);
|
||||
@ -138,22 +147,8 @@ class ApiTimelineTagAction extends ApiPrivateAuthAction
|
||||
$atom->setLogo($logo);
|
||||
$atom->setUpdated('now');
|
||||
|
||||
$atom->addLink(
|
||||
common_local_url(
|
||||
'tag',
|
||||
array('tag' => $this->tag)
|
||||
)
|
||||
);
|
||||
|
||||
$aargs = array('format' => 'atom');
|
||||
if (!empty($this->tag)) {
|
||||
$aargs['tag'] = $this->tag;
|
||||
}
|
||||
|
||||
$atom->addLink(
|
||||
$this->getSelfUri('ApiTimelineTag', $aargs),
|
||||
array('rel' => 'self', 'type' => 'application/atom+xml')
|
||||
);
|
||||
$atom->addLink($link);
|
||||
$atom->setSelfLink($self);
|
||||
|
||||
$atom->addEntryFromNotices($this->notices);
|
||||
$this->raw($atom->getString());
|
||||
|
@ -29,6 +29,7 @@
|
||||
* @author Robin Millette <robin@millette.info>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -112,19 +113,17 @@ class ApiTimelineUserAction extends ApiBareAuthAction
|
||||
function showTimeline()
|
||||
{
|
||||
$profile = $this->user->getProfile();
|
||||
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||
|
||||
$sitename = common_config('site', 'name');
|
||||
$title = sprintf(_("%s timeline"), $this->user->nickname);
|
||||
// We'll use the shared params from the Atom stub
|
||||
// for other feed types.
|
||||
$atom = new AtomUserNoticeFeed($this->user, $this->auth_user);
|
||||
|
||||
$link = common_local_url(
|
||||
'showstream',
|
||||
array('nickname' => $this->user->nickname)
|
||||
);
|
||||
$subtitle = sprintf(
|
||||
_('Updates from %1$s on %2$s!'),
|
||||
$this->user->nickname, $sitename
|
||||
);
|
||||
$logo = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_PROFILE_SIZE);
|
||||
|
||||
$self = $this->getSelfUri();
|
||||
|
||||
// FriendFeed's SUP protocol
|
||||
// Also added RSS and Atom feeds
|
||||
@ -138,55 +137,23 @@ class ApiTimelineUserAction extends ApiBareAuthAction
|
||||
break;
|
||||
case 'rss':
|
||||
$this->showRssTimeline(
|
||||
$this->notices, $title, $link,
|
||||
$subtitle, $suplink, $logo
|
||||
$this->notices,
|
||||
$atom->title,
|
||||
$link,
|
||||
$atom->subtitle,
|
||||
$suplink,
|
||||
$atom->logo,
|
||||
$self
|
||||
);
|
||||
break;
|
||||
case 'atom':
|
||||
|
||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||
|
||||
// @todo set all this Atom junk up inside the feed class
|
||||
|
||||
$atom = new AtomUserNoticeFeed($this->user);
|
||||
|
||||
$atom->setTitle($title);
|
||||
$atom->setSubtitle($subtitle);
|
||||
$atom->setLogo($logo);
|
||||
$atom->setUpdated('now');
|
||||
|
||||
$atom->addLink(
|
||||
common_local_url(
|
||||
'showstream',
|
||||
array('nickname' => $this->user->nickname)
|
||||
)
|
||||
);
|
||||
|
||||
$id = $this->arg('id');
|
||||
$aargs = array('format' => 'atom');
|
||||
if (!empty($id)) {
|
||||
$aargs['id'] = $id;
|
||||
}
|
||||
|
||||
$atom->setId($this->getSelfUri('ApiTimelineUser', $aargs));
|
||||
|
||||
$atom->addLink(
|
||||
$this->getSelfUri('ApiTimelineUser', $aargs),
|
||||
array('rel' => 'self', 'type' => 'application/atom+xml')
|
||||
);
|
||||
|
||||
$atom->addLink(
|
||||
$suplink,
|
||||
array(
|
||||
'rel' => 'http://api.friendfeed.com/2008/03#sup',
|
||||
'type' => 'application/json'
|
||||
)
|
||||
);
|
||||
|
||||
$atom->setId($self);
|
||||
$atom->setSelfLink($self);
|
||||
$atom->addEntryFromNotices($this->notices);
|
||||
|
||||
#$this->raw($atom->getString());
|
||||
print $atom->getString(); // temporary for output buffering
|
||||
$this->raw($atom->getString());
|
||||
|
||||
break;
|
||||
case 'json':
|
||||
|
@ -22,7 +22,7 @@
|
||||
* @category Search
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2008-2009 StatusNet, Inc.
|
||||
* @copyright 2008-2010 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/
|
||||
*/
|
||||
@ -31,6 +31,8 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/apiprivateauth.php';
|
||||
|
||||
/**
|
||||
* Returns the top ten queries that are currently trending
|
||||
*
|
||||
@ -43,7 +45,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
* @see ApiAction
|
||||
*/
|
||||
|
||||
class TwitapitrendsAction extends ApiAction
|
||||
class ApiTrendsAction extends ApiPrivateAuthAction
|
||||
{
|
||||
|
||||
var $callback;
|
||||
@ -82,7 +84,7 @@ class TwitapitrendsAction extends ApiAction
|
||||
*/
|
||||
function showTrends()
|
||||
{
|
||||
$this->serverError(_('API method under construction.'), $code = 501);
|
||||
$this->serverError(_('API method under construction.'), 501);
|
||||
}
|
||||
|
||||
}
|
@ -113,7 +113,7 @@ class ApiUserShowAction extends ApiPrivateAuthAction
|
||||
|
||||
if ($this->format == 'xml') {
|
||||
$this->initDocument('xml');
|
||||
$this->showTwitterXmlUser($twitter_user);
|
||||
$this->showTwitterXmlUser($twitter_user, 'user', true);
|
||||
$this->endDocument('xml');
|
||||
} elseif ($this->format == 'json') {
|
||||
$this->initDocument('json');
|
||||
|
@ -103,7 +103,7 @@ class AvatarsettingsAction extends AccountSettingsAction
|
||||
|
||||
if (!$profile) {
|
||||
common_log_db_error($user, 'SELECT', __FILE__);
|
||||
$this->serverError(_('User without matching profile'));
|
||||
$this->serverError(_('User without matching profile.'));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -182,7 +182,7 @@ class AvatarsettingsAction extends AccountSettingsAction
|
||||
|
||||
if (!$profile) {
|
||||
common_log_db_error($user, 'SELECT', __FILE__);
|
||||
$this->serverError(_('User without matching profile'));
|
||||
$this->serverError(_('User without matching profile.'));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -301,6 +301,10 @@ class AvatarsettingsAction extends AccountSettingsAction
|
||||
$this->showForm($e->getMessage());
|
||||
return;
|
||||
}
|
||||
if ($imagefile === null) {
|
||||
$this->showForm(_('No file uploaded.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$cur = common_current_user();
|
||||
|
||||
|
@ -66,7 +66,7 @@ class BlockAction extends ProfileFormAction
|
||||
assert(!empty($cur)); // checked by parent
|
||||
|
||||
if ($cur->hasBlocked($this->profile)) {
|
||||
$this->clientError(_("You already blocked that user."));
|
||||
$this->clientError(_('You already blocked that user.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -87,13 +87,15 @@ class BlockAction extends ProfileFormAction
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
if ($this->arg('no')) {
|
||||
$this->returnToArgs();
|
||||
$this->returnToPrevious();
|
||||
} elseif ($this->arg('yes')) {
|
||||
$this->handlePost();
|
||||
$this->returnToArgs();
|
||||
$this->returnToPrevious();
|
||||
} else {
|
||||
$this->showPage();
|
||||
}
|
||||
} else {
|
||||
$this->showPage();
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,6 +120,12 @@ class BlockAction extends ProfileFormAction
|
||||
*/
|
||||
function areYouSureForm()
|
||||
{
|
||||
// @fixme if we ajaxify the confirmation form, skip the preview on ajax hits
|
||||
$profile = new ArrayWrapper(array($this->profile));
|
||||
$preview = new ProfileList($profile, $this);
|
||||
$preview->show();
|
||||
|
||||
|
||||
$id = $this->profile->id;
|
||||
$this->elementStart('form', array('id' => 'block-' . $id,
|
||||
'method' => 'post',
|
||||
@ -140,8 +148,20 @@ class BlockAction extends ProfileFormAction
|
||||
$this->hidden($k, $v);
|
||||
}
|
||||
}
|
||||
$this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not block this user"));
|
||||
$this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Block this user'));
|
||||
$this->submit('form_action-no',
|
||||
// TRANS: Button label on the user block form.
|
||||
_m('BUTTON','No'),
|
||||
'submit form_action-primary',
|
||||
'no',
|
||||
// TRANS: Submit button title for 'No' when blocking a user.
|
||||
_('Do not block this user'));
|
||||
$this->submit('form_action-yes',
|
||||
// TRANS: Button label on the user block form.
|
||||
_m('BUTTON','Yes'),
|
||||
'submit form_action-secondary',
|
||||
'yes',
|
||||
// TRANS: Submit button title for 'Yes' when blocking a user.
|
||||
_('Block this user'));
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
}
|
||||
@ -168,4 +188,45 @@ class BlockAction extends ProfileFormAction
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('form_action-yes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Override for form session token checks; on our first hit we're just
|
||||
* requesting confirmation, which doesn't need a token. We need to be
|
||||
* able to take regular GET requests from email!
|
||||
*
|
||||
* @throws ClientException if token is bad on POST request or if we have
|
||||
* confirmation parameters which could trigger something.
|
||||
*/
|
||||
function checkSessionToken()
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST' ||
|
||||
$this->arg('yes') ||
|
||||
$this->arg('no')) {
|
||||
|
||||
return parent::checkSessionToken();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we reached this form without returnto arguments, return to the
|
||||
* current user's subscription list.
|
||||
*
|
||||
* @return string URL
|
||||
*/
|
||||
function defaultReturnTo()
|
||||
{
|
||||
$user = common_current_user();
|
||||
if ($user) {
|
||||
return common_local_url('subscribers',
|
||||
array('nickname' => $user->nickname));
|
||||
} else {
|
||||
return common_local_url('public');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,8 @@ class BookmarkletAction extends NewnoticeAction
|
||||
{
|
||||
function showTitle()
|
||||
{
|
||||
$this->element('title', null, _('Post to ').common_config('site', 'name'));
|
||||
// TRANS: Title for mini-posting window loaded from bookmarklet.
|
||||
$this->element('title', null, sprintf(_('Post to %s'), common_config('site', 'name')));
|
||||
}
|
||||
|
||||
function showHeader()
|
||||
|
@ -87,10 +87,12 @@ class ConfirmaddressAction extends Action
|
||||
}
|
||||
$type = $confirm->address_type;
|
||||
if (!in_array($type, array('email', 'jabber', 'sms'))) {
|
||||
$this->serverError(sprintf(_('Unrecognized address type %s'), $type));
|
||||
// TRANS: Server error for an unknow address type, which can be 'email', 'jabber', or 'sms'.
|
||||
$this->serverError(sprintf(_('Unrecognized address type %s.'), $type));
|
||||
return;
|
||||
}
|
||||
if ($cur->$type == $confirm->address) {
|
||||
// TRANS: Client error for an already confirmed email/jabbel/sms address.
|
||||
$this->clientError(_('That address has already been confirmed.'));
|
||||
return;
|
||||
}
|
||||
|
@ -150,13 +150,17 @@ class DeleteapplicationAction extends Action
|
||||
'This will clear all data about the application from the '.
|
||||
'database, including all existing user connections.'));
|
||||
$this->submit('form_action-no',
|
||||
_('No'),
|
||||
// TRANS: Button label on the delete application form.
|
||||
_m('BUTTON','No'),
|
||||
'submit form_action-primary',
|
||||
'no',
|
||||
_("Do not delete this application"));
|
||||
// TRANS: Submit button title for 'No' when deleting an application.
|
||||
_('Do not delete this application'));
|
||||
$this->submit('form_action-yes',
|
||||
_('Yes'),
|
||||
// TRANS: Button label on the delete application form.
|
||||
_m('BUTTON','Yes'),
|
||||
'submit form_action-secondary',
|
||||
// TRANS: Submit button title for 'Yes' when deleting an application.
|
||||
'yes', _('Delete this application'));
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
|
@ -142,8 +142,20 @@ class DeletenoticeAction extends Action
|
||||
$this->hidden('token', common_session_token());
|
||||
$this->hidden('notice', $this->trimmed('notice'));
|
||||
$this->element('p', null, _('Are you sure you want to delete this notice?'));
|
||||
$this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not delete this notice"));
|
||||
$this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Delete this notice'));
|
||||
$this->submit('form_action-no',
|
||||
// TRANS: Button label on the delete notice form.
|
||||
_m('BUTTON','No'),
|
||||
'submit form_action-primary',
|
||||
'no',
|
||||
// TRANS: Submit button title for 'No' when deleting a notice.
|
||||
_("Do not delete this notice"));
|
||||
$this->submit('form_action-yes',
|
||||
// TRANS: Button label on the delete notice form.
|
||||
_m('BUTTON','Yes'),
|
||||
'submit form_action-secondary',
|
||||
'yes',
|
||||
// TRANS: Submit button title for 'Yes' when deleting a notice.
|
||||
_('Delete this notice'));
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
}
|
||||
|
@ -64,14 +64,14 @@ class DeleteuserAction extends ProfileFormAction
|
||||
assert(!empty($cur)); // checked by parent
|
||||
|
||||
if (!$cur->hasRight(Right::DELETEUSER)) {
|
||||
$this->clientError(_("You cannot delete users."));
|
||||
$this->clientError(_('You cannot delete users.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->user = User::staticGet('id', $this->profile->id);
|
||||
|
||||
if (empty($this->user)) {
|
||||
$this->clientError(_("You can only delete local users."));
|
||||
$this->clientError(_('You can only delete local users.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -92,10 +92,10 @@ class DeleteuserAction extends ProfileFormAction
|
||||
{
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
if ($this->arg('no')) {
|
||||
$this->returnToArgs();
|
||||
$this->returnToPrevious();
|
||||
} elseif ($this->arg('yes')) {
|
||||
$this->handlePost();
|
||||
$this->returnToArgs();
|
||||
$this->returnToPrevious();
|
||||
} else {
|
||||
$this->showPage();
|
||||
}
|
||||
@ -147,8 +147,20 @@ class DeleteuserAction extends ProfileFormAction
|
||||
}
|
||||
Event::handle('EndDeleteUserForm', array($this, $this->user));
|
||||
}
|
||||
$this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not block this user"));
|
||||
$this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Delete this user'));
|
||||
$this->submit('form_action-no',
|
||||
// TRANS: Button label on the delete user form.
|
||||
_m('BUTTON','No'),
|
||||
'submit form_action-primary',
|
||||
'no',
|
||||
// TRANS: Submit button title for 'No' when deleting a user.
|
||||
_('Do not block this user'));
|
||||
$this->submit('form_action-yes',
|
||||
// TRANS: Button label on the delete user form.
|
||||
_m('BUTTON','Yes'),
|
||||
'submit form_action-secondary',
|
||||
'yes',
|
||||
// TRANS: Submit button title for 'Yes' when deleting a user.
|
||||
_('Delete this user'));
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
}
|
||||
@ -162,7 +174,15 @@ class DeleteuserAction extends ProfileFormAction
|
||||
function handlePost()
|
||||
{
|
||||
if (Event::handle('StartDeleteUser', array($this, $this->user))) {
|
||||
$this->user->delete();
|
||||
// Mark the account as deleted and shove low-level deletion tasks
|
||||
// to background queues. Removing a lot of posts can take a while...
|
||||
if (!$this->user->hasRole(Profile_role::DELETED)) {
|
||||
$this->user->grantRole(Profile_role::DELETED);
|
||||
}
|
||||
|
||||
$qm = QueueManager::get();
|
||||
$qm->enqueue($this->user, 'deluser');
|
||||
|
||||
Event::handle('EndDeleteUser', array($this, $this->user));
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ class DesignadminpanelAction extends AdminPanelAction
|
||||
|
||||
function title()
|
||||
{
|
||||
// TRANS: Message used as title for design settings for the site.
|
||||
return _('Design');
|
||||
}
|
||||
|
||||
@ -125,9 +126,19 @@ class DesignadminpanelAction extends AdminPanelAction
|
||||
return;
|
||||
}
|
||||
|
||||
// check for an image upload
|
||||
// check for file uploads
|
||||
|
||||
$bgimage = $this->saveBackgroundImage();
|
||||
$customTheme = $this->saveCustomTheme();
|
||||
|
||||
$oldtheme = common_config('site', 'theme');
|
||||
if ($customTheme) {
|
||||
// This feels pretty hacky :D
|
||||
$this->args['theme'] = $customTheme;
|
||||
$themeChanged = true;
|
||||
} else {
|
||||
$themeChanged = ($this->trimmed('theme') != $oldtheme);
|
||||
}
|
||||
|
||||
static $settings = array('theme', 'logo');
|
||||
|
||||
@ -139,15 +150,13 @@ class DesignadminpanelAction extends AdminPanelAction
|
||||
|
||||
$this->validate($values);
|
||||
|
||||
$oldtheme = common_config('site', 'theme');
|
||||
|
||||
$config = new Config();
|
||||
|
||||
$config->query('BEGIN');
|
||||
|
||||
// Only update colors if the theme has not changed.
|
||||
|
||||
if ($oldtheme == $values['theme']) {
|
||||
if (!$themeChanged) {
|
||||
|
||||
$bgcolor = new WebColor($this->trimmed('design_background'));
|
||||
$ccolor = new WebColor($this->trimmed('design_content'));
|
||||
@ -189,6 +198,13 @@ class DesignadminpanelAction extends AdminPanelAction
|
||||
Config::save('design', 'backgroundimage', $bgimage);
|
||||
}
|
||||
|
||||
if (common_config('custom_css', 'enabled')) {
|
||||
$css = $this->arg('css');
|
||||
if ($css != common_config('custom_css', 'css')) {
|
||||
Config::save('custom_css', 'css', $css);
|
||||
}
|
||||
}
|
||||
|
||||
$config->query('COMMIT');
|
||||
}
|
||||
|
||||
@ -262,6 +278,33 @@ class DesignadminpanelAction extends AdminPanelAction
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the custom theme if the user uploaded one.
|
||||
*
|
||||
* @return mixed custom theme name, if succesful, or null if no theme upload.
|
||||
* @throws ClientException for invalid theme archives
|
||||
* @throws ServerException if trouble saving the theme files
|
||||
*/
|
||||
|
||||
function saveCustomTheme()
|
||||
{
|
||||
if (common_config('theme_upload', 'enabled') &&
|
||||
$_FILES['design_upload_theme']['error'] == UPLOAD_ERR_OK) {
|
||||
|
||||
$upload = ThemeUploader::fromUpload('design_upload_theme');
|
||||
$basedir = common_config('local', 'dir');
|
||||
if (empty($basedir)) {
|
||||
$basedir = INSTALLDIR . '/local';
|
||||
}
|
||||
$name = 'custom'; // @todo allow multiples, custom naming?
|
||||
$outdir = $basedir . '/theme/' . $name;
|
||||
$upload->extract($outdir);
|
||||
return $name;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to validate setting values
|
||||
*
|
||||
@ -272,11 +315,11 @@ class DesignadminpanelAction extends AdminPanelAction
|
||||
{
|
||||
if (!empty($values['logo']) &&
|
||||
!Validate::uri($values['logo'], array('allowed_schemes' => array('http', 'https')))) {
|
||||
$this->clientError(_("Invalid logo URL."));
|
||||
$this->clientError(_('Invalid logo URL.'));
|
||||
}
|
||||
|
||||
if (!in_array($values['theme'], Theme::listAvailable())) {
|
||||
$this->clientError(sprintf(_("Theme not available: %s"), $values['theme']));
|
||||
$this->clientError(sprintf(_("Theme not available: %s."), $values['theme']));
|
||||
}
|
||||
}
|
||||
|
||||
@ -370,7 +413,15 @@ class DesignAdminPanelForm extends AdminForm
|
||||
|
||||
function formData()
|
||||
{
|
||||
$this->showLogo();
|
||||
$this->showTheme();
|
||||
$this->showBackground();
|
||||
$this->showColors();
|
||||
$this->showAdvanced();
|
||||
}
|
||||
|
||||
function showLogo()
|
||||
{
|
||||
$this->out->elementStart('fieldset', array('id' => 'settings_design_logo'));
|
||||
$this->out->element('legend', null, _('Change logo'));
|
||||
|
||||
@ -383,6 +434,11 @@ class DesignAdminPanelForm extends AdminForm
|
||||
$this->out->elementEnd('ul');
|
||||
|
||||
$this->out->elementEnd('fieldset');
|
||||
|
||||
}
|
||||
|
||||
function showTheme()
|
||||
{
|
||||
$this->out->elementStart('fieldset', array('id' => 'settings_design_theme'));
|
||||
$this->out->element('legend', null, _('Change theme'));
|
||||
|
||||
@ -406,10 +462,23 @@ class DesignAdminPanelForm extends AdminForm
|
||||
false, $this->value('theme'));
|
||||
$this->unli();
|
||||
|
||||
if (common_config('theme_upload', 'enabled')) {
|
||||
$this->li();
|
||||
$this->out->element('label', array('for' => 'design_upload_theme'), _('Custom theme'));
|
||||
$this->out->element('input', array('id' => 'design_upload_theme',
|
||||
'name' => 'design_upload_theme',
|
||||
'type' => 'file'));
|
||||
$this->out->element('p', 'form_guide', _('You can upload a custom StatusNet theme as a .ZIP archive.'));
|
||||
$this->unli();
|
||||
}
|
||||
|
||||
$this->out->elementEnd('ul');
|
||||
|
||||
$this->out->elementEnd('fieldset');
|
||||
}
|
||||
|
||||
function showBackground()
|
||||
{
|
||||
$design = $this->out->design;
|
||||
|
||||
$this->out->elementStart('fieldset', array('id' =>
|
||||
@ -454,6 +523,7 @@ class DesignAdminPanelForm extends AdminForm
|
||||
|
||||
$this->out->element('label', array('for' => 'design_background-image_on',
|
||||
'class' => 'radio'),
|
||||
// TRANS: Used as radio button label to add a background image.
|
||||
_('On'));
|
||||
|
||||
$attrs = array('name' => 'design_background-image_onoff',
|
||||
@ -470,6 +540,7 @@ class DesignAdminPanelForm extends AdminForm
|
||||
|
||||
$this->out->element('label', array('for' => 'design_background-image_off',
|
||||
'class' => 'radio'),
|
||||
// TRANS: Used as radio button label to not add a background image.
|
||||
_('Off'));
|
||||
$this->out->element('p', 'form_guide', _('Turn background image on or off.'));
|
||||
$this->unli();
|
||||
@ -483,6 +554,11 @@ class DesignAdminPanelForm extends AdminForm
|
||||
|
||||
$this->out->elementEnd('ul');
|
||||
$this->out->elementEnd('fieldset');
|
||||
}
|
||||
|
||||
function showColors()
|
||||
{
|
||||
$design = $this->out->design;
|
||||
|
||||
$this->out->elementStart('fieldset', array('id' => 'settings_design_color'));
|
||||
$this->out->element('legend', null, _('Change colours'));
|
||||
@ -490,6 +566,7 @@ class DesignAdminPanelForm extends AdminForm
|
||||
$this->out->elementStart('ul', 'form_data');
|
||||
|
||||
try {
|
||||
// @fixme avoid loop unrolling in non-performance-critical contexts like this
|
||||
|
||||
$bgcolor = new WebColor($design->backgroundcolor);
|
||||
|
||||
@ -557,6 +634,7 @@ class DesignAdminPanelForm extends AdminForm
|
||||
$this->unli();
|
||||
|
||||
} catch (WebColorException $e) {
|
||||
// @fixme normalize them individually!
|
||||
common_log(LOG_ERR, 'Bad color values in site design: ' .
|
||||
$e->getMessage());
|
||||
}
|
||||
@ -566,6 +644,27 @@ class DesignAdminPanelForm extends AdminForm
|
||||
$this->out->elementEnd('ul');
|
||||
}
|
||||
|
||||
function showAdvanced()
|
||||
{
|
||||
if (common_config('custom_css', 'enabled')) {
|
||||
$this->out->elementStart('fieldset', array('id' => 'settings_design_advanced'));
|
||||
$this->out->element('legend', null, _('Advanced'));
|
||||
$this->out->elementStart('ul', 'form_data');
|
||||
|
||||
$this->li();
|
||||
$this->out->element('label', array('for' => 'css'), _('Custom CSS'));
|
||||
$this->out->element('textarea', array('name' => 'css',
|
||||
'id' => 'css',
|
||||
'cols' => '50',
|
||||
'rows' => '10'),
|
||||
strval(common_config('custom_css', 'css')));
|
||||
$this->unli();
|
||||
|
||||
$this->out->elementEnd('fieldset');
|
||||
$this->out->elementEnd('ul');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action elements
|
||||
*
|
||||
|
@ -71,7 +71,7 @@ class DisfavorAction extends Action
|
||||
$notice = Notice::staticGet($id);
|
||||
$token = $this->trimmed('token-'.$notice->id);
|
||||
if (!$token || $token != common_session_token()) {
|
||||
$this->clientError(_("There was a problem with your session token. Try again, please."));
|
||||
$this->clientError(_('There was a problem with your session token. Try again, please.'));
|
||||
return;
|
||||
}
|
||||
$fave = new Fave();
|
||||
|
@ -13,7 +13,7 @@
|
||||
* @link http://status.net/
|
||||
*
|
||||
* StatusNet - the distributed open-source microblogging tool
|
||||
* Copyright (C) 2008, 2009, StatusNet, Inc.
|
||||
* Copyright (C) 2008-2010, 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
|
||||
@ -168,15 +168,29 @@ class DocAction extends Action
|
||||
|
||||
function getFilename()
|
||||
{
|
||||
$localDef = null;
|
||||
$local = null;
|
||||
|
||||
$site = StatusNet::currentSite();
|
||||
|
||||
if (!empty($site) && file_exists(INSTALLDIR.'/local/doc-src/'.$site.'/'.$this->title)) {
|
||||
$localDef = INSTALLDIR.'/local/doc-src/'.$site.'/'.$this->title;
|
||||
|
||||
$local = glob(INSTALLDIR.'/local/doc-src/'.$site.'/'.$this->title.'.*');
|
||||
if ($local === false) {
|
||||
// Some systems return false, others array(), if dir didn't exist.
|
||||
$local = array();
|
||||
}
|
||||
} else {
|
||||
if (file_exists(INSTALLDIR.'/local/doc-src/'.$this->title)) {
|
||||
$localDef = INSTALLDIR.'/local/doc-src/'.$this->title;
|
||||
}
|
||||
|
||||
$local = glob(INSTALLDIR.'/local/doc-src/'.$this->title.'.*');
|
||||
if ($local === false) {
|
||||
// Some systems return false, others array(), if dir didn't exist.
|
||||
$local = array();
|
||||
}
|
||||
}
|
||||
|
||||
if (count($local) || isset($localDef)) {
|
||||
return $this->negotiateLanguage($local, $localDef);
|
||||
|
@ -57,6 +57,7 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
|
||||
function title()
|
||||
{
|
||||
// TRANS: Title for e-mail settings.
|
||||
return _('Email settings');
|
||||
}
|
||||
|
||||
@ -68,6 +69,10 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
|
||||
function getInstructions()
|
||||
{
|
||||
// XXX: For consistency of parameters in messages, this should be a
|
||||
// regular parameters, replaced with sprintf().
|
||||
// TRANS: E-mail settings page instructions.
|
||||
// TRANS: %%site.name%% is the name of the site.
|
||||
return _('Manage how you get email from %%site.name%%.');
|
||||
}
|
||||
|
||||
@ -97,102 +102,126 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
common_local_url('emailsettings')));
|
||||
$this->elementStart('fieldset');
|
||||
$this->elementStart('fieldset', array('id' => 'settings_email_address'));
|
||||
$this->element('legend', null, _('Address'));
|
||||
// TRANS: Form legend for e-mail settings form.
|
||||
$this->element('legend', null, _('Email address'));
|
||||
$this->hidden('token', common_session_token());
|
||||
|
||||
if ($user->email) {
|
||||
$this->element('p', array('id' => 'form_confirmed'), $user->email);
|
||||
// TRANS: Form note in e-mail settings form.
|
||||
$this->element('p', array('class' => 'form_note'), _('Current confirmed email address.'));
|
||||
$this->hidden('email', $user->email);
|
||||
$this->submit('remove', _('Remove'));
|
||||
// TRANS: Button label to remove a confirmed e-mail address.
|
||||
$this->submit('remove', _m('BUTTON','Remove'));
|
||||
} else {
|
||||
$confirm = $this->getConfirmation();
|
||||
if ($confirm) {
|
||||
$this->element('p', array('id' => 'form_unconfirmed'), $confirm->address);
|
||||
// TRANS: Form note in e-mail settings form.
|
||||
$this->element('p', array('class' => 'form_note'),
|
||||
_('Awaiting confirmation on this address. '.
|
||||
'Check your inbox (and spam box!) for a message '.
|
||||
'with further instructions.'));
|
||||
$this->hidden('email', $confirm->address);
|
||||
$this->submit('cancel', _('Cancel'));
|
||||
// TRANS: Button label to cancel an e-mail address confirmation procedure.
|
||||
$this->submit('cancel', _m('BUTTON','Cancel'));
|
||||
} else {
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
// TRANS: Field label for e-mail address input in e-mail settings form.
|
||||
$this->input('email', _('Email address'),
|
||||
($this->arg('email')) ? $this->arg('email') : null,
|
||||
// TRANS: Instructions for e-mail address input form.
|
||||
_('Email address, like "UserName@example.org"'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
$this->submit('add', _('Add'));
|
||||
// TRANS: Button label for adding an e-mail address in e-mail settings form.
|
||||
$this->submit('add', _m('BUTTON','Add'));
|
||||
}
|
||||
}
|
||||
$this->elementEnd('fieldset');
|
||||
|
||||
if (common_config('emailpost', 'enabled') && $user->email) {
|
||||
$this->elementStart('fieldset', array('id' => 'settings_email_incoming'));
|
||||
// TRANS: Form legend for incoming e-mail settings form.
|
||||
$this->element('legend', null, _('Incoming email'));
|
||||
if ($user->incomingemail) {
|
||||
$this->elementStart('p');
|
||||
$this->element('span', 'address', $user->incomingemail);
|
||||
// XXX: Looks a little awkward in the UI.
|
||||
// Something like "xxxx@identi.ca Send email ..". Needs improvement.
|
||||
$this->element('span', 'input_instructions',
|
||||
// TRANS: Form instructions for incoming e-mail form in e-mail settings.
|
||||
_('Send email to this address to post new notices.'));
|
||||
$this->elementEnd('p');
|
||||
$this->submit('removeincoming', _('Remove'));
|
||||
// TRANS: Button label for removing a set sender e-mail address to post notices from.
|
||||
$this->submit('removeincoming', _m('BUTTON','Remove'));
|
||||
}
|
||||
|
||||
$this->elementStart('p');
|
||||
$this->element('span', 'input_instructions',
|
||||
// TRANS: Instructions for incoming e-mail address input form.
|
||||
_('Make a new email address for posting to; '.
|
||||
'cancels the old one.'));
|
||||
$this->elementEnd('p');
|
||||
$this->submit('newincoming', _('New'));
|
||||
// TRANS: Button label for adding an e-mail address to send notices from.
|
||||
$this->submit('newincoming', _m('BUTTON','New'));
|
||||
$this->elementEnd('fieldset');
|
||||
}
|
||||
|
||||
$this->elementStart('fieldset', array('id' => 'settings_email_preferences'));
|
||||
$this->element('legend', null, _('Preferences'));
|
||||
// TRANS: Form legend for e-mail preferences form.
|
||||
$this->element('legend', null, _('Email preferences'));
|
||||
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('emailnotifysub',
|
||||
// TRANS: Checkbox label in e-mail preferences form.
|
||||
_('Send me notices of new subscriptions through email.'),
|
||||
$user->emailnotifysub);
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('emailnotifyfav',
|
||||
// TRANS: Checkbox label in e-mail preferences form.
|
||||
_('Send me email when someone '.
|
||||
'adds my notice as a favorite.'),
|
||||
$user->emailnotifyfav);
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('emailnotifymsg',
|
||||
// TRANS: Checkbox label in e-mail preferences form.
|
||||
_('Send me email when someone sends me a private message.'),
|
||||
$user->emailnotifymsg);
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('emailnotifyattn',
|
||||
// TRANS: Checkbox label in e-mail preferences form.
|
||||
_('Send me email when someone sends me an "@-reply".'),
|
||||
$user->emailnotifyattn);
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('emailnotifynudge',
|
||||
// TRANS: Checkbox label in e-mail preferences form.
|
||||
_('Allow friends to nudge me and send me an email.'),
|
||||
$user->emailnotifynudge);
|
||||
$this->elementEnd('li');
|
||||
if (common_config('emailpost', 'enabled')) {
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('emailpost',
|
||||
// TRANS: Checkbox label in e-mail preferences form.
|
||||
_('I want to post notices by email.'),
|
||||
$user->emailpost);
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('emailmicroid',
|
||||
// TRANS: Checkbox label in e-mail preferences form.
|
||||
_('Publish a MicroID for my email address.'),
|
||||
$user->emailmicroid);
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
$this->submit('save', _('Save'));
|
||||
// TRANS: Button label to save e-mail preferences.
|
||||
$this->submit('save', _m('BUTTON','Save'));
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
@ -253,6 +282,7 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
} else if ($this->arg('newincoming')) {
|
||||
$this->newIncoming();
|
||||
} else {
|
||||
// TRANS: Message given submitting a form with an unknown action in e-mail settings.
|
||||
$this->showForm(_('Unexpected form submission.'));
|
||||
}
|
||||
}
|
||||
@ -293,13 +323,15 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
|
||||
if ($result === false) {
|
||||
common_log_db_error($user, 'UPDATE', __FILE__);
|
||||
// TRANS: Server error thrown on database error updating e-mail preferences.
|
||||
$this->serverError(_('Couldn\'t update user.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$user->query('COMMIT');
|
||||
|
||||
$this->showForm(_('Preferences saved.'), true);
|
||||
// TRANS: Confirmation message for successful e-mail preferences save.
|
||||
$this->showForm(_('Email preferences saved.'), true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -317,6 +349,7 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
// Some validation
|
||||
|
||||
if (!$email) {
|
||||
// TRANS: Message given saving e-mail address without having provided one.
|
||||
$this->showForm(_('No email address.'));
|
||||
return;
|
||||
}
|
||||
@ -324,16 +357,20 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
$email = common_canonical_email($email);
|
||||
|
||||
if (!$email) {
|
||||
// TRANS: Message given saving e-mail address that cannot be normalised.
|
||||
$this->showForm(_('Cannot normalize that email address'));
|
||||
return;
|
||||
}
|
||||
if (!Validate::email($email, common_config('email', 'check_domain'))) {
|
||||
// TRANS: Message given saving e-mail address that not valid.
|
||||
$this->showForm(_('Not a valid email address.'));
|
||||
return;
|
||||
} else if ($user->email == $email) {
|
||||
// TRANS: Message given saving e-mail address that is already set.
|
||||
$this->showForm(_('That is already your email address.'));
|
||||
return;
|
||||
} else if ($this->emailExists($email)) {
|
||||
// TRANS: Message given saving e-mail address that is already set for another user.
|
||||
$this->showForm(_('That email address already belongs '.
|
||||
'to another user.'));
|
||||
return;
|
||||
@ -350,12 +387,14 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
|
||||
if ($result === false) {
|
||||
common_log_db_error($confirm, 'INSERT', __FILE__);
|
||||
// TRANS: Server error thrown on database error adding e-mail confirmation code.
|
||||
$this->serverError(_('Couldn\'t insert confirmation code.'));
|
||||
return;
|
||||
}
|
||||
|
||||
mail_confirm_address($user, $confirm->code, $user->nickname, $email);
|
||||
|
||||
// TRANS: Message given saving valid e-mail address that is to be confirmed.
|
||||
$msg = _('A confirmation code was sent to the email address you added. '.
|
||||
'Check your inbox (and spam box!) for the code and instructions '.
|
||||
'on how to use it.');
|
||||
@ -376,11 +415,13 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
$confirm = $this->getConfirmation();
|
||||
|
||||
if (!$confirm) {
|
||||
// TRANS: Message given canceling e-mail address confirmation that is not pending.
|
||||
$this->showForm(_('No pending confirmation to cancel.'));
|
||||
return;
|
||||
}
|
||||
if ($confirm->address != $email) {
|
||||
$this->showForm(_('That is the wrong IM address.'));
|
||||
// TRANS: Message given canceling e-mail address confirmation for the wrong e-mail address.
|
||||
$this->showForm(_('That is the wrong email address.'));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -388,11 +429,13 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
|
||||
if (!$result) {
|
||||
common_log_db_error($confirm, 'DELETE', __FILE__);
|
||||
// TRANS: Server error thrown on database error canceling e-mail address confirmation.
|
||||
$this->serverError(_('Couldn\'t delete email confirmation.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->showForm(_('Confirmation cancelled.'), true);
|
||||
// TRANS: Message given after successfully canceling e-mail address confirmation.
|
||||
$this->showForm(_('Email confirmation cancelled.'), true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -410,6 +453,8 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
// Maybe an old tab open...?
|
||||
|
||||
if ($user->email != $email) {
|
||||
// TRANS: Message given trying to remove an e-mail address that is not
|
||||
// TRANS: registered for the active user.
|
||||
$this->showForm(_('That is not your email address.'));
|
||||
return;
|
||||
}
|
||||
@ -424,12 +469,14 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
|
||||
if (!$result) {
|
||||
common_log_db_error($user, 'UPDATE', __FILE__);
|
||||
// TRANS: Server error thrown on database error removing a registered e-mail address.
|
||||
$this->serverError(_('Couldn\'t update user.'));
|
||||
return;
|
||||
}
|
||||
$user->query('COMMIT');
|
||||
|
||||
$this->showForm(_('The address was removed.'), true);
|
||||
// TRANS: Message given after successfully removing a registered e-mail address.
|
||||
$this->showForm(_('The email address was removed.'), true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -453,9 +500,11 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
|
||||
if (!$user->updateKeys($orig)) {
|
||||
common_log_db_error($user, 'UPDATE', __FILE__);
|
||||
// TRANS: Server error thrown on database error removing incoming e-mail address.
|
||||
$this->serverError(_("Couldn't update user record."));
|
||||
}
|
||||
|
||||
// TRANS: Message given after successfully removing an incoming e-mail address.
|
||||
$this->showForm(_('Incoming email address removed.'), true);
|
||||
}
|
||||
|
||||
@ -475,9 +524,11 @@ class EmailsettingsAction extends AccountSettingsAction
|
||||
|
||||
if (!$user->updateKeys($orig)) {
|
||||
common_log_db_error($user, 'UPDATE', __FILE__);
|
||||
// TRANS: Server error thrown on database error adding incoming e-mail address.
|
||||
$this->serverError(_("Couldn't update user record."));
|
||||
}
|
||||
|
||||
// TRANS: Message given after successfully adding an incoming e-mail address.
|
||||
$this->showForm(_('New incoming email address added.'), true);
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ class FavorAction extends Action
|
||||
$notice = Notice::staticGet($id);
|
||||
$token = $this->trimmed('token-'.$notice->id);
|
||||
if (!$token || $token != common_session_token()) {
|
||||
$this->clientError(_("There was a problem with your session token. Try again, please."));
|
||||
$this->clientError(_('There was a problem with your session token. Try again, please.'));
|
||||
return;
|
||||
}
|
||||
if ($user->hasFave($notice)) {
|
||||
|
@ -89,7 +89,7 @@ class FavoritesrssAction extends Rss10Action
|
||||
function getNotices($limit=0)
|
||||
{
|
||||
$user = $this->user;
|
||||
$notice = $user->favoriteNotices(0, $limit);
|
||||
$notice = $user->favoriteNotices(false, 0, $limit);
|
||||
$notices = array();
|
||||
while ($notice->fetch()) {
|
||||
$notices[] = clone($notice);
|
||||
|
@ -135,7 +135,7 @@ class FinishremotesubscribeAction extends Action
|
||||
$service->getServiceURI(OMB_ENDPOINT_UPDATEPROFILE);
|
||||
|
||||
if (!$remote->update($orig_remote)) {
|
||||
$this->serverError(_('Error updating remote profile'));
|
||||
$this->serverError(_('Error updating remote profile.'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,9 @@ class FoafAction extends Action
|
||||
// Would be nice to tell if they were a Person or not (e.g. a #person usertag?)
|
||||
$this->elementStart('Agent', array('rdf:about' =>
|
||||
$this->user->uri));
|
||||
if ($this->user->email) {
|
||||
$this->element('mbox_sha1sum', null, sha1('mailto:' . $this->user->email));
|
||||
}
|
||||
if ($this->profile->fullname) {
|
||||
$this->element('name', null, $this->profile->fullname);
|
||||
}
|
||||
@ -126,7 +128,7 @@ class FoafAction extends Action
|
||||
$this->element('geo:lat', null, $location->lat);
|
||||
}
|
||||
if ($location->lon) {
|
||||
$this->element('geo:long', null, $location->lat);
|
||||
$this->element('geo:long', null, $location->lon);
|
||||
}
|
||||
if ($location->getURL()) {
|
||||
$this->element('page', array('rdf:resource'=>$location->getURL()));
|
||||
@ -152,7 +154,9 @@ class FoafAction extends Action
|
||||
}
|
||||
|
||||
$person = $this->showMicrobloggingAccount($this->profile,
|
||||
common_root_url(), $this->user->uri, false);
|
||||
common_root_url(), $this->user->uri,
|
||||
/*$fetchSubscriptions*/true,
|
||||
/*$isSubscriber*/false);
|
||||
|
||||
// Get people who subscribe to user
|
||||
|
||||
@ -162,40 +166,29 @@ class FoafAction extends Action
|
||||
|
||||
if ($sub->find()) {
|
||||
while ($sub->fetch()) {
|
||||
if ($sub->token) {
|
||||
$other = Remote_profile::staticGet('id', $sub->subscriber);
|
||||
$profile = Profile::staticGet('id', $sub->subscriber);
|
||||
} else {
|
||||
$other = User::staticGet('id', $sub->subscriber);
|
||||
$profile = Profile::staticGet('id', $sub->subscriber);
|
||||
}
|
||||
if (!$other) {
|
||||
if (empty($profile)) {
|
||||
common_debug('Got a bad subscription: '.print_r($sub,true));
|
||||
continue;
|
||||
}
|
||||
if (array_key_exists($other->uri, $person)) {
|
||||
$person[$other->uri][0] = BOTH;
|
||||
$user = $profile->getUser();
|
||||
$other_uri = $profile->getUri();
|
||||
if (array_key_exists($other_uri, $person)) {
|
||||
$person[$other_uri][0] = BOTH;
|
||||
} else {
|
||||
$person[$other->uri] = array(LISTENER,
|
||||
$other->id,
|
||||
$person[$other_uri] = array(LISTENER,
|
||||
$profile->id,
|
||||
$profile->nickname,
|
||||
(empty($sub->token)) ? 'User' : 'Remote_profile');
|
||||
$user ? 'local' : 'remote');
|
||||
}
|
||||
$other->free();
|
||||
$other = null;
|
||||
unset($other);
|
||||
$profile->free();
|
||||
$profile = null;
|
||||
unset($profile);
|
||||
}
|
||||
}
|
||||
|
||||
$sub->free();
|
||||
$sub = null;
|
||||
unset($sub);
|
||||
|
||||
foreach ($person as $uri => $p) {
|
||||
list($type, $id, $nickname, $cls) = $p;
|
||||
list($type, $id, $nickname, $local) = $p;
|
||||
if ($type == BOTH) {
|
||||
$this->element('knows', array('rdf:resource' => $uri));
|
||||
}
|
||||
@ -206,8 +199,8 @@ class FoafAction extends Action
|
||||
|
||||
foreach ($person as $uri => $p) {
|
||||
$foaf_url = null;
|
||||
list($type, $id, $nickname, $cls) = $p;
|
||||
if ($cls == 'User') {
|
||||
list($type, $id, $nickname, $local) = $p;
|
||||
if ($local == 'local') {
|
||||
$foaf_url = common_local_url('foaf', array('nickname' => $nickname));
|
||||
}
|
||||
$profile = Profile::staticGet($id);
|
||||
@ -216,9 +209,10 @@ class FoafAction extends Action
|
||||
$this->element('knows', array('rdf:resource' => $this->user->uri));
|
||||
}
|
||||
$this->showMicrobloggingAccount($profile,
|
||||
($cls == 'User') ? common_root_url() : null,
|
||||
($local == 'local') ? common_root_url() : null,
|
||||
$uri,
|
||||
true);
|
||||
/*$fetchSubscriptions*/false,
|
||||
/*$isSubscriber*/($type == LISTENER || $type == BOTH));
|
||||
if ($foaf_url) {
|
||||
$this->element('rdfs:seeAlso', array('rdf:resource' => $foaf_url));
|
||||
}
|
||||
@ -243,7 +237,21 @@ class FoafAction extends Action
|
||||
$this->elementEnd('PersonalProfileDocument');
|
||||
}
|
||||
|
||||
function showMicrobloggingAccount($profile, $service=null, $useruri=null, $isSubscriber=false)
|
||||
/**
|
||||
* Output FOAF <account> bit for the given profile.
|
||||
*
|
||||
* @param Profile $profile
|
||||
* @param mixed $service Root URL of this StatusNet instance for a local
|
||||
* user, otherwise null.
|
||||
* @param mixed $useruri URI string for the referenced profile..
|
||||
* @param boolean $fetchSubscriptions Should we load and list all their subscriptions?
|
||||
* @param boolean $isSubscriber if not fetching subs, we can still mark the user as following the current page.
|
||||
*
|
||||
* @return array if $fetchSubscribers is set, return a list of info on those
|
||||
* subscriptions.
|
||||
*/
|
||||
|
||||
function showMicrobloggingAccount($profile, $service=null, $useruri=null, $fetchSubscriptions=false, $isSubscriber=false)
|
||||
{
|
||||
$attr = array();
|
||||
if ($useruri) {
|
||||
@ -251,7 +259,7 @@ class FoafAction extends Action
|
||||
}
|
||||
|
||||
// Their account
|
||||
$this->elementStart('holdsAccount');
|
||||
$this->elementStart('account');
|
||||
$this->elementStart('OnlineAccount', $attr);
|
||||
if ($service) {
|
||||
$this->element('accountServiceHomepage', array('rdf:resource' =>
|
||||
@ -265,9 +273,7 @@ class FoafAction extends Action
|
||||
|
||||
$person = array();
|
||||
|
||||
if ($isSubscriber) {
|
||||
$this->element('sioc:follows', array('rdf:resource'=>$this->user->uri . '#acct'));
|
||||
} else {
|
||||
if ($fetchSubscriptions) {
|
||||
// Get people user is subscribed to
|
||||
$sub = new Subscription();
|
||||
$sub->subscriber = $profile->id;
|
||||
@ -275,38 +281,30 @@ class FoafAction extends Action
|
||||
|
||||
if ($sub->find()) {
|
||||
while ($sub->fetch()) {
|
||||
if (!empty($sub->token)) {
|
||||
$other = Remote_profile::staticGet('id', $sub->subscribed);
|
||||
$profile = Profile::staticGet('id', $sub->subscribed);
|
||||
} else {
|
||||
$other = User::staticGet('id', $sub->subscribed);
|
||||
$profile = Profile::staticGet('id', $sub->subscribed);
|
||||
}
|
||||
if (empty($other)) {
|
||||
if (empty($profile)) {
|
||||
common_debug('Got a bad subscription: '.print_r($sub,true));
|
||||
continue;
|
||||
}
|
||||
$this->element('sioc:follows', array('rdf:resource' => $other->uri.'#acct'));
|
||||
$person[$other->uri] = array(LISTENEE,
|
||||
$other->id,
|
||||
$user = $profile->getUser();
|
||||
$other_uri = $profile->getUri();
|
||||
$this->element('sioc:follows', array('rdf:resource' => $other_uri.'#acct'));
|
||||
$person[$other_uri] = array(LISTENEE,
|
||||
$profile->id,
|
||||
$profile->nickname,
|
||||
(empty($sub->token)) ? 'User' : 'Remote_profile');
|
||||
$other->free();
|
||||
$other = null;
|
||||
unset($other);
|
||||
$profile->free();
|
||||
$profile = null;
|
||||
$user ? 'local' : 'remote');
|
||||
unset($profile);
|
||||
}
|
||||
}
|
||||
|
||||
$sub->free();
|
||||
$sub = null;
|
||||
unset($sub);
|
||||
} else if ($isSubscriber) {
|
||||
// Just declare that they follow the user whose FOAF we're showing.
|
||||
$this->element('sioc:follows', array('rdf:resource' => $this->user->uri . '#acct'));
|
||||
}
|
||||
|
||||
$this->elementEnd('OnlineAccount');
|
||||
$this->elementEnd('holdsAccount');
|
||||
$this->elementEnd('account');
|
||||
|
||||
return $person;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ class FoafGroupAction extends Action
|
||||
return false;
|
||||
}
|
||||
|
||||
$local = Local_group::staticGet('nickname', $nickname);
|
||||
$local = Local_group::staticGet('nickname', $this->nickname);
|
||||
|
||||
if (!$local) {
|
||||
$this->clientError(_('No such group.'), 404);
|
||||
@ -126,7 +126,8 @@ class FoafGroupAction extends Action
|
||||
while ($members->fetch()) {
|
||||
$member_uri = common_local_url('userbyid', array('id'=>$members->id));
|
||||
$member_details[$member_uri] = array(
|
||||
'nickname' => $members->nickname
|
||||
'nickname' => $members->nickname,
|
||||
'is_admin' => false,
|
||||
);
|
||||
$this->element('member', array('rdf:resource' => $member_uri));
|
||||
}
|
||||
@ -146,7 +147,7 @@ class FoafGroupAction extends Action
|
||||
{
|
||||
$this->elementStart('Agent', array('rdf:about' => $uri));
|
||||
$this->element('nick', null, $details['nickname']);
|
||||
$this->elementStart('holdsAccount');
|
||||
$this->elementStart('account');
|
||||
$this->elementStart('sioc:User', array('rdf:about'=>$uri.'#acct'));
|
||||
$this->elementStart('sioc:has_function');
|
||||
$this->elementStart('statusnet:GroupAdminRole');
|
||||
@ -154,7 +155,7 @@ class FoafGroupAction extends Action
|
||||
$this->elementEnd('statusnet:GroupAdminRole');
|
||||
$this->elementEnd('sioc:has_function');
|
||||
$this->elementEnd('sioc:User');
|
||||
$this->elementEnd('holdsAccount');
|
||||
$this->elementEnd('account');
|
||||
$this->elementEnd('Agent');
|
||||
}
|
||||
else
|
||||
|
@ -37,6 +37,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
* @category Action
|
||||
* @package StatusNet
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
99
actions/grantrole.php
Normal file
99
actions/grantrole.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Action class to sandbox an abusive user
|
||||
*
|
||||
* 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 Action
|
||||
* @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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sandbox a user.
|
||||
*
|
||||
* @category Action
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
class GrantRoleAction extends ProfileFormAction
|
||||
{
|
||||
/**
|
||||
* Check parameters
|
||||
*
|
||||
* @param array $args action arguments (URL, GET, POST)
|
||||
*
|
||||
* @return boolean success flag
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
if (!parent::prepare($args)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->role = $this->arg('role');
|
||||
if (!Profile_role::isValid($this->role)) {
|
||||
$this->clientError(_('Invalid role.'));
|
||||
return false;
|
||||
}
|
||||
if (!Profile_role::isSettable($this->role)) {
|
||||
$this->clientError(_('This role is reserved and cannot be set.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$cur = common_current_user();
|
||||
|
||||
assert(!empty($cur)); // checked by parent
|
||||
|
||||
if (!$cur->hasRight(Right::GRANTROLE)) {
|
||||
$this->clientError(_('You cannot grant user roles on this site.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(!empty($this->profile)); // checked by parent
|
||||
|
||||
if ($this->profile->hasRole($this->role)) {
|
||||
$this->clientError(_('User already has this role.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sandbox a user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handlePost()
|
||||
{
|
||||
$this->profile->grantRole($this->role);
|
||||
}
|
||||
}
|
@ -41,7 +41,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
class GroupblockAction extends Action
|
||||
class GroupblockAction extends RedirectingAction
|
||||
{
|
||||
var $profile = null;
|
||||
var $group = null;
|
||||
@ -117,9 +117,7 @@ class GroupblockAction extends Action
|
||||
parent::handle($args);
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
if ($this->arg('no')) {
|
||||
common_redirect(common_local_url('groupmembers',
|
||||
array('nickname' => $this->group->nickname)),
|
||||
303);
|
||||
$this->returnToPrevious();
|
||||
} elseif ($this->arg('yes')) {
|
||||
$this->blockProfile();
|
||||
} elseif ($this->arg('blockto')) {
|
||||
@ -175,8 +173,20 @@ class GroupblockAction extends Action
|
||||
$this->hidden($k, $v);
|
||||
}
|
||||
}
|
||||
$this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not block this user from this group"));
|
||||
$this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Block this user from this group'));
|
||||
$this->submit('form_action-no',
|
||||
// TRANS: Button label on the form to block a user from a group.
|
||||
_m('BUTTON','No'),
|
||||
'submit form_action-primary',
|
||||
'no',
|
||||
// TRANS: Submit button title for 'No' when blocking a user from a group.
|
||||
_('Do not block this user from this group'));
|
||||
$this->submit('form_action-yes',
|
||||
// TRANS: Button label on the form to block a user from a group.
|
||||
_m('BUTTON','Yes'),
|
||||
'submit form_action-secondary',
|
||||
'yes',
|
||||
// TRANS: Submit button title for 'Yes' when blocking a user from a group.
|
||||
_('Block this user from this group'));
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
}
|
||||
@ -197,22 +207,26 @@ class GroupblockAction extends Action
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now, gotta figure where we go back to
|
||||
foreach ($this->args as $k => $v) {
|
||||
if ($k == 'returnto-action') {
|
||||
$action = $v;
|
||||
} elseif (substr($k, 0, 9) == 'returnto-') {
|
||||
$args[substr($k, 9)] = $v;
|
||||
}
|
||||
$this->returnToPrevious();
|
||||
}
|
||||
|
||||
/**
|
||||
* If we reached this form without returnto arguments, default to
|
||||
* the top of the group's member list.
|
||||
*
|
||||
* @return string URL
|
||||
*/
|
||||
function defaultReturnTo()
|
||||
{
|
||||
return common_local_url('groupmembers',
|
||||
array('nickname' => $this->group->nickname));
|
||||
}
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
$this->autofocus('form_action-yes');
|
||||
}
|
||||
|
||||
if ($action) {
|
||||
common_redirect(common_local_url($action, $args), 303);
|
||||
} else {
|
||||
common_redirect(common_local_url('groupmembers',
|
||||
array('nickname' => $this->group->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,13 +205,13 @@ class GroupMemberListItem extends ProfileListItem
|
||||
!$this->profile->isAdmin($this->group)) {
|
||||
$this->out->elementStart('li', 'entity_make_admin');
|
||||
$maf = new MakeAdminForm($this->out, $this->profile, $this->group,
|
||||
array('action' => 'groupmembers',
|
||||
'nickname' => $this->group->nickname));
|
||||
$this->returnToArgs());
|
||||
$maf->show();
|
||||
$this->out->elementEnd('li');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function showGroupBlockForm()
|
||||
{
|
||||
$user = common_current_user();
|
||||
@ -219,12 +219,49 @@ class GroupMemberListItem extends ProfileListItem
|
||||
if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group)) {
|
||||
$this->out->elementStart('li', 'entity_block');
|
||||
$bf = new GroupBlockForm($this->out, $this->profile, $this->group,
|
||||
array('action' => 'groupmembers',
|
||||
'nickname' => $this->group->nickname));
|
||||
$this->returnToArgs());
|
||||
$bf->show();
|
||||
$this->out->elementEnd('li');
|
||||
}
|
||||
}
|
||||
|
||||
function linkAttributes()
|
||||
{
|
||||
$aAttrs = parent::linkAttributes();
|
||||
|
||||
if (common_config('nofollow', 'members')) {
|
||||
$aAttrs['rel'] .= ' nofollow';
|
||||
}
|
||||
|
||||
return $aAttrs;
|
||||
}
|
||||
|
||||
function homepageAttributes()
|
||||
{
|
||||
$aAttrs = parent::linkAttributes();
|
||||
|
||||
if (common_config('nofollow', 'members')) {
|
||||
$aAttrs['rel'] = 'nofollow';
|
||||
}
|
||||
|
||||
return $aAttrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch necessary return-to arguments for the profile forms
|
||||
* to return to this list when they're done.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function returnToArgs()
|
||||
{
|
||||
$args = array('action' => 'groupmembers',
|
||||
'nickname' => $this->group->nickname);
|
||||
$page = $this->out->arg('page');
|
||||
if ($page) {
|
||||
$args['param-page'] = $page;
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,8 +135,10 @@ class groupRssAction extends Rss10Action
|
||||
$c = array('url' => common_local_url('grouprss',
|
||||
array('nickname' =>
|
||||
$group->nickname)),
|
||||
// TRANS: Message is used as link title. %s is a user nickname.
|
||||
'title' => sprintf(_('%s timeline'), $group->nickname),
|
||||
'link' => common_local_url('showgroup', array('nickname' => $group->nickname)),
|
||||
// TRANS: Message is used as link description. %1$s is a username, %2$s is a site name.
|
||||
'description' => sprintf(_('Updates from members of %1$s on %2$s!'),
|
||||
$group->nickname, common_config('site', 'name')));
|
||||
return $c;
|
||||
|
@ -56,6 +56,7 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
|
||||
function title()
|
||||
{
|
||||
// TRANS: Title for instance messaging settings.
|
||||
return _('IM settings');
|
||||
}
|
||||
|
||||
@ -67,6 +68,9 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
|
||||
function getInstructions()
|
||||
{
|
||||
// TRANS: Instant messaging settings page instructions.
|
||||
// TRANS: [instant messages] is link text, "(%%doc.im%%)" is the link.
|
||||
// TRANS: the order and formatting of link text and link should remain unchanged.
|
||||
return _('You can send and receive notices through '.
|
||||
'Jabber/GTalk [instant messages](%%doc.im%%). '.
|
||||
'Configure your address and settings below.');
|
||||
@ -86,6 +90,7 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
{
|
||||
if (!common_config('xmpp', 'enabled')) {
|
||||
$this->element('div', array('class' => 'error'),
|
||||
// TRANS: Message given in the IM settings if XMPP is not enabled on the site.
|
||||
_('IM is not available.'));
|
||||
return;
|
||||
}
|
||||
@ -97,32 +102,41 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
'action' =>
|
||||
common_local_url('imsettings')));
|
||||
$this->elementStart('fieldset', array('id' => 'settings_im_address'));
|
||||
$this->element('legend', null, _('Address'));
|
||||
// TRANS: Form legend for IM settings form.
|
||||
$this->element('legend', null, _('IM address'));
|
||||
$this->hidden('token', common_session_token());
|
||||
|
||||
if ($user->jabber) {
|
||||
$this->element('p', 'form_confirmed', $user->jabber);
|
||||
// TRANS: Form note in IM settings form.
|
||||
$this->element('p', 'form_note',
|
||||
_('Current confirmed Jabber/GTalk address.'));
|
||||
$this->hidden('jabber', $user->jabber);
|
||||
$this->submit('remove', _('Remove'));
|
||||
// TRANS: Button label to remove a confirmed IM address.
|
||||
$this->submit('remove', _m('BUTTON','Remove'));
|
||||
} else {
|
||||
$confirm = $this->getConfirmation();
|
||||
if ($confirm) {
|
||||
$this->element('p', 'form_unconfirmed', $confirm->address);
|
||||
$this->element('p', 'form_note',
|
||||
// TRANS: Form note in IM settings form.
|
||||
// TRANS: %s is the IM address set for the site.
|
||||
sprintf(_('Awaiting confirmation on this address. '.
|
||||
'Check your Jabber/GTalk account for a '.
|
||||
'message with further instructions. '.
|
||||
'(Did you add %s to your buddy list?)'),
|
||||
jabber_daemon_address()));
|
||||
$this->hidden('jabber', $confirm->address);
|
||||
$this->submit('cancel', _('Cancel'));
|
||||
// TRANS: Button label to cancel an IM address confirmation procedure.
|
||||
$this->submit('cancel', _m('BUTTON','Cancel'));
|
||||
} else {
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
// TRANS: Field label for IM address input in IM settings form.
|
||||
$this->input('jabber', _('IM address'),
|
||||
($this->arg('jabber')) ? $this->arg('jabber') : null,
|
||||
// TRANS: IM address input field instructions in IM settings form.
|
||||
// TRANS: %s is the IM address set for the site.
|
||||
sprintf(_('Jabber or GTalk address, '.
|
||||
'like "UserName@example.org". '.
|
||||
'First, make sure to add %s to your '.
|
||||
@ -130,37 +144,44 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
jabber_daemon_address()));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
$this->submit('add', _('Add'));
|
||||
// TRANS: Button label for adding an IM address in IM settings form.
|
||||
$this->submit('add', _m('BUTTON','Add'));
|
||||
}
|
||||
}
|
||||
$this->elementEnd('fieldset');
|
||||
|
||||
$this->elementStart('fieldset', array('id' => 'settings_im_preferences'));
|
||||
$this->element('legend', null, _('Preferences'));
|
||||
// TRANS: Form legend for IM preferences form.
|
||||
$this->element('legend', null, _('IM preferences'));
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('jabbernotify',
|
||||
// TRANS: Checkbox label in IM preferences form.
|
||||
_('Send me notices through Jabber/GTalk.'),
|
||||
$user->jabbernotify);
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('updatefrompresence',
|
||||
// TRANS: Checkbox label in IM preferences form.
|
||||
_('Post a notice when my Jabber/GTalk status changes.'),
|
||||
$user->updatefrompresence);
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('jabberreplies',
|
||||
// TRANS: Checkbox label in IM preferences form.
|
||||
_('Send me replies through Jabber/GTalk '.
|
||||
'from people I\'m not subscribed to.'),
|
||||
$user->jabberreplies);
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('jabbermicroid',
|
||||
// TRANS: Checkbox label in IM preferences form.
|
||||
_('Publish a MicroID for my Jabber/GTalk address.'),
|
||||
$user->jabbermicroid);
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
$this->submit('save', _('Save'));
|
||||
// TRANS: Button label to save IM preferences.
|
||||
$this->submit('save', _m('BUTTON','Save'));
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
}
|
||||
@ -217,6 +238,7 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
} else if ($this->arg('remove')) {
|
||||
$this->removeAddress();
|
||||
} else {
|
||||
// TRANS: Message given submitting a form with an unknown action in IM settings.
|
||||
$this->showForm(_('Unexpected form submission.'));
|
||||
}
|
||||
}
|
||||
@ -232,7 +254,6 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
|
||||
function savePreferences()
|
||||
{
|
||||
|
||||
$jabbernotify = $this->boolean('jabbernotify');
|
||||
$updatefrompresence = $this->boolean('updatefrompresence');
|
||||
$jabberreplies = $this->boolean('jabberreplies');
|
||||
@ -255,12 +276,14 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
|
||||
if ($result === false) {
|
||||
common_log_db_error($user, 'UPDATE', __FILE__);
|
||||
// TRANS: Server error thrown on database error updating IM preferences.
|
||||
$this->serverError(_('Couldn\'t update user.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$user->query('COMMIT');
|
||||
|
||||
// TRANS: Confirmation message for successful IM preferences save.
|
||||
$this->showForm(_('Preferences saved.'), true);
|
||||
}
|
||||
|
||||
@ -282,6 +305,7 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
// Some validation
|
||||
|
||||
if (!$jabber) {
|
||||
// TRANS: Message given saving IM address without having provided one.
|
||||
$this->showForm(_('No Jabber ID.'));
|
||||
return;
|
||||
}
|
||||
@ -289,16 +313,20 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
$jabber = jabber_normalize_jid($jabber);
|
||||
|
||||
if (!$jabber) {
|
||||
// TRANS: Message given saving IM address that cannot be normalised.
|
||||
$this->showForm(_('Cannot normalize that Jabber ID'));
|
||||
return;
|
||||
}
|
||||
if (!jabber_valid_base_jid($jabber)) {
|
||||
if (!jabber_valid_base_jid($jabber, common_config('email', 'domain_check'))) {
|
||||
// TRANS: Message given saving IM address that not valid.
|
||||
$this->showForm(_('Not a valid Jabber ID'));
|
||||
return;
|
||||
} else if ($user->jabber == $jabber) {
|
||||
// TRANS: Message given saving IM address that is already set.
|
||||
$this->showForm(_('That is already your Jabber ID.'));
|
||||
return;
|
||||
} else if ($this->jabberExists($jabber)) {
|
||||
// TRANS: Message given saving IM address that is already set for another user.
|
||||
$this->showForm(_('Jabber ID already belongs to another user.'));
|
||||
return;
|
||||
}
|
||||
@ -316,6 +344,7 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
|
||||
if ($result === false) {
|
||||
common_log_db_error($confirm, 'INSERT', __FILE__);
|
||||
// TRANS: Server error thrown on database error adding IM confirmation code.
|
||||
$this->serverError(_('Couldn\'t insert confirmation code.'));
|
||||
return;
|
||||
}
|
||||
@ -324,6 +353,8 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
$user->nickname,
|
||||
$jabber);
|
||||
|
||||
// TRANS: Message given saving valid IM address that is to be confirmed.
|
||||
// TRANS: %s is the IM address set for the site.
|
||||
$msg = sprintf(_('A confirmation code was sent '.
|
||||
'to the IM address you added. '.
|
||||
'You must approve %s for '.
|
||||
@ -348,10 +379,12 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
$confirm = $this->getConfirmation();
|
||||
|
||||
if (!$confirm) {
|
||||
// TRANS: Message given canceling IM address confirmation that is not pending.
|
||||
$this->showForm(_('No pending confirmation to cancel.'));
|
||||
return;
|
||||
}
|
||||
if ($confirm->address != $jabber) {
|
||||
// TRANS: Message given canceling IM address confirmation for the wrong IM address.
|
||||
$this->showForm(_('That is the wrong IM address.'));
|
||||
return;
|
||||
}
|
||||
@ -360,11 +393,13 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
|
||||
if (!$result) {
|
||||
common_log_db_error($confirm, 'DELETE', __FILE__);
|
||||
$this->serverError(_('Couldn\'t delete email confirmation.'));
|
||||
// TRANS: Server error thrown on database error canceling IM address confirmation.
|
||||
$this->serverError(_('Couldn\'t delete IM confirmation.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->showForm(_('Confirmation cancelled.'), true);
|
||||
// TRANS: Message given after successfully canceling IM address confirmation.
|
||||
$this->showForm(_('IM confirmation cancelled.'), true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -384,6 +419,8 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
// Maybe an old tab open...?
|
||||
|
||||
if ($user->jabber != $jabber) {
|
||||
// TRANS: Message given trying to remove an IM address that is not
|
||||
// TRANS: registered for the active user.
|
||||
$this->showForm(_('That is not your Jabber ID.'));
|
||||
return;
|
||||
}
|
||||
@ -398,6 +435,7 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
|
||||
if (!$result) {
|
||||
common_log_db_error($user, 'UPDATE', __FILE__);
|
||||
// TRANS: Server error thrown on database error removing a registered IM address.
|
||||
$this->serverError(_('Couldn\'t update user.'));
|
||||
return;
|
||||
}
|
||||
@ -405,7 +443,8 @@ class ImsettingsAction extends ConnectSettingsAction
|
||||
|
||||
// XXX: unsubscribe to the old address
|
||||
|
||||
$this->showForm(_('The address was removed.'), true);
|
||||
// TRANS: Message given after successfully removing a registered IM address.
|
||||
$this->showForm(_('The IM address was removed.'), true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -38,7 +38,7 @@ class InviteAction extends CurrentUserDesignAction
|
||||
if (!common_config('invite', 'enabled')) {
|
||||
$this->clientError(_('Invites have been disabled.'));
|
||||
} else if (!common_logged_in()) {
|
||||
$this->clientError(sprintf(_('You must be logged in to invite other users to use %s'),
|
||||
$this->clientError(sprintf(_('You must be logged in to invite other users to use %s.'),
|
||||
common_config('site', 'name')));
|
||||
return;
|
||||
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
@ -224,8 +224,10 @@ class InviteAction extends CurrentUserDesignAction
|
||||
|
||||
$headers['From'] = mail_notify_from();
|
||||
$headers['To'] = trim($email);
|
||||
// TRANS: Subject for invitation email. Note that 'them' is correct as a gender-neutral singular 3rd-person pronoun in English.
|
||||
$headers['Subject'] = sprintf(_('%1$s has invited you to join them on %2$s'), $bestname, $sitename);
|
||||
|
||||
// TRANS: Body text for invitation email. Note that 'them' is correct as a gender-neutral singular 3rd-person pronoun in English.
|
||||
$body = sprintf(_("%1\$s has invited you to join them on %2\$s (%3\$s).\n\n".
|
||||
"%2\$s is a micro-blogging service that lets you keep up-to-date with people you know and people who interest you.\n\n".
|
||||
"You can also share news about yourself, your thoughts, or your life online with people who know about you. ".
|
||||
|
@ -62,6 +62,28 @@ class LoginAction extends Action
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare page to run
|
||||
*
|
||||
*
|
||||
* @param $args
|
||||
* @return string title
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
// @todo this check should really be in index.php for all sensitive actions
|
||||
$ssl = common_config('site', 'ssl');
|
||||
if (empty($_SERVER['HTTPS']) && ($ssl == 'always' || $ssl == 'sometimes')) {
|
||||
common_redirect(common_local_url('login'));
|
||||
// exit
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle input, produce output
|
||||
*
|
||||
@ -267,10 +289,14 @@ class LoginAction extends Action
|
||||
'user name and password ' .
|
||||
'before changing your settings.');
|
||||
} else {
|
||||
return _('Login with your username and password. ' .
|
||||
'Don\'t have a username yet? ' .
|
||||
$prompt = _('Login with your username and password.');
|
||||
if (!common_config('site', 'closed') && !common_config('site', 'inviteonly')) {
|
||||
$prompt .= ' ';
|
||||
$prompt .= _('Don\'t have a username yet? ' .
|
||||
'[Register](%%action.register%%) a new account.');
|
||||
}
|
||||
return $prompt;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,7 +41,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
class MakeadminAction extends Action
|
||||
class MakeadminAction extends RedirectingAction
|
||||
{
|
||||
var $profile = null;
|
||||
var $group = null;
|
||||
@ -148,20 +148,19 @@ class MakeadminAction extends Action
|
||||
$this->group->getBestName());
|
||||
}
|
||||
|
||||
foreach ($this->args as $k => $v) {
|
||||
if ($k == 'returnto-action') {
|
||||
$action = $v;
|
||||
} else if (substr($k, 0, 9) == 'returnto-') {
|
||||
$args[substr($k, 9)] = $v;
|
||||
}
|
||||
$this->returnToArgs();
|
||||
}
|
||||
|
||||
if ($action) {
|
||||
common_redirect(common_local_url($action, $args), 303);
|
||||
} else {
|
||||
common_redirect(common_local_url('groupmembers',
|
||||
array('nickname' => $this->group->nickname)),
|
||||
303);
|
||||
}
|
||||
/**
|
||||
* If we reached this form without returnto arguments, default to
|
||||
* the top of the group's member list.
|
||||
*
|
||||
* @return string URL
|
||||
*/
|
||||
function defaultReturnTo()
|
||||
{
|
||||
return common_local_url('groupmembers',
|
||||
array('nickname' => $this->group->nickname));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ class MicrosummaryAction extends Action
|
||||
$notice = $user->getCurrentNotice();
|
||||
|
||||
if (!$notice) {
|
||||
$this->clientError(_('No current status'), 404);
|
||||
$this->clientError(_('No current status.'), 404);
|
||||
}
|
||||
|
||||
header('Content-Type: text/plain');
|
||||
|
@ -184,13 +184,21 @@ class NewnoticeAction extends Action
|
||||
|
||||
$options = array('reply_to' => ($replyto == 'false') ? null : $replyto);
|
||||
|
||||
if ($user->shareLocation() && $this->arg('notice_data-geo')) {
|
||||
|
||||
if ($user->shareLocation()) {
|
||||
// use browser data if checked; otherwise profile data
|
||||
if ($this->arg('notice_data-geo')) {
|
||||
$locOptions = Notice::locationOptions($this->trimmed('lat'),
|
||||
$this->trimmed('lon'),
|
||||
$this->trimmed('location_id'),
|
||||
$this->trimmed('location_ns'),
|
||||
$user->getProfile());
|
||||
} else {
|
||||
$locOptions = Notice::locationOptions(null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$user->getProfile());
|
||||
}
|
||||
|
||||
$options = array_merge($options, $locOptions);
|
||||
}
|
||||
@ -201,8 +209,6 @@ class NewnoticeAction extends Action
|
||||
$upload->attachToNotice($notice);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($this->boolean('ajax')) {
|
||||
header('Content-Type: text/xml;charset=utf-8');
|
||||
$this->xw->startDocument('1.0', 'UTF-8');
|
||||
|
@ -99,7 +99,7 @@ class OauthconnectionssettingsAction extends ConnectSettingsAction
|
||||
|
||||
$application = $profile->getApplications($offset, $limit);
|
||||
|
||||
$cnt == 0;
|
||||
$cnt = 0;
|
||||
|
||||
if (!empty($application)) {
|
||||
$al = new ApplicationList($application, $user, $this, true);
|
||||
@ -112,7 +112,7 @@ class OauthconnectionssettingsAction extends ConnectSettingsAction
|
||||
|
||||
$this->pagination($this->page > 1, $cnt > APPS_PER_PAGE,
|
||||
$this->page, 'connectionssettings',
|
||||
array('nickname' => $this->user->nickname));
|
||||
array('nickname' => $user->nickname));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -183,7 +183,7 @@ class OauthconnectionssettingsAction extends ConnectSettingsAction
|
||||
|
||||
if (!$result) {
|
||||
common_log_db_error($orig, 'DELETE', __FILE__);
|
||||
$this->clientError(_('Unable to revoke access for app: ' . $app->id));
|
||||
$this->clientError(sprintf(_('Unable to revoke access for app: %s.'), $app->id));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -195,7 +195,7 @@ class OauthconnectionssettingsAction extends ConnectSettingsAction
|
||||
|
||||
function showEmptyListMessage()
|
||||
{
|
||||
$message = sprintf(_('You have not authorized any applications to use your account.'));
|
||||
$message = _('You have not authorized any applications to use your account.');
|
||||
|
||||
$this->elementStart('div', 'guide');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
|
@ -23,6 +23,7 @@
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @copyright 2008 StatusNet, Inc.
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
@ -60,7 +61,7 @@ class OembedAction extends Action
|
||||
$proxy_args = $r->map($path);
|
||||
|
||||
if (!$proxy_args) {
|
||||
$this->serverError(_("$path not found"), 404);
|
||||
$this->serverError(_("$path not found."), 404);
|
||||
}
|
||||
$oembed=array();
|
||||
$oembed['version']='1.0';
|
||||
@ -72,11 +73,11 @@ class OembedAction extends Action
|
||||
$id = $proxy_args['notice'];
|
||||
$notice = Notice::staticGet($id);
|
||||
if(empty($notice)){
|
||||
$this->serverError(_("notice $id not found"), 404);
|
||||
$this->serverError(_("Notice $id not found."), 404);
|
||||
}
|
||||
$profile = $notice->getProfile();
|
||||
if (empty($profile)) {
|
||||
$this->serverError(_('Notice has no profile'), 500);
|
||||
$this->serverError(_('Notice has no profile.'), 500);
|
||||
}
|
||||
if (!empty($profile->fullname)) {
|
||||
$authorname = $profile->fullname . ' (' . $profile->nickname . ')';
|
||||
@ -95,7 +96,7 @@ class OembedAction extends Action
|
||||
$id = $proxy_args['attachment'];
|
||||
$attachment = File::staticGet($id);
|
||||
if(empty($attachment)){
|
||||
$this->serverError(_("attachment $id not found"), 404);
|
||||
$this->serverError(_("Attachment $id not found."), 404);
|
||||
}
|
||||
if(empty($attachment->filename) && $file_oembed = File_oembed::staticGet('file_id', $attachment->id)){
|
||||
// Proxy the existing oembed information
|
||||
@ -123,7 +124,7 @@ class OembedAction extends Action
|
||||
if($attachment->title) $oembed['title']=$attachment->title;
|
||||
break;
|
||||
default:
|
||||
$this->serverError(_("$path not supported for oembed requests"), 501);
|
||||
$this->serverError(_("$path not supported for oembed requests."), 501);
|
||||
}
|
||||
switch($args['format']){
|
||||
case 'xml':
|
||||
@ -154,10 +155,12 @@ class OembedAction extends Action
|
||||
$this->end_document('json');
|
||||
break;
|
||||
default:
|
||||
$this->serverError(_('content type ' . $apidata['content-type'] . ' not supported'), 501);
|
||||
// TRANS: Error message displaying attachments. %s is a raw MIME type (eg 'image/png')
|
||||
$this->serverError(sprintf(_('Content type %s not supported.'), $apidata['content-type']), 501);
|
||||
}
|
||||
}else{
|
||||
$this->serverError(_('Only ' . common_root_url() . ' urls over plain http please'), 404);
|
||||
// TRANS: Error message displaying attachments. %s is the site's base URL.
|
||||
$this->serverError(sprintf(_('Only %s URLs over plain HTTP please.'), common_root_url()), 404);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,6 +126,8 @@ class OtpAction extends Action
|
||||
$this->lt->delete();
|
||||
$this->lt = null;
|
||||
|
||||
common_real_login(true);
|
||||
|
||||
if ($this->rememberme) {
|
||||
common_rememberme($this->user);
|
||||
}
|
||||
|
@ -154,19 +154,19 @@ class PathsadminpanelAction extends AdminPanelAction
|
||||
// Validate theme dir
|
||||
|
||||
if (!empty($values['theme']['dir']) && !is_readable($values['theme']['dir'])) {
|
||||
$this->clientError(sprintf(_("Theme directory not readable: %s"), $values['theme']['dir']));
|
||||
$this->clientError(sprintf(_("Theme directory not readable: %s."), $values['theme']['dir']));
|
||||
}
|
||||
|
||||
// Validate avatar dir
|
||||
|
||||
if (empty($values['avatar']['dir']) || !is_writable($values['avatar']['dir'])) {
|
||||
$this->clientError(sprintf(_("Avatar directory not writable: %s"), $values['avatar']['dir']));
|
||||
$this->clientError(sprintf(_("Avatar directory not writable: %s."), $values['avatar']['dir']));
|
||||
}
|
||||
|
||||
// Validate background dir
|
||||
|
||||
if (empty($values['background']['dir']) || !is_writable($values['background']['dir'])) {
|
||||
$this->clientError(sprintf(_("Background directory not writable: %s"), $values['background']['dir']));
|
||||
$this->clientError(sprintf(_("Background directory not writable: %s."), $values['background']['dir']));
|
||||
}
|
||||
|
||||
// Validate locales dir
|
||||
@ -174,13 +174,13 @@ class PathsadminpanelAction extends AdminPanelAction
|
||||
// XXX: What else do we need to validate for lacales path here? --Z
|
||||
|
||||
if (!empty($values['site']['locale_path']) && !is_readable($values['site']['locale_path'])) {
|
||||
$this->clientError(sprintf(_("Locales directory not readable: %s"), $values['site']['locale_path']));
|
||||
$this->clientError(sprintf(_("Locales directory not readable: %s."), $values['site']['locale_path']));
|
||||
}
|
||||
|
||||
// Validate SSL setup
|
||||
|
||||
if (mb_strlen($values['site']['sslserver']) > 255) {
|
||||
$this->clientError(_("Invalid SSL server. The maximum length is 255 characters."));
|
||||
$this->clientError(_('Invalid SSL server. The maximum length is 255 characters.'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,8 +32,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/profilelist.php';
|
||||
|
||||
/**
|
||||
* This class outputs a paginated list of profiles self-tagged with a given tag
|
||||
*
|
||||
@ -67,7 +65,7 @@ class PeopletagAction extends Action
|
||||
$this->tag = $this->trimmed('tag');
|
||||
|
||||
if (!common_valid_profile_tag($this->tag)) {
|
||||
$this->clientError(sprintf(_('Not a valid people tag: %s'),
|
||||
$this->clientError(sprintf(_('Not a valid people tag: %s.'),
|
||||
$this->tag));
|
||||
return;
|
||||
}
|
||||
@ -124,8 +122,8 @@ class PeopletagAction extends Action
|
||||
|
||||
$profile->query(sprintf($qry, $this->tag, $lim));
|
||||
|
||||
$pl = new ProfileList($profile, $this);
|
||||
$cnt = $pl->show();
|
||||
$ptl = new PeopleTagList($profile, $this); // pass the ammunition
|
||||
$cnt = $ptl->show();
|
||||
|
||||
$this->pagination($this->page > 1,
|
||||
$cnt > PROFILES_PER_PAGE,
|
||||
@ -146,3 +144,37 @@ class PeopletagAction extends Action
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PeopleTagList extends ProfileList
|
||||
{
|
||||
function newListItem($profile)
|
||||
{
|
||||
return new PeopleTagListItem($profile, $this->action);
|
||||
}
|
||||
}
|
||||
|
||||
class PeopleTagListItem extends ProfileListItem
|
||||
{
|
||||
function linkAttributes()
|
||||
{
|
||||
$aAttrs = parent::linkAttributes();
|
||||
|
||||
if (common_config('nofollow', 'peopletag')) {
|
||||
$aAttrs['rel'] .= ' nofollow';
|
||||
}
|
||||
|
||||
return $aAttrs;
|
||||
}
|
||||
|
||||
function homepageAttributes()
|
||||
{
|
||||
$aAttrs = parent::linkAttributes();
|
||||
|
||||
if (common_config('nofollow', 'peopletag')) {
|
||||
$aAttrs['rel'] = 'nofollow';
|
||||
}
|
||||
|
||||
return $aAttrs;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ class PostnoticeAction extends Action
|
||||
{
|
||||
$content = common_shorten_links($_POST['omb_notice_content']);
|
||||
if (Notice::contentTooLong($content)) {
|
||||
$this->clientError(_('Invalid notice content'), 400);
|
||||
$this->clientError(_('Invalid notice content.'), 400);
|
||||
return false;
|
||||
}
|
||||
$license = $_POST['omb_notice_license'];
|
||||
|
@ -80,7 +80,7 @@ class PublicAction extends Action
|
||||
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
||||
|
||||
if ($this->page > MAX_PUBLIC_PAGE) {
|
||||
$this->clientError(sprintf(_("Beyond the page limit (%s)"), MAX_PUBLIC_PAGE));
|
||||
$this->clientError(sprintf(_("Beyond the page limit (%s)."), MAX_PUBLIC_PAGE));
|
||||
}
|
||||
|
||||
common_set_returnto($this->selfUrl());
|
||||
@ -95,7 +95,7 @@ class PublicAction extends Action
|
||||
|
||||
if($this->page > 1 && $this->notice->N == 0){
|
||||
// TRANS: Server error when page not found (404)
|
||||
$this->serverError(_('No such page'),$code=404);
|
||||
$this->serverError(_('No such page.'),$code=404);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -109,7 +109,7 @@ class PublictagcloudAction extends Action
|
||||
$cutoff = sprintf("notice_tag.created > '%s'",
|
||||
common_sql_date(time() - common_config('tag', 'cutoff')));
|
||||
$tags->selectAdd($calc . ' as weight');
|
||||
$tags->addWhere($cutoff);
|
||||
$tags->whereAdd($cutoff);
|
||||
$tags->groupBy('tag');
|
||||
$tags->orderBy('weight DESC');
|
||||
|
||||
|
@ -8,7 +8,9 @@
|
||||
* @category Action
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @author Robin Millette <millette@status.net>
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://status.net/
|
||||
*
|
||||
@ -44,6 +46,7 @@ require_once INSTALLDIR.'/lib/xrdsoutputter.php';
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @author Robin Millette <millette@status.net>
|
||||
* @author Craig Andrews <candrews@integralblue.com>
|
||||
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://status.net/
|
||||
*
|
||||
|
@ -21,7 +21,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
|
||||
|
||||
# You have 24 hours to claim your password
|
||||
|
||||
define(MAX_RECOVERY_TIME, 24 * 60 * 60);
|
||||
define('MAX_RECOVERY_TIME', 24 * 60 * 60);
|
||||
|
||||
class RecoverpasswordAction extends Action
|
||||
{
|
||||
@ -262,10 +262,20 @@ class RecoverpasswordAction extends Action
|
||||
# See if it's an unconfirmed email address
|
||||
|
||||
if (!$user) {
|
||||
$confirm_email = Confirm_address::staticGet('address', common_canonical_email($nore));
|
||||
if ($confirm_email && $confirm_email->address_type == 'email') {
|
||||
// Warning: it may actually be legit to have multiple folks
|
||||
// who have claimed, but not yet confirmed, the same address.
|
||||
// We'll only send to the first one that comes up.
|
||||
$confirm_email = new Confirm_address();
|
||||
$confirm_email->address = common_canonical_email($nore);
|
||||
$confirm_email->address_type = 'email';
|
||||
$confirm_email->find();
|
||||
if ($confirm_email->fetch()) {
|
||||
$user = User::staticGet($confirm_email->user_id);
|
||||
} else {
|
||||
$confirm_email = null;
|
||||
}
|
||||
} else {
|
||||
$confirm_email = null;
|
||||
}
|
||||
|
||||
if (!$user) {
|
||||
@ -276,9 +286,11 @@ class RecoverpasswordAction extends Action
|
||||
# Try to get an unconfirmed email address if they used a user name
|
||||
|
||||
if (!$user->email && !$confirm_email) {
|
||||
$confirm_email = Confirm_address::staticGet('user_id', $user->id);
|
||||
if ($confirm_email && $confirm_email->address_type != 'email') {
|
||||
# Skip non-email confirmations
|
||||
$confirm_email = new Confirm_address();
|
||||
$confirm_email->user_id = $user->id;
|
||||
$confirm_email->address_type = 'email';
|
||||
$confirm_email->find();
|
||||
if (!$confirm_email->fetch()) {
|
||||
$confirm_email = null;
|
||||
}
|
||||
}
|
||||
@ -294,7 +306,7 @@ class RecoverpasswordAction extends Action
|
||||
$confirm->code = common_confirmation_code(128);
|
||||
$confirm->address_type = 'recover';
|
||||
$confirm->user_id = $user->id;
|
||||
$confirm->address = (isset($user->email)) ? $user->email : $confirm_email->address;
|
||||
$confirm->address = (!empty($user->email)) ? $user->email : $confirm_email->address;
|
||||
|
||||
if (!$confirm->insert()) {
|
||||
common_log_db_error($confirm, 'INSERT', __FILE__);
|
||||
@ -319,7 +331,8 @@ class RecoverpasswordAction extends Action
|
||||
$body .= common_config('site', 'name');
|
||||
$body .= "\n";
|
||||
|
||||
mail_to_user($user, _('Password recovery requested'), $body, $confirm->address);
|
||||
$headers = _mail_prepare_headers('recoverpassword', $user->nickname, $user->nickname);
|
||||
mail_to_user($user, _('Password recovery requested'), $body, $headers, $confirm->address);
|
||||
|
||||
$this->mode = 'sent';
|
||||
$this->msg = _('Instructions for recovering your password ' .
|
||||
|
@ -74,6 +74,13 @@ class RegisterAction extends Action
|
||||
parent::prepare($args);
|
||||
$this->code = $this->trimmed('code');
|
||||
|
||||
// @todo this check should really be in index.php for all sensitive actions
|
||||
$ssl = common_config('site', 'ssl');
|
||||
if (empty($_SERVER['HTTPS']) && ($ssl == 'always' || $ssl == 'sometimes')) {
|
||||
common_redirect(common_local_url('register'));
|
||||
// exit
|
||||
}
|
||||
|
||||
if (empty($this->code)) {
|
||||
common_ensure_session();
|
||||
if (array_key_exists('invitecode', $_SESSION)) {
|
||||
@ -491,11 +498,7 @@ class RegisterAction extends Action
|
||||
$this->elementStart('li');
|
||||
$this->element('input', $attrs);
|
||||
$this->elementStart('label', array('class' => 'checkbox', 'for' => 'license'));
|
||||
$this->text(_('My text and files are available under '));
|
||||
$this->element('a', array('href' => common_config('license', 'url')),
|
||||
common_config('license', 'title'), _("Creative Commons Attribution 3.0"));
|
||||
$this->text(_(' except this private data: password, '.
|
||||
'email address, IM address, and phone number.'));
|
||||
$this->raw($this->licenseCheckbox());
|
||||
$this->elementEnd('label');
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
@ -505,6 +508,48 @@ class RegisterAction extends Action
|
||||
$this->elementEnd('form');
|
||||
}
|
||||
|
||||
function licenseCheckbox()
|
||||
{
|
||||
$out = '';
|
||||
switch (common_config('license', 'type')) {
|
||||
case 'private':
|
||||
// TRANS: Copyright checkbox label in registration dialog, for private sites.
|
||||
$out .= htmlspecialchars(sprintf(
|
||||
_('I understand that content and data of %1$s are private and confidential.'),
|
||||
common_config('site', 'name')));
|
||||
// fall through
|
||||
case 'allrightsreserved':
|
||||
if ($out != '') {
|
||||
$out .= ' ';
|
||||
}
|
||||
if (common_config('license', 'owner')) {
|
||||
// TRANS: Copyright checkbox label in registration dialog, for all rights reserved with a specified copyright owner.
|
||||
$out .= htmlspecialchars(sprintf(
|
||||
_('My text and files are copyright by %1$s.'),
|
||||
common_config('license', 'owner')));
|
||||
} else {
|
||||
// TRANS: Copyright checkbox label in registration dialog, for all rights reserved with ownership left to contributors.
|
||||
$out .= htmlspecialchars(_('My text and files remain under my own copyright.'));
|
||||
}
|
||||
// TRANS: Copyright checkbox label in registration dialog, for all rights reserved.
|
||||
$out .= ' ' . _('All rights reserved.');
|
||||
break;
|
||||
case 'cc': // fall through
|
||||
default:
|
||||
// TRANS: Copyright checkbox label in registration dialog, for Creative Commons-style licenses.
|
||||
$message = _('My text and files are available under %s ' .
|
||||
'except this private data: password, ' .
|
||||
'email address, IM address, and phone number.');
|
||||
$link = '<a href="' .
|
||||
htmlspecialchars(common_config('license', 'url')) .
|
||||
'">' .
|
||||
htmlspecialchars(common_config('license', 'title')) .
|
||||
'</a>';
|
||||
$out .= sprintf(htmlspecialchars($message), $link);
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show some information about registering for the site
|
||||
*
|
||||
|
@ -188,7 +188,7 @@ class RemotesubscribeAction extends Action
|
||||
$profile = $user->getProfile();
|
||||
if (!$profile) {
|
||||
common_log_db_error($user, 'SELECT', __FILE__);
|
||||
$this->serverError(_('User without matching profile'));
|
||||
$this->serverError(_('User without matching profile.'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -54,21 +54,21 @@ class RepeatAction extends Action
|
||||
$this->user = common_current_user();
|
||||
|
||||
if (empty($this->user)) {
|
||||
$this->clientError(_("Only logged-in users can repeat notices."));
|
||||
$this->clientError(_('Only logged-in users can repeat notices.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = $this->trimmed('notice');
|
||||
|
||||
if (empty($id)) {
|
||||
$this->clientError(_("No notice specified."));
|
||||
$this->clientError(_('No notice specified.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->notice = Notice::staticGet('id', $id);
|
||||
|
||||
if (empty($this->notice)) {
|
||||
$this->clientError(_("No notice specified."));
|
||||
$this->clientError(_('No notice specified.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -80,14 +80,14 @@ class RepeatAction extends Action
|
||||
$token = $this->trimmed('token-'.$id);
|
||||
|
||||
if (empty($token) || $token != common_session_token()) {
|
||||
$this->clientError(_("There was a problem with your session token. Try again, please."));
|
||||
$this->clientError(_('There was a problem with your session token. Try again, please.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$profile = $this->user->getProfile();
|
||||
|
||||
if ($profile->hasRepeated($id)) {
|
||||
$this->clientError(_("You already repeated that notice."));
|
||||
$this->clientError(_('You already repeated that notice.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ class RepliesAction extends OwnerDesignAction
|
||||
|
||||
if($this->page > 1 && $this->notice->N == 0){
|
||||
// TRANS: Server error when page not found (404)
|
||||
$this->serverError(_('No such page'),$code=404);
|
||||
$this->serverError(_('No such page.'),$code=404);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
99
actions/revokerole.php
Normal file
99
actions/revokerole.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Action class to sandbox an abusive user
|
||||
*
|
||||
* 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 Action
|
||||
* @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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sandbox a user.
|
||||
*
|
||||
* @category Action
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
class RevokeRoleAction extends ProfileFormAction
|
||||
{
|
||||
/**
|
||||
* Check parameters
|
||||
*
|
||||
* @param array $args action arguments (URL, GET, POST)
|
||||
*
|
||||
* @return boolean success flag
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
if (!parent::prepare($args)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->role = $this->arg('role');
|
||||
if (!Profile_role::isValid($this->role)) {
|
||||
$this->clientError(_('Invalid role.'));
|
||||
return false;
|
||||
}
|
||||
if (!Profile_role::isSettable($this->role)) {
|
||||
$this->clientError(_('This role is reserved and cannot be set.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$cur = common_current_user();
|
||||
|
||||
assert(!empty($cur)); // checked by parent
|
||||
|
||||
if (!$cur->hasRight(Right::REVOKEROLE)) {
|
||||
$this->clientError(_('You cannot revoke user roles on this site.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(!empty($this->profile)); // checked by parent
|
||||
|
||||
if (!$this->profile->hasRole($this->role)) {
|
||||
$this->clientError(_("User doesn't have this role."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sandbox a user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handlePost()
|
||||
{
|
||||
$this->profile->revokeRole($this->role);
|
||||
}
|
||||
}
|
@ -62,14 +62,14 @@ class SandboxAction extends ProfileFormAction
|
||||
assert(!empty($cur)); // checked by parent
|
||||
|
||||
if (!$cur->hasRight(Right::SANDBOXUSER)) {
|
||||
$this->clientError(_("You cannot sandbox users on this site."));
|
||||
$this->clientError(_('You cannot sandbox users on this site.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(!empty($this->profile)); // checked by parent
|
||||
|
||||
if ($this->profile->isSandboxed()) {
|
||||
$this->clientError(_("User is already sandboxed."));
|
||||
$this->clientError(_('User is already sandboxed.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -121,11 +121,11 @@ class ShowfavoritesAction extends OwnerDesignAction
|
||||
// Show imported/gateway notices as well as local if
|
||||
// the user is looking at his own favorites
|
||||
|
||||
$this->notice = $this->user->favoriteNotices(($this->page-1)*NOTICES_PER_PAGE,
|
||||
NOTICES_PER_PAGE + 1, true);
|
||||
$this->notice = $this->user->favoriteNotices(true, ($this->page-1)*NOTICES_PER_PAGE,
|
||||
NOTICES_PER_PAGE + 1);
|
||||
} else {
|
||||
$this->notice = $this->user->favoriteNotices(($this->page-1)*NOTICES_PER_PAGE,
|
||||
NOTICES_PER_PAGE + 1, false);
|
||||
$this->notice = $this->user->favoriteNotices(false, ($this->page-1)*NOTICES_PER_PAGE,
|
||||
NOTICES_PER_PAGE + 1);
|
||||
}
|
||||
|
||||
if (empty($this->notice)) {
|
||||
@ -135,7 +135,7 @@ class ShowfavoritesAction extends OwnerDesignAction
|
||||
|
||||
if($this->page > 1 && $this->notice->N == 0){
|
||||
// TRANS: Server error when page not found (404)
|
||||
$this->serverError(_('No such page'),$code=404);
|
||||
$this->serverError(_('No such page.'),$code=404);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -221,7 +221,8 @@ class ShowgroupAction extends GroupDesignAction
|
||||
|
||||
function showGroupProfile()
|
||||
{
|
||||
$this->elementStart('div', 'entity_profile vcard author');
|
||||
$this->elementStart('div', array('id' => 'i',
|
||||
'class' => 'entity_profile vcard author'));
|
||||
|
||||
$this->element('h2', null, _('Group profile'));
|
||||
|
||||
@ -301,6 +302,7 @@ class ShowgroupAction extends GroupDesignAction
|
||||
$this->element('h2', null, _('Group actions'));
|
||||
$this->elementStart('ul');
|
||||
$this->elementStart('li', 'entity_subscribe');
|
||||
if (Event::handle('StartGroupSubscribe', array($this, $this->group))) {
|
||||
$cur = common_current_user();
|
||||
if ($cur) {
|
||||
if ($cur->isMember($this->group)) {
|
||||
@ -311,9 +313,9 @@ class ShowgroupAction extends GroupDesignAction
|
||||
$jf->show();
|
||||
}
|
||||
}
|
||||
|
||||
Event::handle('EndGroupSubscribe', array($this, $this->group));
|
||||
}
|
||||
$this->elementEnd('li');
|
||||
|
||||
$this->elementEnd('ul');
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
@ -386,10 +388,12 @@ class ShowgroupAction extends GroupDesignAction
|
||||
$this->elementStart('div', array('id' => 'entity_members',
|
||||
'class' => 'section'));
|
||||
|
||||
if (Event::handle('StartShowGroupMembersMiniList', array($this))) {
|
||||
|
||||
$this->element('h2', null, _('Members'));
|
||||
|
||||
$pml = new ProfileMiniList($member, $this);
|
||||
$cnt = $pml->show();
|
||||
$gmml = new GroupMembersMiniList($member, $this);
|
||||
$cnt = $gmml->show();
|
||||
if ($cnt == 0) {
|
||||
$this->element('p', null, _('(None)'));
|
||||
}
|
||||
@ -400,6 +404,9 @@ class ShowgroupAction extends GroupDesignAction
|
||||
_('All members'));
|
||||
}
|
||||
|
||||
Event::handle('EndShowGroupMembersMiniList', array($this));
|
||||
}
|
||||
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
@ -423,14 +430,6 @@ class ShowgroupAction extends GroupDesignAction
|
||||
|
||||
function showStatistics()
|
||||
{
|
||||
// XXX: WORM cache this
|
||||
$members = $this->group->getMembers();
|
||||
$members_count = 0;
|
||||
/** $member->count() doesn't work. */
|
||||
while ($members->fetch()) {
|
||||
$members_count++;
|
||||
}
|
||||
|
||||
$this->elementStart('div', array('id' => 'entity_statistics',
|
||||
'class' => 'section'));
|
||||
|
||||
@ -444,7 +443,7 @@ class ShowgroupAction extends GroupDesignAction
|
||||
|
||||
$this->elementStart('dl', 'entity_members');
|
||||
$this->element('dt', null, _('Members'));
|
||||
$this->element('dd', null, (is_int($members_count)) ? $members_count : '0');
|
||||
$this->element('dd', null, $this->group->getMemberCount());
|
||||
$this->elementEnd('dl');
|
||||
|
||||
$this->elementEnd('div');
|
||||
@ -500,3 +499,26 @@ class GroupAdminSection extends ProfileSection
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class GroupMembersMiniList extends ProfileMiniList
|
||||
{
|
||||
function newListItem($profile)
|
||||
{
|
||||
return new GroupMembersMiniListItem($profile, $this->action);
|
||||
}
|
||||
}
|
||||
|
||||
class GroupMembersMiniListItem extends ProfileMiniListItem
|
||||
{
|
||||
function linkAttributes()
|
||||
{
|
||||
$aAttrs = parent::linkAttributes();
|
||||
|
||||
if (common_config('nofollow', 'members')) {
|
||||
$aAttrs['rel'] .= ' nofollow';
|
||||
}
|
||||
|
||||
return $aAttrs;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,17 +97,12 @@ class ShownoticeAction extends OwnerDesignAction
|
||||
$this->profile = $this->notice->getProfile();
|
||||
|
||||
if (empty($this->profile)) {
|
||||
$this->serverError(_('Notice has no profile'), 500);
|
||||
$this->serverError(_('Notice has no profile.'), 500);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->user = User::staticGet('id', $this->profile->id);
|
||||
|
||||
if ($this->notice->is_local == Notice::REMOTE_OMB) {
|
||||
common_redirect($this->notice->uri);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||
|
||||
return true;
|
||||
@ -198,13 +193,20 @@ class ShownoticeAction extends OwnerDesignAction
|
||||
|
||||
if ($this->notice->is_local == Notice::REMOTE_OMB) {
|
||||
if (!empty($this->notice->url)) {
|
||||
common_redirect($this->notice->url, 301);
|
||||
$target = $this->notice->url;
|
||||
} else if (!empty($this->notice->uri) && preg_match('/^https?:/', $this->notice->uri)) {
|
||||
common_redirect($this->notice->uri, 301);
|
||||
}
|
||||
// Old OMB posts saved the remote URL only into the URI field.
|
||||
$target = $this->notice->uri;
|
||||
} else {
|
||||
$this->showPage();
|
||||
// Shouldn't happen.
|
||||
$target = false;
|
||||
}
|
||||
if ($target && $target != $this->selfUrl()) {
|
||||
common_redirect($target, 301);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,14 +62,14 @@ class SilenceAction extends ProfileFormAction
|
||||
assert(!empty($cur)); // checked by parent
|
||||
|
||||
if (!$cur->hasRight(Right::SILENCEUSER)) {
|
||||
$this->clientError(_("You cannot silence users on this site."));
|
||||
$this->clientError(_('You cannot silence users on this site.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(!empty($this->profile)); // checked by parent
|
||||
|
||||
if ($this->profile->isSilenced()) {
|
||||
$this->clientError(_("User is already silenced."));
|
||||
$this->clientError(_('User is already silenced.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ class SiteadminpanelAction extends AdminPanelAction
|
||||
|
||||
function getInstructions()
|
||||
{
|
||||
return _('Basic settings for this StatusNet site.');
|
||||
return _('Basic settings for this StatusNet site');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,10 +90,11 @@ class SiteadminpanelAction extends AdminPanelAction
|
||||
|
||||
function saveSettings()
|
||||
{
|
||||
static $settings = array('site' => array('name', 'broughtby', 'broughtbyurl',
|
||||
static $settings = array(
|
||||
'site' => array('name', 'broughtby', 'broughtbyurl',
|
||||
'email', 'timezone', 'language',
|
||||
'site', 'textlimit', 'dupelimit'),
|
||||
'snapshot' => array('run', 'reporturl', 'frequency'));
|
||||
);
|
||||
|
||||
$values = array();
|
||||
|
||||
@ -129,7 +130,7 @@ class SiteadminpanelAction extends AdminPanelAction
|
||||
// Validate site name
|
||||
|
||||
if (empty($values['site']['name'])) {
|
||||
$this->clientError(_("Site name must have non-zero length."));
|
||||
$this->clientError(_('Site name must have non-zero length.'));
|
||||
}
|
||||
|
||||
// Validate email
|
||||
@ -158,35 +159,16 @@ class SiteadminpanelAction extends AdminPanelAction
|
||||
$this->clientError(sprintf(_('Unknown language "%s".'), $values['site']['language']));
|
||||
}
|
||||
|
||||
// Validate report URL
|
||||
|
||||
if (!is_null($values['snapshot']['reporturl']) &&
|
||||
!Validate::uri($values['snapshot']['reporturl'], array('allowed_schemes' => array('http', 'https')))) {
|
||||
$this->clientError(_("Invalid snapshot report URL."));
|
||||
}
|
||||
|
||||
// Validate snapshot run value
|
||||
|
||||
if (!in_array($values['snapshot']['run'], array('web', 'cron', 'never'))) {
|
||||
$this->clientError(_("Invalid snapshot run value."));
|
||||
}
|
||||
|
||||
// Validate snapshot run value
|
||||
|
||||
if (!Validate::number($values['snapshot']['frequency'])) {
|
||||
$this->clientError(_("Snapshot frequency must be a number."));
|
||||
}
|
||||
|
||||
// Validate text limit
|
||||
|
||||
if (!Validate::number($values['site']['textlimit'], array('min' => 140))) {
|
||||
$this->clientError(_("Minimum text limit is 140 characters."));
|
||||
if (!Validate::number($values['site']['textlimit'], array('min' => 0))) {
|
||||
$this->clientError(_("Minimum text limit is 0 (unlimited)."));
|
||||
}
|
||||
|
||||
// Validate dupe limit
|
||||
|
||||
if (!Validate::number($values['site']['dupelimit'], array('min' => 1))) {
|
||||
$this->clientError(_("Dupe limit must 1 or more seconds."));
|
||||
$this->clientError(_("Dupe limit must be one or more seconds."));
|
||||
}
|
||||
|
||||
}
|
||||
@ -277,40 +259,14 @@ class SiteAdminPanelForm extends AdminForm
|
||||
$this->unli();
|
||||
|
||||
$this->li();
|
||||
$this->out->dropdown('language', _('Language'),
|
||||
get_nice_language_list(), _('Default site language'),
|
||||
$this->out->dropdown('language', _('Default language'),
|
||||
get_nice_language_list(), _('Site language when autodetection from browser settings is not available'),
|
||||
false, $this->value('language'));
|
||||
$this->unli();
|
||||
|
||||
$this->out->elementEnd('ul');
|
||||
$this->out->elementEnd('fieldset');
|
||||
|
||||
$this->out->elementStart('fieldset', array('id' => 'settings_admin_snapshots'));
|
||||
$this->out->element('legend', null, _('Snapshots'));
|
||||
$this->out->elementStart('ul', 'form_data');
|
||||
$this->li();
|
||||
$snapshot = array('web' => _('Randomly during Web hit'),
|
||||
'cron' => _('In a scheduled job'),
|
||||
'never' => _('Never'));
|
||||
$this->out->dropdown('run', _('Data snapshots'),
|
||||
$snapshot, _('When to send statistical data to status.net servers'),
|
||||
false, $this->value('run', 'snapshot'));
|
||||
$this->unli();
|
||||
|
||||
$this->li();
|
||||
$this->input('frequency', _('Frequency'),
|
||||
_('Snapshots will be sent once every N web hits'),
|
||||
'snapshot');
|
||||
$this->unli();
|
||||
|
||||
$this->li();
|
||||
$this->input('reporturl', _('Report URL'),
|
||||
_('Snapshots will be sent to this URL'),
|
||||
'snapshot');
|
||||
$this->unli();
|
||||
$this->out->elementEnd('ul');
|
||||
$this->out->elementEnd('fieldset');
|
||||
|
||||
$this->out->elementStart('fieldset', array('id' => 'settings_admin_limits'));
|
||||
$this->out->element('legend', null, _('Limits'));
|
||||
$this->out->elementStart('ul', 'form_data');
|
||||
|
201
actions/sitenoticeadminpanel.php
Normal file
201
actions/sitenoticeadminpanel.php
Normal file
@ -0,0 +1,201 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Site notice administration panel
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @category Settings
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2010 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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
|
||||
|
||||
/**
|
||||
* Update the site-wide notice text
|
||||
*
|
||||
* @category Admin
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@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 SitenoticeadminpanelAction extends AdminPanelAction
|
||||
{
|
||||
/**
|
||||
* Returns the page title
|
||||
*
|
||||
* @return string page title
|
||||
*/
|
||||
|
||||
function title()
|
||||
{
|
||||
return _('Site Notice');
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructions for using this form.
|
||||
*
|
||||
* @return string instructions
|
||||
*/
|
||||
|
||||
function getInstructions()
|
||||
{
|
||||
return _('Edit site-wide message');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the site notice admin panel form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showForm()
|
||||
{
|
||||
$form = new SiteNoticeAdminPanelForm($this);
|
||||
$form->show();
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save settings from the form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function saveSettings()
|
||||
{
|
||||
$siteNotice = $this->trimmed('site-notice');
|
||||
|
||||
// assert(all values are valid);
|
||||
// This throws an exception on validation errors
|
||||
|
||||
$this->validate($siteNotice);
|
||||
|
||||
$config = new Config();
|
||||
|
||||
$result = Config::save('site', 'notice', $siteNotice);
|
||||
|
||||
if (!$result) {
|
||||
$this->ServerError(_("Unable to save site notice."));
|
||||
}
|
||||
}
|
||||
|
||||
function validate(&$siteNotice)
|
||||
{
|
||||
// Validate notice text
|
||||
|
||||
if (mb_strlen($siteNotice) > 255) {
|
||||
$this->clientError(
|
||||
_('Max length for the site-wide notice is 255 chars.')
|
||||
);
|
||||
}
|
||||
|
||||
// scrub HTML input
|
||||
|
||||
$config = array(
|
||||
'safe' => 1,
|
||||
'deny_attribute' => 'id,style,on*'
|
||||
);
|
||||
|
||||
$siteNotice = htmLawed($siteNotice, $config);
|
||||
}
|
||||
}
|
||||
|
||||
class SiteNoticeAdminPanelForm extends AdminForm
|
||||
{
|
||||
/**
|
||||
* ID of the form
|
||||
*
|
||||
* @return int ID of the form
|
||||
*/
|
||||
|
||||
function id()
|
||||
{
|
||||
return 'form_site_notice_admin_panel';
|
||||
}
|
||||
|
||||
/**
|
||||
* class of the form
|
||||
*
|
||||
* @return string class of the form
|
||||
*/
|
||||
|
||||
function formClass()
|
||||
{
|
||||
return 'form_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Action of the form
|
||||
*
|
||||
* @return string URL of the action
|
||||
*/
|
||||
|
||||
function action()
|
||||
{
|
||||
return common_local_url('sitenoticeadminpanel');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data elements of the form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function formData()
|
||||
{
|
||||
$this->out->elementStart('ul', 'form_data');
|
||||
|
||||
$this->out->elementStart('li');
|
||||
$this->out->textarea(
|
||||
'site-notice',
|
||||
_('Site notice text'),
|
||||
common_config('site', 'notice'),
|
||||
_('Site-wide notice text (255 chars max; HTML okay)')
|
||||
);
|
||||
$this->out->elementEnd('li');
|
||||
|
||||
$this->out->elementEnd('ul');
|
||||
}
|
||||
|
||||
/**
|
||||
* Action elements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function formActions()
|
||||
{
|
||||
$this->out->submit(
|
||||
'submit',
|
||||
_('Save'),
|
||||
'submit',
|
||||
null,
|
||||
_('Save site notice')
|
||||
);
|
||||
}
|
||||
}
|
@ -55,6 +55,7 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
|
||||
function title()
|
||||
{
|
||||
// TRANS: Title for SMS settings.
|
||||
return _('SMS settings');
|
||||
}
|
||||
|
||||
@ -66,6 +67,10 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
|
||||
function getInstructions()
|
||||
{
|
||||
// XXX: For consistency of parameters in messages, this should be a
|
||||
// regular parameters, replaced with sprintf().
|
||||
// TRANS: SMS settings page instructions.
|
||||
// TRANS: %%site.name%% is the name of the site.
|
||||
return _('You can receive SMS messages through email from %%site.name%%.');
|
||||
}
|
||||
|
||||
@ -88,6 +93,7 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
{
|
||||
if (!common_config('sms', 'enabled')) {
|
||||
$this->element('div', array('class' => 'error'),
|
||||
// TRANS: Message given in the SMS settings if SMS is not enabled on the site.
|
||||
_('SMS is not available.'));
|
||||
return;
|
||||
}
|
||||
@ -101,7 +107,8 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
common_local_url('smssettings')));
|
||||
|
||||
$this->elementStart('fieldset', array('id' => 'settings_sms_address'));
|
||||
$this->element('legend', null, _('Address'));
|
||||
// TRANS: Form legend for SMS settings form.
|
||||
$this->element('legend', null, _('SMS address'));
|
||||
$this->hidden('token', common_session_token());
|
||||
|
||||
if ($user->sms) {
|
||||
@ -109,10 +116,12 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
$this->element('p', 'form_confirmed',
|
||||
$user->sms . ' (' . $carrier->name . ')');
|
||||
$this->element('p', 'form_guide',
|
||||
// TRANS: Form guide in SMS settings form.
|
||||
_('Current confirmed SMS-enabled phone number.'));
|
||||
$this->hidden('sms', $user->sms);
|
||||
$this->hidden('carrier', $user->carrier);
|
||||
$this->submit('remove', _('Remove'));
|
||||
// TRANS: Button label to remove a confirmed SMS address.
|
||||
$this->submit('remove', _m('BUTTON','Remove'));
|
||||
} else {
|
||||
$confirm = $this->getConfirmation();
|
||||
if ($confirm) {
|
||||
@ -120,57 +129,75 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
$this->element('p', 'form_unconfirmed',
|
||||
$confirm->address . ' (' . $carrier->name . ')');
|
||||
$this->element('p', 'form_guide',
|
||||
// TRANS: Form guide in IM settings form.
|
||||
_('Awaiting confirmation on this phone number.'));
|
||||
$this->hidden('sms', $confirm->address);
|
||||
$this->hidden('carrier', $confirm->address_extra);
|
||||
$this->submit('cancel', _('Cancel'));
|
||||
// TRANS: Button label to cancel a SMS address confirmation procedure.
|
||||
$this->submit('cancel', _m('BUTTON','Cancel'));
|
||||
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
// TRANS: Field label for SMS address input in SMS settings form.
|
||||
$this->input('code', _('Confirmation code'), null,
|
||||
// TRANS: Form field instructions in SMS settings form.
|
||||
_('Enter the code you received on your phone.'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
$this->submit('confirm', _('Confirm'));
|
||||
// TRANS: Button label to confirm SMS confirmation code in SMS settings.
|
||||
$this->submit('confirm', _m('BUTTON','Confirm'));
|
||||
} else {
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
// TRANS: Field label for SMS phone number input in SMS settings form.
|
||||
$this->input('sms', _('SMS phone number'),
|
||||
($this->arg('sms')) ? $this->arg('sms') : null,
|
||||
// TRANS: SMS phone number input field instructions in SMS settings form.
|
||||
_('Phone number, no punctuation or spaces, '.
|
||||
'with area code'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
$this->carrierSelect();
|
||||
$this->submit('add', _('Add'));
|
||||
// TRANS: Button label for adding a SMS phone number in SMS settings form.
|
||||
$this->submit('add', _m('BUTTON','Add'));
|
||||
}
|
||||
}
|
||||
$this->elementEnd('fieldset');
|
||||
|
||||
if ($user->sms) {
|
||||
$this->elementStart('fieldset', array('id' => 'settings_sms_incoming_email'));
|
||||
// XXX: Confused! This is about SMS. Should this message be updated?
|
||||
// TRANS: Form legend for incoming SMS settings form.
|
||||
$this->element('legend', null, _('Incoming email'));
|
||||
|
||||
if ($user->incomingemail) {
|
||||
$this->element('p', 'form_unconfirmed', $user->incomingemail);
|
||||
$this->element('p', 'form_note',
|
||||
// XXX: Confused! This is about SMS. Should this message be updated?
|
||||
// TRANS: Form instructions for incoming SMS e-mail address form in SMS settings.
|
||||
_('Send email to this address to post new notices.'));
|
||||
$this->submit('removeincoming', _('Remove'));
|
||||
// TRANS: Button label for removing a set sender SMS e-mail address to post notices from.
|
||||
$this->submit('removeincoming', _m('BUTTON','Remove'));
|
||||
}
|
||||
|
||||
$this->element('p', 'form_guide',
|
||||
// XXX: Confused! This is about SMS. Should this message be updated?
|
||||
// TRANS: Instructions for incoming SMS e-mail address input form.
|
||||
_('Make a new email address for posting to; '.
|
||||
'cancels the old one.'));
|
||||
$this->submit('newincoming', _('New'));
|
||||
// TRANS: Button label for adding an SMS e-mail address to send notices from.
|
||||
$this->submit('newincoming', _m('BUTTON','New'));
|
||||
$this->elementEnd('fieldset');
|
||||
}
|
||||
|
||||
$this->elementStart('fieldset', array('id' => 'settings_sms_preferences'));
|
||||
$this->element('legend', null, _('Preferences'));
|
||||
// TRANS: Form legend for SMS preferences form.
|
||||
$this->element('legend', null, _('SMS preferences'));
|
||||
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('smsnotify',
|
||||
// TRANS: Checkbox label in SMS preferences form.
|
||||
_('Send me notices through SMS; '.
|
||||
'I understand I may incur '.
|
||||
'exorbitant charges from my carrier.'),
|
||||
@ -178,7 +205,8 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
|
||||
$this->submit('save', _('Save'));
|
||||
// TRANS: Button label to save SMS preferences.
|
||||
$this->submit('save', _m('BUTTON','Save'));
|
||||
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
@ -245,6 +273,7 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
} else if ($this->arg('confirm')) {
|
||||
$this->confirmCode();
|
||||
} else {
|
||||
// TRANS: Message given submitting a form with an unknown action in SMS settings.
|
||||
$this->showForm(_('Unexpected form submission.'));
|
||||
}
|
||||
}
|
||||
@ -275,13 +304,15 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
|
||||
if ($result === false) {
|
||||
common_log_db_error($user, 'UPDATE', __FILE__);
|
||||
// TRANS: Server error thrown on database error updating SMS preferences.
|
||||
$this->serverError(_('Couldn\'t update user.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$user->query('COMMIT');
|
||||
|
||||
$this->showForm(_('Preferences saved.'), true);
|
||||
// TRANS: Confirmation message for successful SMS preferences save.
|
||||
$this->showForm(_('SMS preferences saved.'), true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -303,11 +334,13 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
// Some validation
|
||||
|
||||
if (!$sms) {
|
||||
// TRANS: Message given saving SMS phone number without having provided one.
|
||||
$this->showForm(_('No phone number.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$carrier_id) {
|
||||
// TRANS: Message given saving SMS phone number without having selected a carrier.
|
||||
$this->showForm(_('No carrier selected.'));
|
||||
return;
|
||||
}
|
||||
@ -315,9 +348,11 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
$sms = common_canonical_sms($sms);
|
||||
|
||||
if ($user->sms == $sms) {
|
||||
// TRANS: Message given saving SMS phone number that is already set.
|
||||
$this->showForm(_('That is already your phone number.'));
|
||||
return;
|
||||
} else if ($this->smsExists($sms)) {
|
||||
// TRANS: Message given saving SMS phone number that is already set for another user.
|
||||
$this->showForm(_('That phone number already belongs to another user.'));
|
||||
return;
|
||||
}
|
||||
@ -334,6 +369,7 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
|
||||
if ($result === false) {
|
||||
common_log_db_error($confirm, 'INSERT', __FILE__);
|
||||
// TRANS: Server error thrown on database error adding SMS confirmation code.
|
||||
$this->serverError(_('Couldn\'t insert confirmation code.'));
|
||||
return;
|
||||
}
|
||||
@ -344,6 +380,7 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
$user->nickname,
|
||||
$carrier->toEmailAddress($sms));
|
||||
|
||||
// TRANS: Message given saving valid SMS phone number that is to be confirmed.
|
||||
$msg = _('A confirmation code was sent to the phone number you added. '.
|
||||
'Check your phone for the code and instructions '.
|
||||
'on how to use it.');
|
||||
@ -367,10 +404,12 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
$confirm = $this->getConfirmation();
|
||||
|
||||
if (!$confirm) {
|
||||
// TRANS: Message given canceling SMS phone number confirmation that is not pending.
|
||||
$this->showForm(_('No pending confirmation to cancel.'));
|
||||
return;
|
||||
}
|
||||
if ($confirm->address != $sms) {
|
||||
// TRANS: Message given canceling SMS phone number confirmation for the wrong phone number.
|
||||
$this->showForm(_('That is the wrong confirmation number.'));
|
||||
return;
|
||||
}
|
||||
@ -379,11 +418,13 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
|
||||
if (!$result) {
|
||||
common_log_db_error($confirm, 'DELETE', __FILE__);
|
||||
// TRANS: Server error thrown on database error canceling SMS phone number confirmation.
|
||||
$this->serverError(_('Couldn\'t delete email confirmation.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->showForm(_('Confirmation cancelled.'), true);
|
||||
// TRANS: Message given after successfully canceling SMS phone number confirmation.
|
||||
$this->showForm(_('SMS confirmation cancelled.'), true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -402,6 +443,8 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
// Maybe an old tab open...?
|
||||
|
||||
if ($user->sms != $sms) {
|
||||
// TRANS: Message given trying to remove an SMS phone number that is not
|
||||
// TRANS: registered for the active user.
|
||||
$this->showForm(_('That is not your phone number.'));
|
||||
return;
|
||||
}
|
||||
@ -417,12 +460,14 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
$result = $user->updateKeys($original);
|
||||
if (!$result) {
|
||||
common_log_db_error($user, 'UPDATE', __FILE__);
|
||||
// TRANS: Server error thrown on database error removing a registered SMS phone number.
|
||||
$this->serverError(_('Couldn\'t update user.'));
|
||||
return;
|
||||
}
|
||||
$user->query('COMMIT');
|
||||
|
||||
$this->showForm(_('The address was removed.'), true);
|
||||
// TRANS: Message given after successfully removing a registered SMS phone number.
|
||||
$this->showForm(_('The SMS phone number was removed.'), true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -462,10 +507,12 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
// TRANS: Label for mobile carrier dropdown menu in SMS settings.
|
||||
$this->element('label', array('for' => 'carrier'), _('Mobile carrier'));
|
||||
$this->elementStart('select', array('name' => 'carrier',
|
||||
'id' => 'carrier'));
|
||||
$this->element('option', array('value' => 0),
|
||||
// TRANS: Default option for mobile carrier dropdown menu in SMS settings.
|
||||
_('Select a carrier'));
|
||||
while ($carrier->fetch()) {
|
||||
$this->element('option', array('value' => $carrier->id),
|
||||
@ -473,6 +520,8 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
}
|
||||
$this->elementEnd('select');
|
||||
$this->element('p', 'form_guide',
|
||||
// TRANS: Form instructions for mobile carrier dropdown menu in SMS settings.
|
||||
// TRANS: %s is an administrative contact's e-mail address.
|
||||
sprintf(_('Mobile carrier for your phone. '.
|
||||
'If you know a carrier that accepts ' .
|
||||
'SMS over email but isn\'t listed here, ' .
|
||||
@ -495,6 +544,7 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
$code = $this->trimmed('code');
|
||||
|
||||
if (!$code) {
|
||||
// TRANS: Message given saving SMS phone number confirmation code without having provided one.
|
||||
$this->showForm(_('No code entered'));
|
||||
return;
|
||||
}
|
||||
|
251
actions/snapshotadminpanel.php
Normal file
251
actions/snapshotadminpanel.php
Normal file
@ -0,0 +1,251 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Snapshots administration panel
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @category Settings
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2010 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')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage snapshots
|
||||
*
|
||||
* @category Admin
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@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 SnapshotadminpanelAction extends AdminPanelAction
|
||||
{
|
||||
/**
|
||||
* Returns the page title
|
||||
*
|
||||
* @return string page title
|
||||
*/
|
||||
|
||||
function title()
|
||||
{
|
||||
return _('Snapshots');
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructions for using this form.
|
||||
*
|
||||
* @return string instructions
|
||||
*/
|
||||
|
||||
function getInstructions()
|
||||
{
|
||||
return _('Manage snapshot configuration');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the snapshots admin panel form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showForm()
|
||||
{
|
||||
$form = new SnapshotAdminPanelForm($this);
|
||||
$form->show();
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save settings from the form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function saveSettings()
|
||||
{
|
||||
static $settings = array(
|
||||
'snapshot' => array('run', 'reporturl', 'frequency')
|
||||
);
|
||||
|
||||
$values = array();
|
||||
|
||||
foreach ($settings as $section => $parts) {
|
||||
foreach ($parts as $setting) {
|
||||
$values[$section][$setting] = $this->trimmed($setting);
|
||||
}
|
||||
}
|
||||
|
||||
// This throws an exception on validation errors
|
||||
|
||||
$this->validate($values);
|
||||
|
||||
// assert(all values are valid);
|
||||
|
||||
$config = new Config();
|
||||
|
||||
$config->query('BEGIN');
|
||||
|
||||
foreach ($settings as $section => $parts) {
|
||||
foreach ($parts as $setting) {
|
||||
Config::save($section, $setting, $values[$section][$setting]);
|
||||
}
|
||||
}
|
||||
|
||||
$config->query('COMMIT');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
function validate(&$values)
|
||||
{
|
||||
// Validate snapshot run value
|
||||
|
||||
if (!in_array($values['snapshot']['run'], array('web', 'cron', 'never'))) {
|
||||
$this->clientError(_('Invalid snapshot run value.'));
|
||||
}
|
||||
|
||||
// Validate snapshot frequency value
|
||||
|
||||
if (!Validate::number($values['snapshot']['frequency'])) {
|
||||
$this->clientError(_('Snapshot frequency must be a number.'));
|
||||
}
|
||||
|
||||
// Validate report URL
|
||||
|
||||
if (!is_null($values['snapshot']['reporturl'])
|
||||
&& !Validate::uri(
|
||||
$values['snapshot']['reporturl'],
|
||||
array('allowed_schemes' => array('http', 'https')
|
||||
)
|
||||
)) {
|
||||
$this->clientError(_('Invalid snapshot report URL.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SnapshotAdminPanelForm extends AdminForm
|
||||
{
|
||||
/**
|
||||
* ID of the form
|
||||
*
|
||||
* @return int ID of the form
|
||||
*/
|
||||
|
||||
function id()
|
||||
{
|
||||
return 'form_snapshot_admin_panel';
|
||||
}
|
||||
|
||||
/**
|
||||
* class of the form
|
||||
*
|
||||
* @return string class of the form
|
||||
*/
|
||||
|
||||
function formClass()
|
||||
{
|
||||
return 'form_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Action of the form
|
||||
*
|
||||
* @return string URL of the action
|
||||
*/
|
||||
|
||||
function action()
|
||||
{
|
||||
return common_local_url('snapshotadminpanel');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data elements of the form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function formData()
|
||||
{
|
||||
$this->out->elementStart(
|
||||
'fieldset',
|
||||
array('id' => 'settings_admin_snapshots')
|
||||
);
|
||||
$this->out->element('legend', null, _('Snapshots'));
|
||||
$this->out->elementStart('ul', 'form_data');
|
||||
$this->li();
|
||||
$snapshot = array(
|
||||
'web' => _('Randomly during web hit'),
|
||||
'cron' => _('In a scheduled job'),
|
||||
'never' => _('Never')
|
||||
);
|
||||
$this->out->dropdown(
|
||||
'run',
|
||||
_('Data snapshots'),
|
||||
$snapshot,
|
||||
_('When to send statistical data to status.net servers'),
|
||||
false,
|
||||
$this->value('run', 'snapshot')
|
||||
);
|
||||
$this->unli();
|
||||
|
||||
$this->li();
|
||||
$this->input(
|
||||
'frequency',
|
||||
_('Frequency'),
|
||||
_('Snapshots will be sent once every N web hits'),
|
||||
'snapshot'
|
||||
);
|
||||
$this->unli();
|
||||
|
||||
$this->li();
|
||||
$this->input(
|
||||
'reporturl',
|
||||
_('Report URL'),
|
||||
_('Snapshots will be sent to this URL'),
|
||||
'snapshot'
|
||||
);
|
||||
$this->unli();
|
||||
$this->out->elementEnd('ul');
|
||||
$this->out->elementEnd('fieldset');
|
||||
}
|
||||
|
||||
/**
|
||||
* Action elements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function formActions()
|
||||
{
|
||||
$this->out->submit(
|
||||
'submit',
|
||||
_('Save'),
|
||||
'submit',
|
||||
null,
|
||||
_('Save snapshot settings')
|
||||
);
|
||||
}
|
||||
}
|
@ -143,9 +143,12 @@ class SubscribersListItem extends SubscriptionListItem
|
||||
function showActions()
|
||||
{
|
||||
$this->startActions();
|
||||
if (Event::handle('StartProfileListItemActionElements', array($this))) {
|
||||
$this->showSubscribeButton();
|
||||
// Relevant code!
|
||||
$this->showBlockForm();
|
||||
Event::handle('EndProfileListItemActionElements', array($this));
|
||||
}
|
||||
$this->endActions();
|
||||
}
|
||||
|
||||
@ -154,10 +157,36 @@ class SubscribersListItem extends SubscriptionListItem
|
||||
$user = common_current_user();
|
||||
|
||||
if (!empty($user) && $this->owner->id == $user->id) {
|
||||
$bf = new BlockForm($this->out, $this->profile,
|
||||
array('action' => 'subscribers',
|
||||
'nickname' => $this->owner->nickname));
|
||||
$returnto = array('action' => 'subscribers',
|
||||
'nickname' => $this->owner->nickname);
|
||||
$page = $this->out->arg('page');
|
||||
if ($page) {
|
||||
$returnto['param-page'] = $page;
|
||||
}
|
||||
$bf = new BlockForm($this->out, $this->profile, $returnto);
|
||||
$bf->show();
|
||||
}
|
||||
}
|
||||
|
||||
function linkAttributes()
|
||||
{
|
||||
$aAttrs = parent::linkAttributes();
|
||||
|
||||
if (common_config('nofollow', 'subscribers')) {
|
||||
$aAttrs['rel'] .= ' nofollow';
|
||||
}
|
||||
|
||||
return $aAttrs;
|
||||
}
|
||||
|
||||
function homepageAttributes()
|
||||
{
|
||||
$aAttrs = parent::linkAttributes();
|
||||
|
||||
if (common_config('nofollow', 'subscribers')) {
|
||||
$aAttrs['rel'] = 'nofollow';
|
||||
}
|
||||
|
||||
return $aAttrs;
|
||||
}
|
||||
}
|
||||
|
@ -196,12 +196,30 @@ class SubscriptionsListItem extends SubscriptionListItem
|
||||
$this->out->hidden('token', common_session_token());
|
||||
$this->out->hidden('profile', $this->profile->id);
|
||||
if (common_config('xmpp', 'enabled')) {
|
||||
$this->out->checkbox('jabber', _('Jabber'), $sub->jabber);
|
||||
$attrs = array('name' => 'jabber',
|
||||
'type' => 'checkbox',
|
||||
'class' => 'checkbox',
|
||||
'id' => 'jabber-'.$this->profile->id);
|
||||
if ($sub->jabber) {
|
||||
$attrs['checked'] = 'checked';
|
||||
}
|
||||
|
||||
$this->out->element('input', $attrs);
|
||||
$this->out->element('label', array('for' => 'jabber-'.$this->profile->id), _('Jabber'));
|
||||
} else {
|
||||
$this->out->hidden('jabber', $sub->jabber);
|
||||
}
|
||||
if (common_config('sms', 'enabled')) {
|
||||
$this->out->checkbox('sms', _('SMS'), $sub->sms);
|
||||
$attrs = array('name' => 'sms',
|
||||
'type' => 'checkbox',
|
||||
'class' => 'checkbox',
|
||||
'id' => 'sms-'.$this->profile->id);
|
||||
if ($sub->sms) {
|
||||
$attrs['checked'] = 'checked';
|
||||
}
|
||||
|
||||
$this->out->element('input', $attrs);
|
||||
$this->out->element('label', array('for' => 'sms-'.$this->profile->id), _('SMS'));
|
||||
} else {
|
||||
$this->out->hidden('sms', $sub->sms);
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ class TagAction extends Action
|
||||
|
||||
if($this->page > 1 && $this->notice->N == 0){
|
||||
// TRANS: Server error when page not found (404)
|
||||
$this->serverError(_('No such page'),$code=404);
|
||||
$this->serverError(_('No such page.'),$code=404);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -102,12 +102,17 @@ class TagAction extends Action
|
||||
|
||||
function showContent()
|
||||
{
|
||||
if(Event::handle('StartTagShowContent', array($this))) {
|
||||
|
||||
$nl = new NoticeList($this->notice, $this);
|
||||
|
||||
$cnt = $nl->show();
|
||||
|
||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$this->page, 'tag', array('tag' => $this->tag));
|
||||
|
||||
Event::handle('EndTagShowContent', array($this));
|
||||
}
|
||||
}
|
||||
|
||||
function isReadOnly($args)
|
||||
|
@ -35,6 +35,7 @@ class TagrssAction extends Rss10Action
|
||||
$this->clientError(_('No such tag.'));
|
||||
return false;
|
||||
} else {
|
||||
$this->notices = $this->getNotices($this->limit);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
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