1212 Commits

Autor SHA1 Mensagem Data
Mikael Nordfeldth b2cfbded2e Upgrading from 1.1.x would make uri fields have length=255 2016-03-15 16:54:10 +01:00
Mikael Nordfeldth 346a73c36f Fix a regression in 1f76c1e4 that stopped sending email confirmation on registration 2016-03-02 14:38:34 +01:00
Mikael Nordfeldth 6336248d71 Notice getRendered() can now be called on uninserted notices 2016-02-25 20:13:00 +01:00
Mikael Nordfeldth 67aff528f5 socialfy-your-domain made people think you needed manual interaction
I don't know why, but people started following those instructions for no
apparent reason and it ended up causing a bunch of federation issues or
homegrown cron script messes.

Maybe changing the name to "another" instead of "your" domain will make
people stop doing stuff randomly.
2016-02-25 20:12:56 +01:00
Mikael Nordfeldth 80f7a5f025 $metadata->thumbnail_url is not guaranteed to be set
We should probably have a separate class for this, so we can more
easily combine different technologies similar to oEmbed/OpenGraph.
2016-02-25 19:47:16 +01:00
Mikael Nordfeldth e6f07d8554 Use in_array instead. Now we get third party responses to contextually interesting threads
I think this solves much of the "third party conversation" issues, assuming involved parties
are using modern GNU social instances.
2016-02-24 00:19:27 +01:00
Mikael Nordfeldth 31c9b2c1d8 Check the notice context for users in UsersalmonAction 2016-02-23 23:56:43 +01:00
Mikael Nordfeldth 9319033ff0 Properly attach activityobjects
For some reason they were written to ->object, which is incorrect as
we use the objects[] array (which usually just holds one entry though)
2016-02-23 23:50:57 +01:00
Mikael Nordfeldth 0eb5122817 Check that the user is in the context of a salmon slap 2016-02-23 23:42:41 +01:00
Mikael Nordfeldth d672547112 getAliases should be only a list (numeric array) 2016-02-23 14:33:09 +01:00
Mikael Nordfeldth e16f7d04a8 Let OpenID match against aliases (fix fancyurl stuff etc.) 2016-02-23 14:15:08 +01:00
Mikael Nordfeldth b59dacb806 getAliases for Profile and Notice
Also move fancyurlfix into site-wide $config['fix']['fancyurls']

TODO: getByUri should make use of this directly I guess?
2016-02-23 14:00:59 +01:00
Mikael Nordfeldth 5f7032dfee Verify that authenticated API calls are made from our domain name.
Evil forms on other websites could otherwise potentially be configured
to have action="https://gnusocial.example/api/statuses/update.json" or
whatever. XHR is already blocked with CORS stuff.

Really, why do browsers allow cross domain POSTs at all? Sigh. The web.
2016-02-22 15:19:10 +01:00
Mikael Nordfeldth c67b89e56b Make WebFinger fancyurlfix configurable 2016-02-21 20:05:32 +01:00
Mikael Nordfeldth ce803f6d06 WebFinger aliases with 'index.php/' 2016-02-21 20:00:07 +01:00
Mikael Nordfeldth 1edb1bbc17 Claim that we are the URL without index.php/ in webfinger response 2016-02-21 19:09:39 +01:00
Mikael Nordfeldth 893d117309 throw new, not just throw 2016-02-21 19:01:37 +01:00
Mikael Nordfeldth 0c17c32267 Let the WebFingerPlugin lookup profile resources with index.php/ too 2016-02-21 18:48:48 +01:00
Mikael Nordfeldth 23e66bef64 common_fake_local_fancy_url to remove index.php/ from a local URL 2016-02-21 18:48:18 +01:00
Mikael Nordfeldth d16a883e17 Allow lookup of User->getByUri (throws NoResultException) 2016-02-21 18:47:47 +01:00
Mikael Nordfeldth b23cc7465f Keep a unique set of WebFingerResource aliases 2016-02-21 18:47:32 +01:00
Mikael Nordfeldth afbdcf8938 Don't publish mbox_sha1sum in FOAF by default.
We say the email is private data, so reasonably we shouldn't reveal it
indirectly through a hash sum: http://xmlns.com/foaf/spec/#term_mbox_sha1sum
2016-02-19 00:10:05 +01:00
Mikael Nordfeldth a838c90951 Only show "public:site" in ToSelector if notice/allowprivate is true 2016-02-18 00:33:16 +01:00
Mikael Nordfeldth f68d1ade3f Put "Everyone" and "Everyone at [local instance]" at the top of ToSelector 2016-02-18 00:32:09 +01:00
Mikael Nordfeldth 543d968b81 NoAcctUriException->profile not $e directly 2016-02-18 00:13:59 +01:00
Mikael Nordfeldth a361fdbd77 Sort ToSelector by AcctUri 2016-02-18 00:05:09 +01:00
Mikael Nordfeldth 73dbc5ca1b Use ToSelector choice again. 2016-02-17 23:44:15 +01:00
Mikael Nordfeldth d9b649642d Show notice feed URLs (and author) 2016-02-17 23:32:56 +01:00
Mikael Nordfeldth d2c11925bf To-selector padlock only shown if site config notice/allowprivate is true 2016-02-17 23:06:11 +01:00
Mikael Nordfeldth 5fbb01130a By default, disallow users to set private_stream 2016-02-17 22:58:31 +01:00
Mikael Nordfeldth 47dc15c9f6 Describe that we don't allow empty fullnames. 2016-02-17 22:48:32 +01:00
Mikael Nordfeldth d6bf90cfb7 If profile fullname is 0 chars use nickname 2016-02-17 22:43:45 +01:00
Mikael Nordfeldth ade4518ae4 Make the Link header give URI for WebFinger lookup 2016-02-17 22:36:33 +01:00
Mikael Nordfeldth 422d475e44 Differentiate two similar log warning messages 2016-02-17 21:57:52 +01:00
Mikael Nordfeldth d2507a6266 Gotta declare FullNoticeStream as abstract class 2016-02-16 02:24:38 +01:00
Mikael Nordfeldth 46829c6d3c FullNoticeStream selects all verbs. 2016-02-16 02:21:39 +01:00
Mikael Nordfeldth 2d1b70c94d created column was ambigououuuouuus 2016-02-15 09:59:34 +01:00
Mikael Nordfeldth 2301862ae6 We only want POST and SHARE in the inbox/home timeline right? 2016-02-15 09:59:18 +01:00
Mikael Nordfeldth dcb7ce36d8 Show shares in public timeline
Also, the unselect rule for DELETE was useless anyway since it would
already have been filtered out by not having true.

(the => false stuff are for when you want ALL _except_ that)
2016-02-14 20:53:26 +01:00
Mikael Nordfeldth e2a090c9cc Use NoticeStream::filterVerbs for filtering in noticestreams 2016-02-14 20:46:13 +01:00
Mikael Nordfeldth c23c3a4f53 Might as well put a FILTER_SANITIZE_EMAIL there
Not that I think we could break out of the directory since
we use basename, but you never know... maybe there's a unicode
bug in PHP or something.
2016-02-13 14:06:05 +01:00
Mikael Nordfeldth 4bf26eff4c socialfy-your-domain updated for webfinger (not tested) 2016-02-13 13:57:15 +01:00
Mikael Nordfeldth be14e15dac Hide attachments in notices by silenced profiles 2016-02-13 13:17:39 +01:00
Mikael Nordfeldth fbcca62ae1 listGet was not meant for that really 2016-02-13 01:19:47 +01:00
Mikael Nordfeldth 8ef2abf30b Render RegiserThrottle extra profile data properly 2016-02-13 01:16:34 +01:00
Mikael Nordfeldth 799c2e47fe Don't depend on ModLog 2016-02-13 01:10:01 +01:00
Mikael Nordfeldth be35975b12 RegisterThrottle list-profiles-by-ip 2016-02-13 01:02:18 +01:00
Mikael Nordfeldth 557ad2d1fd Show user registration IP to users who can see ModLog 2016-02-13 00:51:43 +01:00
Mikael Nordfeldth c7c34ec05a Only administrators can delete other privileged users. 2016-02-12 15:00:18 +01:00
Mikael Nordfeldth 83f679fb57 Profile->isPrivileged() to check if users have more rights than to post etc. 2016-02-12 14:47:49 +01:00
Mikael Nordfeldth 3cef75bcac Update the comment on silencing privileged users in ModHelper 2016-02-12 14:47:44 +01:00
Mikael Nordfeldth e5ad98e601 Silence action can only be used on non-priviliged users 2016-02-12 14:22:25 +01:00
Mikael Nordfeldth 5dce08d068 Add Profile::ensureCurrent() to verify we _certainly_ got a Profile. 2016-02-12 13:52:48 +01:00
Mikael Nordfeldth f10625f8bc file and avatar dirs on instances with no such dirs in filesystem 2016-02-12 02:29:33 +01:00
Mikael Nordfeldth 338df7e35b Fix Nickname::isSystemPath() work properly for routes 2016-02-12 02:21:11 +01:00
Mikael Nordfeldth c8753353ed Do not delete_orphan_files on an instance with Qvitter 2016-02-12 01:45:47 +01:00
Mikael Nordfeldth 913595780f And LEFT JOIN to actually get all results 2016-02-12 00:05:36 +01:00
Mikael Nordfeldth 1471defff3 ...and avoid duplicate results... 2016-02-11 23:38:12 +01:00
Mikael Nordfeldth 05fea4cdc6 Aurhg, and get all the properties, not just id 2016-02-11 22:54:29 +01:00
Mikael Nordfeldth 2198f39597 Haha, it essentially became a NOOP with the last commit 2016-02-11 22:49:45 +01:00
Mikael Nordfeldth 6f2fbd448d Fixed the delete orphan script to include deleted notices
The file_to_post table sometimes had post_id with values that did not
exist in the notice table.
2016-02-11 22:43:26 +01:00
Mikael Nordfeldth 38a187b93e Delete orphan files maintenance script
When deleting a profile it'll delete its notices and the coupling to
file entries, but not the file entries themselves (and thus not the
files). So if one to delete a person uploading offending images, then
the images are left behind and can be hotlinked. This will remove it.
2016-02-11 22:19:56 +01:00
Mikael Nordfeldth 7fdcbd56d5 XMPP URI scheme for HTMLPurifier 2016-02-11 21:31:50 +01:00
Mikael Nordfeldth 67dfc0a046 application/xml allowed in uploads 2016-02-11 00:04:14 +01:00
Mikael Nordfeldth b9d35659c8 Stricter exception check 2016-02-10 04:43:30 +01:00
Mikael Nordfeldth 733debd9b3 Use thumbnail upscaling config value 2016-02-10 04:40:54 +01:00
Mikael Nordfeldth 8806cce735 Default to avoid upscaling of thumbnails. 45x45=>450x450 is ugly 2016-02-10 04:40:10 +01:00
Mikael Nordfeldth dd229e855a Allow finding the "original remote thumbnail"
This will probably cause older oEmbed images not to show, since they
probably were updated to use empty url entries because they were thought
of as local ones. During a migration period maybe you want to change
the default value of notNullUrl to 'false' in File_thumbnail::byFile(...)
2016-02-10 04:37:43 +01:00
Mikael Nordfeldth 893d888152 Add urlhash field to File_thumbnail for indexing 2016-02-10 04:15:41 +01:00
Mikael Nordfeldth 49b7648fea Managed_DataObject gets onInsert and onUpdate 2016-02-10 03:37:27 +01:00
Mikael Nordfeldth d0b2d86ca1 background is not used, so removed from documentation 2016-02-10 02:32:17 +01:00
Mikael Nordfeldth 9f961597c6 Document site/sslproxy config value
Should be put into installation configuration too. Maybe a sample
and commented out entry in config.php as well.
2016-02-10 01:11:43 +01:00
Mikael Nordfeldth a61235086b Use config site/sslproxy to force HTTPS (i.e. using reverse proxy to enable it)
Usage in config.php: $config['site']['sslproxy'] = true;

Add this to documentation...
2016-02-10 01:05:02 +01:00
Mikael Nordfeldth ec257d940a Either use or don't use HTTPS
The risk of injection attacks using HTTP is too great to allow a
site that allows both HTTP and HTTPS...
2016-02-10 00:57:39 +01:00
Mikael Nordfeldth dcf29c2a07 s/isHTTPS/useHTTPS/ for HTTPS URL generation 2016-02-10 00:38:14 +01:00
Mikael Nordfeldth eaa394ed7d bitcoin schema for HTMLPurifier 2016-02-08 20:20:31 +01:00
Mikael Nordfeldth 7c90d7022b Require the license with HTML5 2016-02-08 17:56:35 +01:00
Mikael Nordfeldth ef5ed10eb9 Log failed captcha entries 2016-02-08 17:51:21 +01:00
Mikael Nordfeldth cd71188d3a SimpleCaptcha plugin to stop basic bots 2016-02-08 17:47:09 +01:00
Mikael Nordfeldth a30d34be7f Returnto the previous page when deleting a notice. 2016-02-08 15:30:28 +01:00
Mikael Nordfeldth d98784e059 Use functions instead of accessing properties in twitterUserArray 2016-02-08 12:21:58 +01:00
Mikael Nordfeldth 3dea259f52 Return intval from getID() 2016-02-08 12:21:46 +01:00
Mikael Nordfeldth 2938b3e960 Don't return true on requiresAuth if screen_name==='0' 2016-02-08 12:14:35 +01:00
Mikael Nordfeldth 13cf744fb3 Allow screennames that are === '0' 2016-02-08 11:40:46 +01:00
Mikael Nordfeldth 2686635f60 Keep the rel="tag" in HTML when purifying 2016-02-07 12:50:26 +01:00
Mikael Nordfeldth 1126f70786 Merge branch 'master' into mmn_fixes 2016-02-07 02:35:44 +01:00
Mikael Nordfeldth 7c7f2f890f Hidespam by default
...why would something described as "Whether to hide silenced users from timelines"
be set to false by default? :)
2016-02-07 02:35:21 +01:00
Mikael Nordfeldth d6664f5735 Hidespam by default
...why would something described as "Whether to hide silenced users from timelines"
be set to false by default? :)
2016-02-07 02:33:53 +01:00
Mikael Nordfeldth 58e852f7f7 Use the -y parameter for ffmpeg/avconv to be non-interactive 2016-02-07 01:59:21 +01:00
Mikael Nordfeldth 6bec22ea4e Write to the tmp file in VideoThumbnails 2016-02-07 01:57:56 +01:00
Mikael Nordfeldth 25f623565a Catch http exception in StoreRemoteMedia 2016-02-07 01:54:37 +01:00
Mikael Nordfeldth 098c8b1df4 NoHttpResponseException extends HTTP_Request2_ConnectionException 2016-02-07 01:52:20 +01:00
Mikael Nordfeldth 55546a5aab Support ffmpeg and avconv depending on which you have 2016-02-07 01:02:59 +01:00
Mikael Nordfeldth 41e36e1f28 Unknown functionality of a script
Something added 6-8 years ago which we don't use anymore...
2016-02-04 12:16:36 +01:00
Mikael Nordfeldth 1f01356076 Fix issue #127 by catching exceptions
update-profile-data.php threw exceptions on http connection issues
2016-02-04 12:06:35 +01:00
Mikael Nordfeldth 60804d1902 ES3 compatibility layer not necessary (noone uses IE8 etc.)
All browsers with javascript support also support ES5 nowadays. Anyone
using older software should upgrade for other reasons, such as security.
2016-02-04 11:37:24 +01:00
Mikael Nordfeldth d5ecbd05a1 Forgot a break in a switch when rendering attachments. 2016-02-03 19:32:51 +01:00
Mikael Nordfeldth 9960714896 Disallow zero-length magnet URIs
magnet: would match, but now we have a zero-length lookahead which
requires the following character to be a question mark: magnet:?
2016-02-03 15:26:19 +01:00
Mikael Nordfeldth 90045d66ea HTMLPurifierSchemes plugin to allow geo and magnet URIs 2016-02-03 14:36:51 +01:00
Mikael Nordfeldth 2c83614170 HTMLPurifier caches were included accidentally 2016-02-03 14:35:26 +01:00
Mikael Nordfeldth 349dba8be0 Only allow our specified URI schemes 2016-02-03 14:31:16 +01:00
Mikael Nordfeldth e903bd0bc3 Hacky support for geo URI detection
Won't work with common_purify yet because there is no geo uri scheme for it
2016-02-03 14:19:08 +01:00
Mikael Nordfeldth b1ed1f48ea Configurable linkify for bare IPv4/IPv6 2016-02-03 12:55:00 +01:00
Mikael Nordfeldth 25c15119bc Backupaccount is always readonly 2016-02-03 01:15:35 +01:00
Mikael Nordfeldth 84930f89f9 Don't allow account backups by default. 2016-02-03 01:08:36 +01:00
Mikael Nordfeldth 19b743a9f5 Set time limit to increase time backupaccount can take
Wills till run out of memory probably, we should fix that.
2016-02-03 01:04:14 +01:00
Mikael Nordfeldth 9fcfb7cb1d Proper error message on too much POST data 2016-02-03 01:03:58 +01:00
Mikael Nordfeldth 6a4aa34b0c Don't process further in redirection if HEAD gives 400 Bad request 2016-02-03 00:34:49 +01:00
Mikael Nordfeldth 40cffb9463 File::isProtected is static 2016-02-03 00:22:18 +01:00
Mikael Nordfeldth a2b914ce60 Get URL schemes by URL type 2016-02-03 00:18:37 +01:00
Mikael Nordfeldth 43abfe659b Bump beta number to 4
We have better webfinger @mention@capability.example at least and
OpportunisticQM is somewhat refined.
2016-01-30 00:04:18 +01:00
Mikael Nordfeldth 367fc054dc Merge branch 'master' into mmn_fixes 2016-01-30 00:03:25 +01:00
Mikael Nordfeldth 771f08b3c7 Merge branch 'master' of git.gnu.io:gnu/gnu-social 2016-01-30 00:02:56 +01:00
Mikael Nordfeldth 5167b1fa40 Don't trust local HTML either
If we reallyreally want to include <img> or <script> or whatever then we
have to do that after Notice::saveActivity sets ->rendered.
2016-01-30 00:02:03 +01:00
Mikael Nordfeldth c6ae883ad2 Don't trust local HTML either
If we reallyreally want to include <img> or <script> or whatever then we
have to do that after Notice::saveActivity sets ->rendered.
2016-01-30 00:00:37 +01:00
Mikael Nordfeldth a5c1b063fd isPerson did not exist for Ostatus_profile 2016-01-29 16:15:06 +01:00
Mikael Nordfeldth 689e277c62 Allow @localuser@mysite.example to be looked up as a mention 2016-01-29 16:06:16 +01:00
Mikael Nordfeldth 36f099958c Don't match @nickname on @nickname@server.com 2016-01-29 15:53:58 +01:00
Mikael Nordfeldth cb40f72c7e Use the profile URI when linking instead of URL
since we'll then get to /user/$id instead of /$nickname which is
good for future archives if someone changes their nickname...
2016-01-29 15:21:01 +01:00
Mikael Nordfeldth 5b11238010 Don't use system include path
Sometimes systems have _old_ DB_DataObject classes lying around that
get included by default, so we just try to avoid anything that we don't
ship ourselves.

<MMN-o> BeS: I'll commit a patch that will make this issue go away
<BeS> MMN-o: that would be awesome!
<MMN-o> but it might upset bashrc who's working on a Debian package (where you're _supposed_ to include from /usr/php etc. :P)
<MMN-o> but I'll leave a comment along with it
2016-01-28 20:31:46 +01:00
Mikael Nordfeldth 6b31feb70f Strict Standards: Declaration of MysqlSchema::get()
should be compatible with Schema::get($conn = NULL)
2016-01-28 20:18:06 +01:00
Mikael Nordfeldth a6898b033d Fullname and location are now text, not varchar, and can be >191|255 2016-01-28 19:12:30 +01:00
Mikael Nordfeldth c0851d59f5 migrateProfilePrefs added to scripts/upgrade.php
Makes it easier for plugin developers to change the topics set in Profile_prefs
2016-01-28 19:03:24 +01:00
Mikael Nordfeldth fb7f572eed Purify oembed html (again)
For a commit or two we didn't do this, because htmLawed failed to filter
out CDATA javascript properly, but now we use HTML Purifier which works.
2016-01-28 19:02:16 +01:00
Mikael Nordfeldth 7e6783bb8f Replace htmLawed with HTMLPurifier 2016-01-28 19:01:13 +01:00
Mikael Nordfeldth daea5647b6 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into mmn_fixes 2016-01-28 17:27:08 +01:00
mmn 9b3cbb373e Merge branch 'oembed_fb_wp_branch' into 'nightly'
Oembed: Fix UTF-8 bug and better wp&fb data (updated!)



See merge request !97
2016-01-28 16:26:33 +00:00
Mikael Nordfeldth efe23ed404 updateWithKeys now understands multi-column keys
and automatically identifies _which_ columns are the right ones,
so for example 'uri' primary keys don't need to be explicitly set
2016-01-28 16:42:59 +01:00
hannes 05439831e7 add comment that DOMDocument('1.0', 'UTF-8') does not work 2016-01-28 15:32:11 +00:00
hannes 06e325d61b fixes two issues when the oembed thumbnail is blank 2016-01-28 15:19:29 +00:00
Mikael Nordfeldth d94f9031ff Changelog deleted in php-gettext 2016-01-28 14:43:01 +01:00
Mikael Nordfeldth 10f16e4f32 php-gettext extlib updated as req !88
Thanks postblue
2016-01-28 14:41:25 +01:00
Mikael Nordfeldth c459bded53 Markdown library updated to 1.6.0, merge req !90
Thanks postblue
2016-01-28 14:37:14 +01:00
Mikael Nordfeldth fb15dc5080 htmLawed updated (manually merging !89)
Thanks postblue
2016-01-28 14:24:03 +01:00
mmn bf38fb7bef Merge branch 'upstream-changes/google-analytics-removal' into 'master'
Removed plugin Google-Analytics

... as this is free/libre and decentralized software and should not promote centralized proprietary software. Please see the included Piwik plugin for a more decentralized alternative!

See merge request !94
2016-01-28 12:55:10 +00:00
Mikael Nordfeldth 7c80c9a1f9 Meh, let's just remove FirePHP, I don't think anyone uses it 2016-01-28 13:48:44 +01:00
mmn dfc11f99ad Merge branch 'update-extlib-firephp' into 'nightly'
Update FirefPHP Core to v0.4.0 released on 23 Apr 2013



See merge request !92
2016-01-28 12:41:34 +00:00
Mikael Nordfeldth bb0cb9b3f6 Manual merge of !87 Update LDAP2 extlib to 2.2.0 (stable) released on 2015-10-30
Thanks postblue
2016-01-28 13:35:23 +01:00
Mikael Nordfeldth d73c264e25 Haha, forgot that the $content content must also be there! 2016-01-27 23:04:19 +01:00
Mikael Nordfeldth 34093388a7 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into mmn_fixes 2016-01-27 22:43:37 +01:00
Mikael Nordfeldth a47563cf3d Don't add space if there's no string in new notice content 2016-01-27 22:41:53 +01:00
Mikael Nordfeldth 03d2b680f8 Allow empty new-notice content via web if there's an upload 2016-01-27 22:39:43 +01:00
mmn 52778e1882 Merge branch 'json_encode_fail_branch' into 'nightly'
output error if json_encode fails



See merge request !86
2016-01-26 21:16:24 +00:00
mmn 42545c6625 Merge branch 'mention_branch' into 'nightly'
correct mentions if parent mentions multiple users with same nickname (don't use first one for all)



See merge request !82
2016-01-26 21:15:25 +00:00
Mikael Nordfeldth e69715005d Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into mmn_fixes 2016-01-26 22:10:23 +01:00
mmn c01982c917 Merge branch 'oembed_thumbnail_branch' into 'nightly'
add a thumbnail to oembed response

just something i added to quitim

See merge request !85
2016-01-26 21:09:07 +00:00
hannes aa76e5863f don't mess upp charsets in oembed/og! check for utf-8 in http header and meta tags, and add prolog when loading html with DOMDocument() 2016-01-26 13:37:52 +00:00
hannes b8d1e1f4a6 silence errors on these xpath queries 2016-01-26 11:28:24 +00:00
hannes 884aeb4d2e common_purify() doesn't remove wordpress' and facebook's javascript properly, maybe better to keep the data intact, and do strip_tags or something similar when using the data 2016-01-26 01:10:15 +00:00
hannes 473f893d04 detab 2016-01-26 01:07:44 +00:00
hannes 76c8139054 not pretty, but gives us better oembed data for wordpress and facebook 2016-01-26 01:05:53 +00:00
Mikael Nordfeldth a48055a3cc Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into mmn_fixes 2016-01-25 20:22:16 +01:00
mmn c0b0f8e2f9 Merge branch 'file_redirection_cleanup_branch' into 'nightly'
Proper URL redirection fix

This greatly reduces the number of times GNU social looks up the same URL with File_redirection::where().

Someone must have mixed up the exlib's internal setting "follow_redirects" with our own. 

This also makes away with the weird backwards recursive handling of protected URLs in File_redirection::lookupWhere(), by saving the chain of redirects the first time HTTPClient:send() looks them up.

See merge request !95
2016-01-25 19:21:52 +00:00
hannes e447964639 remove my ugly debug info 2016-01-25 19:10:35 +00:00
hannes b1b6a0a69c config['follow_redirects'] is the extlib's config! if max_redirs is set we want to do our own redirection following in this function 2016-01-25 19:03:26 +00:00
hannes a888294135 add our own protected urls 2016-01-25 19:00:46 +00:00
hannes ca0c792ed3 File and File_redirection records are saved in File_redirection::where() now 2016-01-25 19:00:05 +00:00
hannes 48e1a2431b save File and File_redirection records in File_redirection::where(), because then we will have to run where() over and over again 2016-01-25 18:55:48 +00:00
Mikael Nordfeldth b15434375c Show plain text files on attachment page. 2016-01-25 16:54:40 +01:00
Roland Haeder 9614aba0e1 Removed plugin Google-Analytics as this is free/libre and decentralized
software and should not promote centralized proprietary software. Please see
the included Piwik plugin for a more decentralized alternative!

Signed-off-by: Roland Haeder <roland@mxchange.org>
2016-01-25 13:19:43 +01:00
postblue fef52d7b51 Update FirefPHP Core to v0.4.0 released on 23 Apr 2013 2016-01-24 21:11:38 +01:00
Mikael Nordfeldth a9d18a077e Harmonize, clarify, categorize URL schemes
Regular expression + avoid-redirection list now match each other.
2016-01-24 12:47:31 +01:00
Mikael Nordfeldth 1cec627d72 Allow bitcoin scheme to URLs 2016-01-24 12:44:28 +01:00
hannes 4e50717e12 output error if json_encode fails 2016-01-23 15:01:27 +00:00
Mikael Nordfeldth ef005987a1 Did the OpportunisticQM fixes in the wrong order 2016-01-22 12:26:53 +01:00
Mikael Nordfeldth 1121b38eb1 use connect_timeout value for execution margin 2016-01-22 12:21:06 +01:00
Mikael Nordfeldth 89dd44bf3e default connect_timeout to 5 instead of extlib 10 2016-01-22 12:20:03 +01:00
Mikael Nordfeldth 81f9a59f25 use connect_timeout value for execution margin 2016-01-22 12:19:17 +01:00
hannes d0e2f8745d add a thumbnail to oembed response 2016-01-21 18:48:30 +00:00
Mikael Nordfeldth 3f9c1c142a Removing unnecessary debug messages etc. 2016-01-21 02:49:34 +01:00
Mikael Nordfeldth 45446f17ad Only set selectVerbs if it's not set in class var 2016-01-21 02:37:38 +01:00
Mikael Nordfeldth be1759f112 i18n 2016-01-21 02:37:07 +01:00
Mikael Nordfeldth d3a4a2225f We want the profile stream to be as raw as possible! 2016-01-21 02:33:43 +01:00
Mikael Nordfeldth 81bf0fd261 Various last fixes to RSVP I think 2016-01-21 02:20:57 +01:00
Mikael Nordfeldth f74d2d555c Working on some RSVP code stuff 2016-01-21 02:10:34 +01:00
Mikael Nordfeldth 5999171c11 Throw NoObjectTypeException on Notice->getObjectType if no string 2016-01-20 21:37:14 +01:00
Mikael Nordfeldth 45b523bada Add xcal namespaces to location and url in event
Also, for fun, add stuff for RSS event module, see:
   http://web.resource.org/rss/1.0/modules/event/
2016-01-20 21:07:55 +01:00
Mikael Nordfeldth 21cc737f5c Cancelling RSVPs now seems to work. 2016-01-20 16:10:10 +01:00
Mikael Nordfeldth 9accd953e4 Merge branch 'master' into mmn_fixes 2016-01-20 15:33:18 +01:00
Mikael Nordfeldth 64e74d527f Handle exceptions when salmon slapping
Make it so notifyDeferred actually _always_ throws exceptions and handle
them in the places it is called.
2016-01-20 15:32:39 +01:00
Mikael Nordfeldth c393bc9563 In very specific circumstances we can bulkDistribute 0 notices
Seems to be what caused an infinite loop on quitter.es, or I guess so anyway.
2016-01-20 15:32:29 +01:00
Mikael Nordfeldth 912d65c767 bulkDistribute won't add empty lists to database 2016-01-20 15:32:24 +01:00
Mikael Nordfeldth fa8e02b832 Handle exceptions when salmon slapping
Make it so notifyDeferred actually _always_ throws exceptions and handle
them in the places it is called.
2016-01-20 14:56:24 +01:00
hannes de047f9727 correct mentions if parent mention multiple users with same nickname (don't use first one for all) 2016-01-19 13:41:25 +00:00
Mikael Nordfeldth 80dc2788dd Started fiddling with CancelRSVP but more must be done
Remember to make event_uri be the selector for CancelRSVPForm and
preferrably even merge it into RSVPForm!
2016-01-19 01:41:06 +01:00
Mikael Nordfeldth 477d71c0bf RSVP stuff, mostly forms.
Now fix CancelRSVP stuff so it gets by event_uri and can cancel existing RSVP.
2016-01-19 01:33:09 +01:00
Mikael Nordfeldth 84dda697d6 RSVPs seem to be created now, just gotta fix CancelrsvpAction 2016-01-19 01:10:06 +01:00
Mikael Nordfeldth 73992a1ed8 Use "newer" terminology and throw exceptions 2016-01-19 00:21:16 +01:00
Mikael Nordfeldth 9eea255c79 Save with options so we get source=web 2016-01-19 00:08:31 +01:00
Mikael Nordfeldth 358684a5ed end_str, not start_str 2016-01-19 00:01:30 +01:00
Mikael Nordfeldth 385705c65b Events get rendered. 2016-01-18 23:58:32 +01:00
Mikael Nordfeldth 15d12b209d Don't include delete verbs in profile notice stream. 2016-01-18 22:04:42 +01:00
Mikael Nordfeldth 7715ea993b getVerb function in Notice class 2016-01-18 22:02:05 +01:00
Mikael Nordfeldth f768de4b46 default connect_timeout to 5 instead of extlib 10 2016-01-18 22:01:45 +01:00
Mikael Nordfeldth cae344b67b Events are now saved but not displayed properly again 2016-01-18 20:57:44 +01:00
Mikael Nordfeldth 6c46a93a81 Minor improvements on Notice::saveActivity 2016-01-18 19:29:45 +01:00
Mikael Nordfeldth 486a02d60d First steps on making NeweventAction a FormAction
Also saving new Happening objects via Notice::saveActivity
2016-01-18 18:42:42 +01:00
Mikael Nordfeldth 11b925c4ca Use a function to getCreated() 2016-01-18 17:03:37 +01:00
Mikael Nordfeldth c1655c2c0f Merge branch 'master' into mmn_fixes 2016-01-17 00:41:43 +01:00
Mikael Nordfeldth b0416ae592 Initial user doesn't need as strict checking on email 2016-01-17 00:41:03 +01:00
Mikael Nordfeldth 78346af572 Merge branch 'master' of git.gnu.io:gnu/gnu-social 2016-01-17 00:40:14 +01:00
Mikael Nordfeldth bdc38a7204 Initial user doesn't need as strict checking on email 2016-01-17 00:39:49 +01:00
Mikael Nordfeldth 6dc0477c00 Let the remote side know the Salmon was accepted (sorta) 2016-01-16 22:39:59 +01:00
Mikael Nordfeldth deda83fdef Distinguish notice saving errors from others for Salmon 2016-01-16 22:39:04 +01:00
Mikael Nordfeldth 4678546d33 We want exceptions to be noticable in activityhandlerplugin 2016-01-16 21:19:34 +01:00
Mikael Nordfeldth a85a08ff35 Add a check in Notice->asActivityObject that we're actually returning such a thing! 2016-01-16 21:13:26 +01:00
Mikael Nordfeldth 0797ee0871 EmptyIdException doesn't carry ->obj 2016-01-16 21:12:53 +01:00
Mikael Nordfeldth 3019f8f23f dbqueuemanager logic 2016-01-16 21:05:34 +01:00
Mikael Nordfeldth fdfa71a033 Extremely verbose debugging is annoying 2016-01-16 18:04:04 +01:00
Mikael Nordfeldth c559b8ce2a bulkDistribute won't add empty lists to database 2016-01-16 17:34:27 +01:00
Mikael Nordfeldth f53ebdeadb Start handling salmon entries directly with Notice::saveActivity
More to come...
2016-01-16 17:25:29 +01:00
Mikael Nordfeldth 1f76c1e4a9 Initial user doesn't need as strict checking on email 2016-01-16 17:23:50 +01:00
Mikael Nordfeldth 2b67b53112 In very specific circumstances we can bulkDistribute 0 notices
Seems to be what caused an infinite loop on quitter.es, or I guess so anyway.
2016-01-16 17:18:14 +01:00
mmn 44c10bb2aa Merge branch 'oembed_branch' into 'nightly'
purify oembed html and don't allow cdata

hopefully we never need stuff in cdata

reason for this is that this link serves javascript in its oembed data: https://www.maketecheasier.com/switch-windows-10-to-linux/

see:
https://www.maketecheasier.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwww.maketecheasier.com%2Fswitch-windows-10-to-linux%2F

i don't feel we want that in our database.  

See merge request !79
2016-01-15 13:11:35 +00:00
Mikael Nordfeldth a1530b0e68 Removing superflous debug stuff 2016-01-14 22:12:36 +01:00
Mikael Nordfeldth 8df38df5cb Get uploaded media_ids via File::getByID()
Filters out failed ones...
2016-01-14 22:05:03 +01:00
Mikael Nordfeldth 16088d9439 ErrorAction and InfoAction fixes, are now ManagedAction 2016-01-14 21:28:47 +01:00
Mikael Nordfeldth bc0a903bd4 ErrorAction to autodiscoverable file. 2016-01-14 21:21:34 +01:00
Mikael Nordfeldth 818fb05cfe role examples in userrole.php 2016-01-14 20:34:12 +01:00
Mikael Nordfeldth e5019c3858 Accept media_ids parameter from Twitter API v1.1 clients
They upload the media first and then provide media IDs in a comma
separated parameter (but we just split it to all whole integers).
2016-01-14 20:24:01 +01:00
Mikael Nordfeldth b570f0d3cb Media files are accepted and uploaded via Twitter API now 2016-01-14 19:15:02 +01:00
Mikael Nordfeldth 2af9de4f23 Minor fixes in Linkback plugin 2016-01-14 19:14:24 +01:00
Mikael Nordfeldth b530d385bc Exception object was not supplied there 2016-01-14 18:51:46 +01:00
Mikael Nordfeldth 0caf0612d0 Make Twitter Media upload API v1.1 reach us
Now we just have to accept the 'media' or 'media_data' (base64 encoded)
POST arguments instead of $_FILES uploads.
2016-01-14 18:29:21 +01:00
Mikael Nordfeldth 6e49281adb Use the Action class itself as error handler 2016-01-14 18:21:11 +01:00
Mikael Nordfeldth 2f1bfe126b Debug message formatting gone wrong 2016-01-14 13:52:11 +01:00
Mikael Nordfeldth c173c4faa5 Actually throw NoQueueHandlerException too. 2016-01-14 13:48:33 +01:00
Mikael Nordfeldth 59e75ef966 Incorrect use of getByHashKey in HubSub 2016-01-14 13:15:31 +01:00
Mikael Nordfeldth f092026541 Documentation fix from master 2016-01-14 13:11:27 +01:00
Mikael Nordfeldth df00a88cb4 Forgot to add NoRouteMapException to 6834f355f2 2016-01-14 13:07:00 +01:00
Mikael Nordfeldth bacd49a6a8 Don't try to replace http with https if https already exists 2016-01-14 13:06:37 +01:00
mmn 0781c2a7b9 Merge branch 'fix_readme' into 'master'
update readme for OpportunisticQM: array need to contain key/value pairs

according to the doc-block of addPlugin() the array should contain key/value pairs, see https://git.gnu.io/gnu/gnu-social/blob/master/lib/gnusocial.php#L46

I updated the readme for the OpportunisticQM plugin to reflect this.

See merge request !81
2016-01-14 12:03:11 +00:00
Björn Schießle b7c849b5b0 array need to contain key/value pairs 2016-01-14 12:39:39 +01:00
Mikael Nordfeldth 83cb1dfa68 Salmon debugging 2016-01-14 03:48:41 +01:00
Mikael Nordfeldth 6834f355f2 Making ClientExceptions turn into ClientErrorAction
Got some 404s which were presented as 500
2016-01-14 02:47:28 +01:00
Mikael Nordfeldth 99261e0781 Don't LOG_ERR missing paths (misspelling clients aren't errors) 2016-01-14 02:22:47 +01:00
Mikael Nordfeldth 53339ff463 Fake oEmbed version in OpenGraph return object 2016-01-14 02:09:12 +01:00
Mikael Nordfeldth 331abf173b Forgot semicolon 2016-01-14 02:05:33 +01:00
Mikael Nordfeldth f699ffeb8a Exception handling in queue handler logic 2016-01-14 02:04:15 +01:00
Mikael Nordfeldth cf7d2f4d0f Salmon queue handler getByID for exception throwing 2016-01-14 01:51:00 +01:00
Mikael Nordfeldth 0ddaa6ff75 Handle exceptions in QueueHandler classes 2016-01-14 01:47:13 +01:00
Mikael Nordfeldth 0482b7de8e Debugging by indexing callback column in HubSub 2016-01-13 22:57:42 +01:00
Mikael Nordfeldth 24d9d76644 OpenGraph image/thumbnail width and height 2016-01-13 22:07:39 +01:00
Mikael Nordfeldth 1e5770bbcf $this->notice is never unset after prepare 2016-01-13 21:34:15 +01:00
Mikael Nordfeldth adba38ce20 Deleted_notice is pluginified, don't call directly from core 2016-01-13 21:29:23 +01:00
Mikael Nordfeldth 45dd343126 Eventify Notice getAsTimestamp (for Deleted_notice) 2016-01-13 21:01:47 +01:00
Mikael Nordfeldth 29b45bb87a Unnecessary call to User::getKV 2016-01-13 20:08:17 +01:00
Mikael Nordfeldth 8ab98b72ac getLeaseRemaining for FeedSub too 2016-01-13 20:01:00 +01:00
Mikael Nordfeldth 377947c57f s/getLease/getLeaseTime/ just to be a bit more clear 2016-01-13 19:55:17 +01:00
Mikael Nordfeldth 1d26fedf12 Don't store lease seconds, just sub start and end
The seconds can always be calculated from the dates!
2016-01-13 19:45:20 +01:00
Mikael Nordfeldth 494746e665 Minor PuSH comment and debug stuff 2016-01-13 19:25:39 +01:00
Mikael Nordfeldth a5fd4fde25 Request a month long sub lease by default 2016-01-13 19:24:07 +01:00
Mikael Nordfeldth b38a789005 HubSub didn't save sub start and end datetimes 2016-01-13 19:23:34 +01:00
Mikael Nordfeldth 818aaa0578 We didn't get profiles from the new-style attention system 2016-01-13 18:35:25 +01:00
Mikael Nordfeldth 961725205d Try if Profile is a Person (in effect ActivityObject::PERSON) 2016-01-13 18:34:48 +01:00
hannes ee305891c4 purify oembed html 2016-01-13 16:03:38 +00:00
hannes 3e7e3de554 don't allow cdata elements in purified html 2016-01-13 16:01:27 +00:00
Mikael Nordfeldth 5c262a788d Unused, unnecessary and intrusive cookie/storage removed! 2016-01-13 15:22:28 +01:00
Mikael Nordfeldth 3720e37f06 property attribute could be null in meta tags of course 2016-01-13 14:24:00 +01:00
Mikael Nordfeldth 99da1ebe41 Catch NoHttpResponseException when using HTTPClient 2016-01-13 14:17:49 +01:00
Mikael Nordfeldth 3ed632decf NoHttpResponseException needed instead of HTTP_Request2_Exception
HTTP_Request2_Exception assumed an HTTP response status code/line
2016-01-13 14:08:48 +01:00
Mikael Nordfeldth e75472f460 Use the upstream function to get effectiveUrl 2016-01-13 14:00:05 +01:00
Akio Nishimura eceafb84de lib/language.php: rewrited jp as ja. 2016-01-13 13:23:06 +01:00
Mikael Nordfeldth 14bd6daab1 Aspect ratio on elements in inline-attachment list 2016-01-12 23:12:41 +01:00
Mikael Nordfeldth e49e113140 Ugly hack to show thumbnails of otherwise unrepresentable attachments
such as text/html, where the thumbnail has been retrieved via oEmbed/OpenGraph
2016-01-12 15:38:59 +01:00
Mikael Nordfeldth 3658774429 Super-basic OpenGraph image preview support, "works for me" 2016-01-12 15:29:03 +01:00
Mikael Nordfeldth f4feef477b Don't follow redirects on PuSH POST. 2016-01-12 14:32:28 +01:00
Mikael Nordfeldth b696fb4eb1 Mimetypes like image/svg+xml were misinterpreted when guessing
We don't really need the mb_ in mb_strtolower but what the heck, why not. I love Unicode.
2016-01-12 13:46:25 +01:00
Mikael Nordfeldth 8c28e54ccc same as previous, but for mime_to_ext 2016-01-12 13:14:17 +01:00
Mikael Nordfeldth dbe5d72e4c If all file extensions are supported we have no list of comparisons 2016-01-12 13:08:54 +01:00
mmn d07640caba Merge branch 'common_purify_branch' into 'nightly'
EndCommonPurify event

Because we have problems with htmLawed on quitter.se, we want to check its output and maybe use another HTML purifier... 

See merge request !78
2016-01-11 21:14:41 +00:00
mmn e4a1dff98d Merge branch 'apiaccountregister_event_branch' into 'nightly'
APIStartRegistrationTry event



See merge request !77
2016-01-11 21:08:09 +00:00
mmn e94017a552 Merge branch 'hidden-h2s' into 'nightly'
Show H2s in notice content

With notices coming from other sources (e.g. Diaspora) and rich-text plugins
such as Textile/Markdown/TinyMCE, it's possible notices include H2 we want
to display.

See merge request !76
2016-01-11 21:01:26 +00:00
hannes a1b509bb0b forgot we need access to $html too 2016-01-11 20:58:34 +00:00
hannes 8d331b0f35 EndCommonPurify event 2016-01-11 20:54:19 +00:00
hannes 543a7e421e APIStartRegistrationTry event 2016-01-11 20:04:31 +00:00
Mikael Nordfeldth c826fe0af4 $target was klantigtly copied from another debug message 2016-01-11 20:10:38 +01:00
Mikael Nordfeldth bd6efa0e45 Update PuSH callback URL if remote side switched to HTTPS
See the comment in the source on why we're not following Location headers...
2016-01-11 19:55:02 +01:00
Mikael Nordfeldth f24cdf4a80 Much more logging in PushHubAction (OStatus) 2016-01-11 19:54:05 +01:00
Mikael Nordfeldth 1a46d86ca6 lib/util.php quick function to do var_export($var,true)
Immensely useful when debugging and we want to put quotes around strings,
potentially stopping any "evil logging attacks" (where input data masks
as logging data).
2016-01-11 19:52:54 +01:00
Mikael Nordfeldth 93c614c184 Do updateWithKeys properly if someone would like to update PRI 2016-01-11 19:52:33 +01:00
Mikael Nordfeldth c1f22f106b Might as well put a $limit on preg_replace here
Since there will (should) never be more than one ^http in that string anyway.
2016-01-11 18:27:26 +01:00
Mikael Nordfeldth 5b2b969a77 Tag notice streams should only show post verbs 2016-01-11 15:15:23 +01:00
Mikael Nordfeldth 8acf930c45 OpportunisticQM matches against _system_ max_execution_time
Probably never runs if max_execution_time is 0. I'll handle that later.
2016-01-11 13:35:29 +01:00
Mikael Nordfeldth b13f8df79b HTTPClient would return null instead of exception
This caused $response->isOK() tests to call a function on a non-existing object, causing all hell to break loose.
2016-01-11 02:36:59 +01:00
Chimo 63fff7ef47 Show H2s in notice content
With notices coming from other sources (e.g. Diaspora) and rich-text plugins
such as Textile/Markdown/TinyMCE, it's possible notices include H2 we want
to display.
2016-01-10 15:37:30 +00:00
Mikael Nordfeldth 87ae5292b8 NSTALL/UPGRADE documentation edits
No more background folder for example. Also comments on chmod a+w
2016-01-10 10:44:16 +01:00
Mikael Nordfeldth e498bc6b7b Control OpportunisticQM verbosity 2016-01-10 00:51:25 +01:00
Mikael Nordfeldth 7fbf72f9c1 Minor changes to OpportunisticQM for debugging 2016-01-10 00:48:04 +01:00
Mikael Nordfeldth 42dff2742a Put salmon slaps in queues before pushing user Atom feed 2016-01-10 00:29:32 +01:00
Mikael Nordfeldth 67801a5566 Not only local groups should be added to group inbox notificiation table 2016-01-09 15:14:38 +01:00
Mikael Nordfeldth 5ef10a14ef Get group attentions too for outbound notices 2016-01-09 15:06:44 +01:00
Mikael Nordfeldth c3c5a9974d Do proper fromUri lookup on groups too 2016-01-09 14:36:47 +01:00
Mikael Nordfeldth 55aa68b941 CancelGroupForm gets same typing as Join and Leave 2016-01-09 14:13:19 +01:00
Mikael Nordfeldth fbec7c4e75 Issue #121 - use correct Group ID and strict User_group typing 2016-01-09 14:06:50 +01:00
Mikael Nordfeldth d1e609a886 Local user profile getUrl gives dynamically generated URL 2016-01-09 13:47:38 +01:00
Mikael Nordfeldth f143925931 Actually return the group home URL 2016-01-09 13:33:30 +01:00
Mikael Nordfeldth d13483ca20 Wups, $poster could be undefined 2016-01-09 13:15:09 +01:00
Mikael Nordfeldth 33194b3cff Attention goes to the parent notice author too 2016-01-08 02:58:31 +01:00
Mikael Nordfeldth 28cd5640c1 Save attentions to Reply table for backwards compatibility
local users only of course
2016-01-08 01:59:16 +01:00
Mikael Nordfeldth 0463d96392 Add more info in logging call
There shouldn't be *HandleSalmonTarget, only verification of actor and
then Notice::saveActivity()!
2016-01-08 01:52:10 +01:00
Mikael Nordfeldth 4e0ed61f7c OStatus queue handler uses Notice->getAttentionProfiles()
and lots more debugging for LOG_DEBUG
2016-01-08 01:31:47 +01:00
Mikael Nordfeldth e6f2676c5c Default to not include delete verbs in notice streams 2016-01-07 23:33:47 +01:00
Mikael Nordfeldth c48871cf1b Notice from web now saves context->attention too! ;) 2016-01-07 23:24:15 +01:00
Mikael Nordfeldth 6255e1dca3 saveAttentions, trying to move away from saveReply 2016-01-07 23:23:51 +01:00
Mikael Nordfeldth 801ca3531b common_find_attentions to populate activities from content text 2016-01-07 23:23:37 +01:00
Mikael Nordfeldth 3eebf2a353 Don't store the notice object for distrib queue handler, just id 2016-01-07 20:24:59 +01:00
Mikael Nordfeldth cd2695190d BeforePluginCheckSchema event for checkschema.php 2016-01-07 18:45:36 +01:00
Mikael Nordfeldth 1f02dc639e shortenLinks _after_ media upload to be consistent with api 2016-01-07 18:14:45 +01:00
Mikael Nordfeldth be58fd64f5 Use index for File url (urlhash) 2016-01-07 18:13:10 +01:00
Mikael Nordfeldth 6505504411 shortenLinks with a capital L 2016-01-07 18:12:29 +01:00
Mikael Nordfeldth d4be5349b3 think I have managed to show oEmbed images better now 2016-01-07 17:35:37 +01:00
Mikael Nordfeldth 9e5c71e701 Fixed group representation in Directory plugin, also some ->raw calls 2016-01-07 12:58:14 +01:00
Mikael Nordfeldth c02f23e63f Return Profile objects from getGroups in GroupdirectoryAction 2016-01-07 12:35:52 +01:00
Mikael Nordfeldth 5d4b1d0b88 Appropriate exception message in GroupNoProfileException 2016-01-07 12:14:48 +01:00
Mikael Nordfeldth 839ae571d8 Define User_group::$profile_id among class variables 2016-01-07 12:12:27 +01:00
Mikael Nordfeldth e7308b0ecb Max execution time margin for OpportunisticQM
I guess it could continue a bit too long in case it got a really long
(failing, timeouting) HTTP request just before max_execution_time hit.
2016-01-07 11:58:09 +01:00
Mikael Nordfeldth 94392ab00c Index the verb column since we do COUNT(*) based on it 2016-01-07 11:39:46 +01:00
Mikael Nordfeldth 05d3622939 Conversation entries where id==0 would screw up the "re-auto-increment" sequencing 2016-01-06 22:26:17 +01:00
Mikael Nordfeldth 6924bb1d29 Gah and a 302 in the non-exception-handling redirect too 2016-01-06 20:09:59 +01:00
Mikael Nordfeldth a9b5519293 Attachment thumbnail redirect is a 302 redirect
It SHOULD be cached but it might no longer be valid if we empty cache or something.
2016-01-06 20:07:40 +01:00
Mikael Nordfeldth 4d179c6b0c Our URLs are permanent redirects, mind you! 2016-01-06 20:06:14 +01:00
Mikael Nordfeldth 47c7e1b875 Breaking class definitions out into separate files and fixing typing 2016-01-06 19:46:56 +01:00
Mikael Nordfeldth f1c4c64cd9 Don't update stored URLs just because we have a filename
This would overwrite remote URLs with local verisons which removes source href...
The reason one might have filenames for remote URLs is that StoreRemoteMedia plugin
fetches them and uses the filename field.
2016-01-06 19:24:03 +01:00
Mikael Nordfeldth 346e34e543 Return dynamically generated URLs for thumbnails for all locally stored entries 2016-01-06 19:06:29 +01:00
Mikael Nordfeldth 4352d1739d Always generate notice URLs on the fly for local notices
Related to issue #118
2016-01-06 16:24:33 +01:00
Mikael Nordfeldth 1a1e44cdfd Issue #118 wanted better TOR support, now Avatar URLs are not stored
There was no reason to store the generated Avatar URLs because it's so
cheap to generate them on the fly.
2016-01-06 16:14:26 +01:00
Mikael Nordfeldth 7b2036a4b5 Note in the debug log if we render the HTML of a message 2016-01-06 15:37:30 +01:00
Mikael Nordfeldth b596391fcd Avoid having to check for notices without rendered copies in upgrade.php
Always call the Notice->getRendered() function to get a rendered copy.
We could perhaps put some sanitation there too in the future
2016-01-06 15:32:27 +01:00
Mikael Nordfeldth d6ac002639 Get conversation ID from child too in scripts/upgrade.php 2016-01-06 14:57:30 +01:00
Mikael Nordfeldth 4a8e936e19 Somewhat more meaningful error message 2016-01-06 14:10:37 +01:00
Mikael Nordfeldth 0fd2ad649e Conversation IDs (again) no longer based on Notice ID 2016-01-06 13:58:46 +01:00
Mikael Nordfeldth 4b22b0c42a More listitems and lists into separate files + stronger typing 2016-01-06 01:36:46 +01:00
Mikael Nordfeldth 6d9f390ba8 Separating classes into files and stronger typing 2016-01-06 01:30:12 +01:00
Mikael Nordfeldth da2f179ae9 Typing to Profile 2016-01-06 01:25:00 +01:00
Mikael Nordfeldth e577e883f4 Subscriber lists to separate files and also Profile typing 2016-01-06 00:57:31 +01:00
Mikael Nordfeldth 59d3bbe037 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into mmn_fixes 2016-01-06 00:53:20 +01:00
mmn d45457e4a9 Merge branch 'nightly' into 'nightly'
only count post-notices (i.e. don't include activity-notices in statuses_count in the API)



See merge request !73
2016-01-05 23:53:08 +00:00
Mikael Nordfeldth 1946197a1c Merge request #10 by aroque but in a slightly different version 2016-01-06 00:48:03 +01:00
hannes 32549cfd8c $notices->verb = ActivityVerb::POST; 2016-01-05 23:29:48 +00:00
mmn 2c5460eb0e Merge branch 'openid-plugin' into 'nightly'
OpenID plugin: 'openid_only' should be 'openidonly'

To match everywhere else.

See merge request !72
2016-01-05 23:28:28 +00:00
Mikael Nordfeldth 31c8416a8f Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into mmn_fixes 2016-01-06 00:24:41 +01:00
mmn 956e053da6 Merge branch 'lookup_url_fix' into 'nightly'
makes url lookup work and adds full url to href for shortened links



See merge request !74
2016-01-05 23:24:16 +00:00
Mikael Nordfeldth 792b62874e Require Profile for Profile->getLists 2016-01-06 00:18:10 +01:00
hannes 0b4b0de412 longurl in href 2016-01-05 23:14:51 +00:00
hannes 1c25cffbd8 add $redir->redir_url to use in common_linkify() 2016-01-05 23:07:24 +00:00
Mikael Nordfeldth 3d66d960a1 Require Profile for Profile->getOtherTags 2016-01-06 00:07:15 +01:00
hannes 8b78e01d4c $longurl->url is just the same $canon we fed to File_redirection::where() 2016-01-05 23:06:02 +00:00
hannes 64f2f3d976 effectiveUrl seems to contain the url we want 2016-01-05 22:44:06 +00:00
Mikael Nordfeldth 8ad6b8809a Don't abort on too long notices in Notice::saveActivity 2016-01-05 17:31:09 +01:00
hannes e10691abea only count post-notices (i.e. don't include activity-notices in statuses_count in the API) 2016-01-05 14:19:33 +00:00
Mikael Nordfeldth 9a75778b29 If there's no Happening, we can't use the RSVP. 2016-01-05 15:00:34 +01:00
Mikael Nordfeldth 3471213d1c processFeed would abort on certain errors where findLocalObject failed 2016-01-05 15:00:07 +01:00
Mikael Nordfeldth ab93bb009c XSS vulnerability when remote-subscribing
->raw was used on non-filtered strings for some reasons, changed
to ->text.
2016-01-05 12:15:50 +01:00
Mikael Nordfeldth df8c14d66a ProfileMiniList->newListItem changed to match ProfileList->newListItem 2016-01-05 00:09:47 +01:00
Mikael Nordfeldth 701f6ff608 Allow Profile->getCurrentNotice to send scoped profile info
not that we're using it anywhere (yet anyway).
2016-01-04 21:42:24 +01:00
Mikael Nordfeldth 6a16939830 Profile->getCurrentNotice handles PrivateStreamException 2016-01-04 21:38:41 +01:00
Chimo bf0df016e5 OpenID plugin: 'openid_only' should be 'openidonly'
To match everywhere else.
2016-01-04 10:36:05 -05:00
Mikael Nordfeldth de7e8c59e8 Version bump since we've fixed a lot of bugs 2016-01-04 02:19:37 +01:00
Mikael Nordfeldth fb537fb7f4 We would end up with a Managed_DataObject if now match was found
meaning we'd return for example a Notice with empty id (translated into 0)
and thus Faves coming in from remote instances where the fave'd notice was
not found would result in faving the first Notice in a table-wide search,
i.e. often the first post on the instance.

Whoopie!
2016-01-04 02:04:18 +01:00
Mikael Nordfeldth 065e23b1c4 Code cleanup in lib/activityutils.php 2016-01-04 01:58:45 +01:00
Mikael Nordfeldth 00ace6c2df More explicit catch 2016-01-04 01:53:33 +01:00
Mikael Nordfeldth f7a1c8a94c The $options array isn't used here 2016-01-04 01:48:54 +01:00
Mikael Nordfeldth 34b25e6afc Use EmptyIdException in Fave deletion try-catch 2016-01-03 22:57:28 +01:00
Mikael Nordfeldth b4b57bba54 EmptyIdException to make sure we get the right in catch 2016-01-03 22:56:48 +01:00
Mikael Nordfeldth bda30a92bc Fave deletion would fail in some cases with missing profiles or notices 2016-01-03 22:35:49 +01:00
Mikael Nordfeldth 7266a968f9 Err, forgot semicolon. 2016-01-03 22:22:58 +01:00
Mikael Nordfeldth f467b89f40 Try-catch on profile deletion unsubscribe actions 2016-01-03 22:21:03 +01:00
Mikael Nordfeldth 3bddf01350 Somewhat better layout for approving/rejecting subrequests 2016-01-03 20:42:21 +01:00
Mikael Nordfeldth c19964094b Pending subscription requests now work as they should
A slight layout issue with the buttons still persists
2016-01-03 20:27:53 +01:00
Mikael Nordfeldth b374e5f08b If a user has a private stream, assume a moderated subscription policy 2016-01-03 19:33:26 +01:00
Mikael Nordfeldth df0f9547b5 Handle private streams better (failed to show profile before) 2016-01-03 19:16:29 +01:00
Mikael Nordfeldth 7df8a6b731 This version of the EventPlugin won't work with StatusNet any longer 2016-01-03 16:23:44 +01:00
Mikael Nordfeldth aa3028e5d9 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into mmn_fixes 2016-01-03 16:23:07 +01:00
mmn 3251ef3b51 Merge branch 'beautify_profile_list' into 'nightly'
Beautify profiles and groups lists

Some css fixes to make groups and profiles list more consistent:

In base:

* Remove bullets that were floating around
* Reduce font size to fit and look better
* Group nickname is bold
* Same location and full name layout in both groups and profile lists

In neo-gnu:

* Align vertically location  

In neo-quitter:

* Make group list look like profile one
* Small adjustments due to changes to base

How it looks with neo-gnu

Profile:

![profile](https://git.gnu.io/gnu/gnu-social/uploads/c403c85c323bdcaa2fbb7ab10539ad39/profile.png)

Groups:

![group](https://git.gnu.io/gnu/gnu-social/uploads/51276daa838c404bd63cc04b208beaa6/group.png)

How it looks with neo-quitter

Profile:

![profile](https://git.gnu.io/gnu/gnu-social/uploads/d16bc2587025769dac9e2b46a0589999/profile.png)

Group:

![group](https://git.gnu.io/gnu/gnu-social/uploads/125670c8bcf08bcabf2cac0e0bb0661b/group.png)


See merge request !26
2016-01-03 15:22:32 +00:00
Mikael Nordfeldth 95d415257a Merge branch 'nightly' into singpolyma/gnu-social-events-saveObjectFromActivity
Conflicts:
	plugins/Event/EventPlugin.php
	plugins/Event/classes/RSVP.php

I just fixed 'em with magic!
2016-01-03 13:08:34 +01:00
Mikael Nordfeldth 0dc7fcce5b Fixes issue #94 with undefined 'fr'
I just copied the English example...
2016-01-03 00:45:47 +01:00
Mikael Nordfeldth 336f099241 Don't store object type for verbs (as they don't have it) 2016-01-02 16:05:20 +01:00
Mikael Nordfeldth fe328ae5e4 Fix because qvitter supplies a twitter array value which is an array
works for json API, not for XML, so we make an exception here...
2016-01-02 02:01:54 +01:00
Mikael Nordfeldth cf6e06a5dd Avoid exception for invalid URL aborting rendering for parent notice if it fails 2016-01-02 00:09:10 +01:00
Mikael Nordfeldth 0dfafe2567 NewnoticeAction now uses Notice::saveActivity(...) 2016-01-01 20:18:54 +01:00
Mikael Nordfeldth 26a6eca94e Location::fromOptions(Notice::locationOptions(...)) 2016-01-01 19:29:31 +01:00
Mikael Nordfeldth f4309ed715 whitespace switch for code layout 2016-01-01 18:43:37 +01:00
Mikael Nordfeldth e02c10a589 common_render_content doesn't require a Profile now 2016-01-01 18:40:58 +01:00
Mikael Nordfeldth 54325e266f upgrade script makes sure all notices have rendered copies 2016-01-01 18:30:38 +01:00
Mikael Nordfeldth ad4beb9091 ->getID() instead of ->id 2016-01-01 18:21:54 +01:00
Mikael Nordfeldth 10973dcf69 Don't require a notice object to common_linkify_mentions 2016-01-01 18:20:42 +01:00
Mikael Nordfeldth 86106b890a Output fixed sizes of thumbnails so we don't get jumpy scrolling 2016-01-01 14:13:16 +01:00
Mikael Nordfeldth 4fc2b2584b RSVPs refer to Happening (event) by URI instead of ID now 2015-12-31 19:23:05 +01:00
Mikael Nordfeldth 34ce2f6cfa minor happening changes 2015-12-31 18:08:12 +01:00
Mikael Nordfeldth f6df44ea85 Handle feed imports with exceptions better 2015-12-31 15:05:35 +01:00
Mikael Nordfeldth 7adf1c99fc s/LOG_ERROR/LOG_ERR/ 2015-12-31 13:04:50 +01:00
Mikael Nordfeldth 7f1ce07e9f Logging destinations and unnecessary debug 2015-12-31 13:00:20 +01:00
Mikael Nordfeldth fab745c6d6 Exception throwing and proper db retrieval
ActivityModeration plugin and its Deleted_notice class.
2015-12-31 12:42:33 +01:00
Mikael Nordfeldth 6606781916 Proper error message in exception 2015-12-31 12:41:02 +01:00
Mikael Nordfeldth 5ba6be1a87 Deleted_notice had a superfluous field 2015-12-31 12:33:59 +01:00
Mikael Nordfeldth df19791a8f Wups, $notice not $stored in the old function... 2015-12-31 02:37:42 +01:00
Mikael Nordfeldth 8b0fdfb4a0 Notice conversation is perhaps not set yet 2015-12-31 02:35:13 +01:00
Mikael Nordfeldth 7cf6aaecd0 Don't do saveKnownReplies unless it's a verb=post 2015-12-31 02:31:35 +01:00
Mikael Nordfeldth 66289d3e76 Use recently implemented functions in saveKnownReplies 2015-12-31 02:22:49 +01:00
Mikael Nordfeldth 6772d991ae Only provide Notice oEmbed data for local notices 2015-12-31 01:55:18 +01:00
Mikael Nordfeldth f61187a210 local/* is already in root .gitignore 2015-12-31 01:54:34 +01:00
Mikael Nordfeldth bceece3bb9 issue #93 2015-12-30 18:03:45 +01:00
Mikael Nordfeldth b0bf620c61 RecoverpasswordAction uses User->setPassword() 2015-12-30 17:53:43 +01:00
Mikael Nordfeldth 29847f172f setPassword now runs validate too 2015-12-30 17:51:57 +01:00
Mikael Nordfeldth d7a8ee99af Added User->setPassword($password) 2015-12-30 17:44:24 +01:00
Mikael Nordfeldth 998db39b1a Notification mails are sent again fixes ssue #99
The problem was that the ActivityVerbPostPlugin handled 'post' verbs
but didn't handle the notifications for them, so now we're returning
true in the event so the default behaviour (sending to 'getReplies'
recipients) is done by default.
2015-12-30 17:35:47 +01:00
mmn ad5d5f8054 Merge branch 'nightly' into 'nightly'
fixes this issue: https://quitter.se/notice/4344600



See merge request !71
2015-12-30 15:38:19 +00:00
hannes 08be0e5c67 fixes this issue: https://quitter.se/notice/4344600 2015-12-30 01:54:48 +00:00
Mikael Nordfeldth c0ef167514 create storage directories automatically 2015-12-28 00:35:02 +01:00
Mikael Nordfeldth 2f836e2a59 GNU social config paths, removed StatusNet/Laconica 2015-12-28 00:09:06 +01:00
Mikael Nordfeldth 17a65ff873 background folder has never been used for GNU social 2015-12-28 00:00:51 +01:00
Mikael Nordfeldth 7f4b51e246 minor tuning to nginx example config
for example we really do wish to force people to use HTTPS ;)
2015-12-27 23:58:10 +01:00
Mikael Nordfeldth 4bc0b374bc File_redirection should get URLs properly 2015-12-27 21:36:23 +01:00
Mikael Nordfeldth bd00ef839d split() is deprecated and should be explode()
We don't need the regexpness anyway.
2015-12-27 15:22:38 +01:00
Mikael Nordfeldth 556d6e198f Confirm_address field address_extra _can_ be NULL 2015-12-27 15:01:28 +01:00
Mikael Nordfeldth cf916141d0 Group membership URI needs dataobjects not IDs 2015-12-27 13:01:24 +01:00
Mikael Nordfeldth feb6b636f4 File_oembed varchar to text changes
No need to have text length limitations in the database for fields which
very well may be longer than what was previously set.
2015-12-27 12:11:29 +01:00
Mikael Nordfeldth 12d77ac3e4 varchar to text since there's no reason to limit the fields
They caused problems when quitter.se was upgrading because someone was
named ryanjjjjjjjjjjjjjjjjjjj[and more than 191 'j's] etc.
2015-12-27 11:50:11 +01:00
Mikael Nordfeldth 4a31e4992d Clarify that notices are also deleted with nukefile.php 2015-12-27 11:43:25 +01:00
Mikael Nordfeldth 6026dcaed1 Report if the email was not sent! 2015-12-27 02:16:12 +01:00
Mikael Nordfeldth 62c4ffe889 Server exceptions should reasonably be 5xx 2015-12-27 02:15:37 +01:00
Mikael Nordfeldth b76461fc78 syntax error 2015-12-27 01:42:03 +01:00
Mikael Nordfeldth 0ac71c2b7b Duplicate URI means we have it already, I assume 2015-12-27 01:40:00 +01:00
Mikael Nordfeldth 83c112e24b Handle lack of parent nicely 2015-12-26 16:36:03 +01:00
Mikael Nordfeldth 306df3dc3b Logging fixes 2015-12-26 16:27:06 +01:00
mmn ace47a4512 Merge branch 'rm-design-config-doc' into 'nightly'
Remove $config['design'] documentation

I believe those options are gone since
36d619480a

Ref. #109 

See merge request !70
2015-12-23 21:04:25 +00:00
mmn 48f31928e9 Merge branch 'autocomplete-group' into 'nightly'
Autocomplete group

Group autocompletion wasn't working for a couple of reasons:

1. $profile wasn't set (d8092207c0)
2. Profile::getUri() wasn't working for Groups, causing Profile::getAcctUri() to throw a ProfileNoAcctUriException (3e830dad37)

See merge request !68
2015-12-23 21:04:18 +00:00
mmn 4904c2bc10 Merge branch 'profile-prefs-getall' into 'nightly'
Fixup Profile_prefs::getAll() 

Ref. #98 

See merge request !69
2015-12-23 21:03:55 +00:00
Chimo cc26c4cb1a Remove $config['design'] documentation
I believe those options are gone since
36d619480a
2015-12-21 17:53:30 +00:00
Chimo 90945e548b Profile_prefs::getAll fix prefs loop
DataObject::fetch doesn't return an object.
2015-12-17 14:58:06 +00:00
Chimo 71119e4980 Profile_prefs::getAll fix call to listFind
2nd argument needs to be an array
2015-12-17 14:55:39 +00:00
Chimo 3e830dad37 Make Profile::getUri work with Groups
and by extension Profile::getAcctUri
2015-12-15 21:50:10 -05:00
Chimo d8092207c0 Autocomplete: Fix $profile being null for groups 2015-12-15 21:48:18 -05:00
Mikael Nordfeldth bb0faaea56 Merge branch 'mmn_fixes' into nightly 2015-12-15 12:34:12 +01:00
Mikael Nordfeldth f5ed66280b $url should've been $file->getUrl() 2015-12-15 12:31:10 +01:00
Mikael Nordfeldth 2b4a6c7dd7 Don't check Link header if not set 2015-12-15 11:51:16 +01:00
Mikael Nordfeldth ef4c11d262 Better checks for defined array indexes 2015-12-15 11:50:57 +01:00
Mikael Nordfeldth 0d39337683 Merge branch 'master' into nightly 2015-12-14 22:11:26 +01:00
mmn 67c0c1b6c5 Merge branch 'send-twitter-replies-to-twitter' into 'master'
Always send Twitter replies to Twitter

If is_twitter_notice($notice->reply_to) then send it to Twitter, even
if twitter import is off.  It's a reply to a Twitter notice, it should
go there!

(Also retweets.)

See merge request !42
2015-12-14 21:10:57 +00:00
mmn 0baa9debbc Merge branch 'direct-feed-sub' into 'master'
If we are given a direct URL to a feed, use that



See merge request !54
2015-12-14 21:09:56 +00:00
mmn 1644608376 Merge branch 'twitter-show-rel-syndication' into 'master'
Include rel-syndication link for tweets

As per: <http://microformats.org/wiki/rel-syndication>
This allows some services to find a post in Twitter.

See merge request !44
2015-12-14 21:09:08 +00:00
mmn 0e91a38c9c Merge branch 'firefox-sub-link' into 'master'
Link to add to Firefox as feedreader

This allows easily subscribing to any feed firefox detects in your GNU Social instance.

See merge request !55
2015-12-14 21:08:22 +00:00
mmn 0f938ff234 Merge branch 'fix-twitter-uri' into 'master'
Twitter URIs have changed

The #! was deprecated ages ago, and Twitter forces HTTPS these days.

See merge request !43
2015-12-14 21:07:48 +00:00
Mikael Nordfeldth c2ea85a5e2 Merge branch 'master' into nightly 2015-12-14 22:07:06 +01:00
mmn 1be376cf87 Merge branch 'inbound-linkback' into 'master'
Accept mentions/replies/rsvps/likes via pingback and webmention

This makes the Linkback plugin bidirectional, allowing reply/mention federation between GNU Social and any pingback-enabled service (including any Wordpress site).

See merge request !41
2015-12-14 21:05:25 +00:00
mmn 1eff108561 Merge branch 'twitter-check-dupe-by-uri' into 'master'
TwitterBridge also check for dupe by uri

In case a twitter item came in from some other source (such as linkback).

See merge request !45
2015-12-14 21:04:22 +00:00
mmn 2addf8e456 Merge branch 'repost-of-uf2' into 'master'
Mark up link to original as a repost for repeats

http://indiewebcamp.com/repost

See merge request !46
2015-12-14 21:03:38 +00:00
Mikael Nordfeldth ef4e61c91b Merge branch 'master' into nightly 2015-12-14 22:03:04 +01:00
Mikael Nordfeldth 4ea396f871 Merge branch 'master' into mmn_fixes 2015-12-14 22:01:50 +01:00
mmn edd62e58fd Merge branch 'at-mention-url' into 'master'
MentionURL Plugin

This plugin enables users to use the syntax `@twitter.com/singpolyma` to mention users the system does not know about, or to be more specific when a nickname is ambiguous.

See merge request !53
2015-12-14 21:01:42 +00:00
mmn 8d26d83d7a Merge branch 'group-join-approve-reject-button-icons' into 'nightly'
Add icons to group-join approval/rejection buttons

Relates to #106 

See merge request !66
2015-12-14 20:48:36 +00:00
mmn 2dd968f94e Merge branch 'group-join-rejections' into 'nightly'
Fix group-join request rejections

Relates to #105 

See merge request !65
2015-12-14 20:48:18 +00:00
mmn d5d8068632 Merge branch 'group-members-pending' into 'nightly'
Fix "pending members" group list

Related to #104 

See merge request !64
2015-12-14 20:47:47 +00:00
mmn 5f0412b9ee Merge branch 'api-docs' into 'nightly'
Add AtomPub, Twitter-compat. API documentation to doc-src/



See merge request !62
2015-12-14 20:47:17 +00:00
Mikael Nordfeldth 289116cb64 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-12-14 21:45:46 +01:00
Mikael Nordfeldth 20592f184d getID() will complain loudly if something is wrong
(just ->id would not)
2015-12-14 21:44:59 +01:00
Mikael Nordfeldth 42c653a9d0 Merge commit '5c4a7a10' into nightly
hannes making sure notice is a repeat and not a delete activity notice
2015-12-14 21:42:08 +01:00
mmn c114c6bbad Merge branch 'php-minversion-detec' into 'nightly'
installer::checkPrereqs bump PHP version to 5.5.0

Related to #102 

See merge request !63
2015-12-14 20:37:53 +00:00
mmn 129bd1bf03 Merge branch 'fix-setpassword' into 'nightly'
Fix /scripts/setpassword.php

common_munge_password is expecting a Profile, we were passing a user_id.

Thanks @aroque for the fix ( ref. #100 )

See merge request !67
2015-12-14 20:37:26 +00:00
Mikael Nordfeldth d659e0aaf9 We have to print/echo when outputting json (thanks hannes) 2015-12-14 21:31:10 +01:00
Mikael Nordfeldth 8d1105fe73 We have to print/echo when outputting json (thanks hannes) 2015-12-14 21:29:39 +01:00
Mikael Nordfeldth 441e2c8d34 redir_info only has data if we ran discovery 2015-12-08 11:42:09 +01:00
Mikael Nordfeldth 4fecda58ff Full identifiers for Autocomplete, less confusing 2015-12-05 16:18:59 +01:00
Mikael Nordfeldth 376d545082 Remember to purify HTML... 2015-12-05 15:56:50 +01:00
Mikael Nordfeldth c498db147a ircs URLs work fine in Firefox at least 2015-12-05 13:02:49 +01:00
Chimo 10bb4cb659 Fix /scripts/setpassword.php
common_munge_password is expecting a Profile, we were passing a user_id.

Thanks @aroque for the fix ( ref. #100 )
2015-12-04 17:09:06 +00:00
Chimo b537696370 Add icons to group-join approval/rejection buttons 2015-12-04 17:00:35 +00:00
Chimo 6d9ea620a3 Fix group-join request rejections 2015-12-04 16:11:15 +00:00
Chimo a06dc57621 Fix "pending members" group list 2015-12-04 15:47:40 +00:00
Chimo 3e16e31080 installer::checkPrereqs bump PHP version to 5.5.0 2015-12-04 15:22:58 +00:00
Mikael Nordfeldth 831e9db7ec Various minor theme enhancements in neo-gnu 2015-11-30 02:31:51 +01:00
Mikael Nordfeldth 4479d780e5 List groups with nickname instead of full name in sidebar 2015-11-30 02:21:17 +01:00
Mikael Nordfeldth 334a0d56e7 Oembed slimmed to only do discovery (soon we get og: discovery too) 2015-11-30 02:06:04 +01:00
Mikael Nordfeldth 8bab642cc7 quickGetJson for HTTP requests to return json objects 2015-11-30 02:05:06 +01:00
Mikael Nordfeldth b7edac2610 HTTPClient get $params array and oEmbedHelper uses it 2015-11-30 01:28:18 +01:00
Chimo c95f74018d Add AtomPub, Twitter-compat. API documentation to doc-src/ 2015-11-24 13:00:32 -05:00
Mikael Nordfeldth fbe0e68617 Events listing, but the stream will change soon 2015-11-23 14:40:59 +01:00
Mikael Nordfeldth 5b847eff12 bump beta version number 2015-11-23 00:42:13 +01:00
Mikael Nordfeldth bca4bb8373 allow form ->li() to set $class 2015-11-23 00:40:28 +01:00
Mikael Nordfeldth b01484a0a3 Managed_DataObject::newUri was called improperly 2015-11-23 00:39:49 +01:00
hannes 5c4a7a1052 make sure returned notice is a repeat, i.e. not a delete activity notice 2015-11-22 20:28:07 +00:00
hannes 1eba33590b ActivityVerb::SHARE instead of http://activitystrea.ms/schema/1.0/share 2015-11-22 20:26:08 +00:00
hannes 70695a1463 make sure the notice is a repeat, i.e. not a delete activity notice that also can have a repeat_of set 2015-11-22 18:59:56 +00:00
Mikael Nordfeldth 1630424797 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-11-20 18:50:26 +01:00
mmn b33b40db45 Merge branch 'refactor-file-processNew' into 'nightly'
Refactor on File::processNew

The code was so involved there was even a comment asking for a refactor.

Now, File_redirection::where always returns a nice File_redirection
object instead of an array or string or nothing.  The object is
either one which already existed or else a new, unsaved object.

Instead of duplicating "does it exist" checks everywhere, do it in
File_redirection::where.  You either get what exists or something to save.

An unsaved File_redirection may be paired with an unsaved File.
You will want to save the File first (using ->saveFile()) and put the
id in File_redirection#file_id before saving.

See merge request !57
2015-11-20 17:50:01 +00:00
Mikael Nordfeldth 38c84a92c7 Merge request #59 which was directed at master 2015-11-20 18:47:21 +01:00
mmn 5d548d157f Merge branch 'master' into 'master'
block check can't be done inside the same try-expression as Subscription::getSub…

…scription(), since if that throws a NoResultException, the block check will not be done. and if you're blocking someone you are not subscribing to them.

See merge request !59
2015-11-20 17:46:53 +00:00
hannes abb8d1273e block check can't be done inside the same try-expression as Subscription::getSubscription(), since if that throws a NoResultException, the block check will not be done. and if you're blocking someone you are not subscribing to them. 2015-11-19 15:55:11 +00:00
Stephen Paul Weber 4f0fae9e90 Show better source for linback items 2015-11-12 19:07:26 +00:00
Stephen Paul Weber 11810bbf54 Update conversation when we update reply_to
Or repeat_of
2015-11-12 19:06:17 +00:00
Stephen Paul Weber 47db1ab063 Autodiscovery header for webmention 2015-11-12 19:06:17 +00:00
Stephen Paul Weber f09a82268f Ignore self pings 2015-11-12 19:06:17 +00:00
Stephen Paul Weber b95b318052 That never was meant to be in that if 2015-11-12 19:06:16 +00:00
Stephen Paul Weber 6aba21fcd8 Use author-declared URL as URI
Will make brid.gy work better, for example.
2015-11-12 19:06:16 +00:00
Stephen Paul Weber fa1e4620cf Add pingback frontend 2015-11-12 19:06:16 +00:00
Stephen Paul Weber aa4d880148 Search in sub-items for links to the target as well 2015-11-12 19:06:16 +00:00
Stephen Paul Weber 96e0819f00 Catch exception that this generates when there is no result 2015-11-12 19:06:16 +00:00
Stephen Paul Weber c5bdf6924d Fix duplicate detection 2015-11-12 19:06:16 +00:00
Stephen Paul Weber 64ac344efa Update on duplicate linkback
This especially allows mentioning mulitple users, etc.
2015-11-12 19:06:16 +00:00
Stephen Paul Weber b9971e8a80 Linkback to user should work 2015-11-12 19:06:15 +00:00
Stephen Paul Weber 1e3cf08d82 Ignore non-local notices as targets 2015-11-12 19:06:15 +00:00
Stephen Paul Weber dbfb698859 Webmention frontend 2015-11-12 19:06:15 +00:00
Stephen Paul Weber 96fb18da3f Initial helpers for verification and microformats
This will form the backend of all incoming linkbacks.
We verify the linkback is real and then try to form a rich notice
out of it.
2015-11-12 19:06:15 +00:00
Mikael Nordfeldth d0e7203d88 Make it clearer that we're handling group IDs 2015-11-08 23:31:45 +01:00
Mikael Nordfeldth acd4980ab4 Fix federation issue with groups (bad list order) 2015-11-08 23:31:23 +01:00
Mikael Nordfeldth 844670f88d Ooops, copypasted something into the wrong place. 2015-11-08 23:24:20 +01:00
Mikael Nordfeldth 65184782aa OStatus usage of static Validate::* calls fixed 2015-11-08 10:33:41 +01:00
Mikael Nordfeldth f29daa22b6 Merge branch 'master' of git.gnu.io:gnu/gnu-social into nightly 2015-11-06 13:39:17 +01:00
mmn dbdac9cfbe Merge branch 'in-reply-to-uf2' into 'master'
Add direct link to parent notice

This is partly for usability, and partly to make Linkbacks for replies work (when the plugin is enabled).

See merge request !37
2015-11-06 12:39:02 +00:00
Mikael Nordfeldth e40014b4de separate classes into files in DirectMessage plugin 2015-11-06 13:35:45 +01:00
Mikael Nordfeldth c83deecba2 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-11-06 13:33:24 +01:00
mmn 5f999e84d8 Merge branch 'nightly' into 'nightly'
getParent() method will fail if the parent notice does not exist in the notice table

getParent() method will fail if the parent notice does not exist in the notice table. See https://quitter.no/notice/709400

There are situations where a user delete his notice which could be a parent notice to a reply.
The user which replied to this deleted notice will then have broken timeline. 
This is caused by the Notice.getParent() method which tries to return the selection of non existing parent notice.

I've tried this code on quitter.no and it seems to work.

See merge request !35
2015-11-06 12:28:00 +00:00
abjectio 507f9a28c0 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-11-05 17:34:34 +01:00
Mikael Nordfeldth 7ccd36849e Merge branch 'master' of git.gnu.io:gnu/gnu-social into nightly
Conflicts:
	plugins/OStatus/OStatusPlugin.php

master vs. nightly thing
2015-11-05 16:16:02 +01:00
mmn f345f1d605 Merge branch 'renew-pshb' into 'master'
Actually use the renew code

We have the code to check once a day and renew, but currently it's
just in a script directory.  This change adds an event listener
hook to check and renew subscriptions daily.

Closes #83

See merge request !38
2015-11-05 15:13:16 +00:00
mmn deb5275c7a Merge branch 'object-types-are-absolute' into 'master'
Stop incorrecly changing object_type to relative URI

All other data is using absolute URI for object_type.

See merge request !40
2015-11-05 15:12:41 +00:00
mmn 959f971a65 Merge branch 'fix-webfinger-link-header' into 'master'
Add all link headers, not just the last one

Given the way Link headers work, it does not make any sense to
just replace all other ones.  Especially when we ourselves are adding
in a loop.

See merge request !47
2015-11-05 15:12:10 +00:00
mmn 9f83e60f25 Merge branch 'pings-interop' into 'master'
Clean up Linkback plugin and add Webmention support

Closes #82

Fixes Pingback, adds Webmention, makes linkbacks opt-out-able for users (at request of quitter.se admin)

See merge request !36
2015-11-05 15:11:29 +00:00
Mikael Nordfeldth 0e32729e59 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-11-05 16:07:42 +01:00
Mikael Nordfeldth c950f18546 Merge branch 'master' into nightly
Some merge requests that were aimed at master
2015-11-05 16:07:05 +01:00
mmn 96e0867d4c Merge branch 'master' into 'master'
update URL

bugz.foocorp.net and gitorious.net are outdated
git.gnu.io is current

See merge request !58
2015-11-05 15:05:55 +00:00
mmn 45b24286e5 Merge branch 'status-204' into 'master'
Accept 204 for PuSH subscription

Some hubs (notably, pushpress, used by wordpress.com) return 204 to mean success.

This used to be allowed by the spec, so no harm in accepting it.

See merge request !48
2015-11-05 15:03:42 +00:00
mmn f513ceac7d Merge branch 'handle-rss-guid' into 'master'
Respect isPermalLink=false on RSS guid



See merge request !49
2015-11-05 15:02:20 +00:00
mmn 5c768d7ef7 Merge branch 'twitter-verb' into 'nightly'
TwitterBridge: Add $notice->verb on import

Since /plugins/ActivityModeration::onStartNotieSave expects it to be there when calling ActivityUtils::compareVerbs. Otherwise, the following exception is unhandled:

2015-10-26 15:33:03 LOG_ERR: [sn.chromic.org:queuedaemon.php:25931] Unhandled exception: No URI to resolve in ActivityUtils::resolveUri  
 0: /lib/activityutils.php(353): ActivityUtils::resolveUri(NULL)  
 1: /lib/activityutils.php(364): ActivityUtils::compareTypes(NULL, Array)  
 2: /plugins/ActivityModeration/ActivityModerationPlugin.php(113): ActivityUtils::compareVerbs(NULL, Array)  
 3: [internal function]: ActivityModerationPlugin->onStartNoticeSave(Object(Notice))  
 4: /lib/event.php(105): call_user_func_array(Array, Array)  
 5: /plugins/TwitterBridge/lib/twitterimport.php(173): Event::handle('StartNoticeSave', Array)  
 6: /plugins/TwitterBridge/lib/twitterimport.php(72): TwitterImport->saveStatus(Object(stdClass))  
 7: /plugins/TwitterBridge/lib/tweetinqueuehandler.php(52): TwitterImport->importStatus(Object(stdClass))  
 8: /lib/dbqueuemanager.php(94): TweetInQueueHandler->handle(Array)  
 9: /lib/iomaster.php(287): DBQueueManager->poll()  
 10: /lib/iomaster.php(161): IoMaster->poll()  
 11: /scripts/queuedaemon.php(111): IoMaster->service()  
 12: /lib/spawningdaemon.php(189): QueueDaemon->runThread()  
 13: /lib/spawningdaemon.php(118): SpawningDaemon->initAndRunChild(2)  
 14: /lib/daemon.php(168): SpawningDaemon->run()  
 15: /scripts/queuedaemon.php(181): Daemon->runOnce()  
 16: {main}

See merge request !50
2015-11-05 15:01:07 +00:00
mmn 4b7c904fe0 Merge branch 'correct-author-for-repeat' into 'master'
Markup correct author for a repeat

The original author is not the author of this entry, but of the original entry.

See merge request !51
2015-11-05 15:00:35 +00:00
mmn a3ddc4ec0c Merge branch 'support-atom-namespaces-in-rss-author' into 'master'
Support more author types on RSS

Specifically, any ActivityStreams or ATOM namespaces being used on
an rss channel.

See merge request !52
2015-11-05 15:00:07 +00:00
mmn 3ca4af6868 Merge branch 'group-join' into 'nightly'
Add User_group::getObjectType

Since 174586bd51, I'm unable to join groups with the logs complaining
about getObjectType not existing on the User_group object.

Note: I'm not sure if this is the correct value to return here, but I
was able to joing groups successfully using this. Let me know if it needs
to be changed and I'll update the Merge Request!

See merge request !56
2015-11-05 14:57:29 +00:00
Matthias Fritzsche ba623d2b4e update URL
bugz.foocorp.net and gitorious.net are outdated
git.gnu.io is current
2015-11-04 12:31:23 +01:00
Stephen Paul Weber a9b1b60a97 Refactor on File::processNew
The code was so involved there was even a comment asking for a refactor.

Now, File_redirection::where always returns a nice File_redirection
object instead of an array or string or nothing.  The object is
either one which already existed or else a new, unsaved object.

Instead of duplicating "does it exist" checks everywhere, do it in
File_redirection::where.  You either get what exists or something to save.

An unsaved File_redirection may be paired with an unsaved File.
You will want to save the File first (using ->saveFile()) and put the
id in File_redirection#file_id before saving.
2015-11-02 05:15:08 +00:00
Chimo d7b58491ce Add User_group::getObjectType
Since 174586bd51, I'm unable to join groups with the logs complaining
about getObjectType not existing on the User_group object.
2015-10-29 20:11:57 -04:00
Stephen Paul Weber a74572b469 Use mb_strlen 2015-10-28 01:46:08 +00:00
Stephen Paul Weber 6ac8b845bf Improvements inspired by the OStatus code 2015-10-28 01:45:51 +00:00
Stephen Paul Weber fe4c8a771b Replace text with nickname if shorter 2015-10-28 01:24:58 +00:00
Stephen Paul Weber 0aa759fab7 Allow mentioning bare domains with OStatus 2015-10-28 01:24:42 +00:00
Stephen Paul Weber 2edf535ecd Add length argument to plugin 2015-10-28 01:24:29 +00:00
Stephen Paul Weber 85d5cfede5 Link to add to Firefox as feedreader 2015-10-28 01:10:28 +00:00
Stephen Paul Weber e58c529c53 If we are given a direct URL to a feed, use that 2015-10-28 00:54:20 +00:00
Stephen Paul Weber 2207eacc92 New length format for other kinds of mentions 2015-10-28 00:15:08 +00:00
Stephen Paul Weber fed0895d98 Move the functionality to a plugin
Use an associated model to prevent race conditions on creating the
profile object.
2015-10-28 00:11:54 +00:00
Mikael Nordfeldth 1b81131c51 Shared notices didn't save the URL 2015-10-28 00:13:17 +01:00
Stephen Paul Weber e1de6e0aa9 Support more author types on RSS
Specifically, any ActivityStreams or ATOM namespaces being used on
an rss channel.
2015-10-27 18:43:57 +00:00
Mikael Nordfeldth ebbb9a8990 Bad HTML in translation. 2015-10-27 19:05:07 +01:00
Stephen Paul Weber 54e87dd2c3 Morkup correct author for a repeat
The original author is not the author of this entry, but of the original entry.
2015-10-27 17:19:03 +00:00
Chimo 3ae81f095c TwitterBridge: Add $notice->verb on import
Since /plugins/ActivityModeration::onStartNotieSave expects it to be there when calling ActivityUtils::compareVerbs. Otherwise, the following exception is unhandled:

2015-10-26 15:33:03 LOG_ERR: [sn.chromic.org:queuedaemon.php:25931] Unhandled exception: No URI to resolve in ActivityUtils::resolveUri
 #0 /lib/activityutils.php(353): ActivityUtils::resolveUri(NULL)
 #1 /lib/activityutils.php(364): ActivityUtils::compareTypes(NULL, Array)
 #2 /plugins/ActivityModeration/ActivityModerationPlugin.php(113): ActivityUtils::compareVerbs(NULL, Array)
 #3 [internal function]: ActivityModerationPlugin->onStartNoticeSave(Object(Notice))
 #4 /lib/event.php(105): call_user_func_array(Array, Array)
 #5 /plugins/TwitterBridge/lib/twitterimport.php(173): Event::handle('StartNoticeSave', Array)
 #6 /plugins/TwitterBridge/lib/twitterimport.php(72): TwitterImport->saveStatus(Object(stdClass))
 #7 /plugins/TwitterBridge/lib/tweetinqueuehandler.php(52): TwitterImport->importStatus(Object(stdClass))
 #8 /lib/dbqueuemanager.php(94): TweetInQueueHandler->handle(Array)
 #9 /lib/iomaster.php(287): DBQueueManager->poll()
 #10 /lib/iomaster.php(161): IoMaster->poll()
 #11 /scripts/queuedaemon.php(111): IoMaster->service()
 #12 /lib/spawningdaemon.php(189): QueueDaemon->runThread()
 #13 /lib/spawningdaemon.php(118): SpawningDaemon->initAndRunChild(2)
 #14 /lib/daemon.php(168): SpawningDaemon->run()
 #15 /scripts/queuedaemon.php(181): Daemon->runOnce()
 #16 {main}
2015-10-27 10:12:33 -04:00
Stephen Paul Weber 03c68d283d Respect isPermalLink=false on RSS guid 2015-10-27 03:18:04 +00:00
Stephen Paul Weber 4c2bc465a0 Accept 204 for PuSH subscription
Some hubs (notably, pushpress, used by wordpress.com) return 204 to mean success.

This used to be allowed by the spec, so no harm in accepting it.
2015-10-27 03:16:39 +00:00
Stephen Paul Weber fae7bc0bc0 Add all link headers, not just the last one
Given the way Link headers work, it does not make any sense to
just replace all other ones.  Especially when we ourselves are adding
in a loop.
2015-10-25 18:42:37 +00:00
Stephen Paul Weber dc36621dc2 Linkback to mentioned profiles 2015-10-25 17:22:15 +00:00
Stephen Paul Weber 21979bb7d7 Allow users to @mention URLs
Because inferring who you mean (especially in the presence of remotes) can suck
2015-10-23 21:15:40 +00:00
Stephen Paul Weber 033ed7e4aa Mark up link to original as a repost for repeats
http://indiewebcamp.com/repost
2015-10-23 19:12:25 +00:00
Stephen Paul Weber cd22be3374 Only show parent wrapper if there are some 2015-10-23 18:51:33 +00:00
Stephen Paul Weber ddfb56d920 TwitterBridge also check for dupe by uri
In case a twitter item came in from some other source (such as linkback).
2015-10-23 18:03:44 +00:00
Stephen Paul Weber 983fd75ec9 Include rel-syndication link for tweets
As per: <http://microformats.org/wiki/rel-syndication>
This allows some services to find a post in Twitter.
2015-10-23 17:56:02 +00:00
Stephen Paul Weber 2030ddfc79 Reduce duplication by handling both cases in find 2015-10-23 16:26:35 +00:00
Stephen Paul Weber 439b466979 Use HTTPS for links to Twitter profiles as well 2015-10-23 16:24:04 +00:00
Stephen Paul Weber d1f1063900 Twitter URIs have changed
The #! was deprecated ages ago, and Twitter forces HTTPS these days.
2015-10-23 16:19:54 +00:00
Stephen Paul Weber 123bb445db Always send Twitter replies to Twitter
If is_twitter_notice($notice->reply_to) then send it to Twitter, even
if twitter import is off.  It's a reply to a Twitter notice, it should
go there!
2015-10-23 15:37:11 +00:00
Stephen Paul Weber 8649591626 Stop incorrecly changing object_type to relative URI
All other data is using absolute URI for object_type.
2015-10-22 17:14:59 +00:00
Stephen Paul Weber 3e1a6a65e6 Event plugin uses saveObjectFromActivity for RSVP
The Event plugin is still using a deprecated hook for saving extra data,
which makes it harder to hook into from other plugins.  This commit
fixes it to use the new hook for at least RSVPs.

NOTE: this plugin incorrectly sets the object_type of RSVP notices to
their verb.  This was existing behaviour which I have preserved for
backwards-compatability.
2015-10-22 17:10:50 +00:00
Stephen Paul Weber 4b31bc3fd2 Enqueue renewals
Better for request times, etc
2015-10-21 01:50:03 +00:00
Stephen Paul Weber df21c3c95d Renew 1 day *before* the end, not 1 day *after* 2015-10-21 01:49:26 +00:00
Stephen Paul Weber df46f123dd Actually use the renew code
We have the code to check once a day and renew, but currently it's
just in a script directory.  This change adds an event listener
hook to check and renew subscriptions daily.
2015-10-21 01:10:48 +00:00
Stephen Paul Weber fc3f1f6942 Add direct link to parent notice
This is partly for usability, and partly to make Linkbacks for replies
work (when the plugin is enabled).
2015-10-19 18:40:40 +00:00
Stephen Paul Weber 677f0ac479 Allow users to opt out of sending linkbacks 2015-10-18 21:28:55 +00:00
abjectio 303fa91720 Removed inboxmessagelist.php - seems to be not needed. Ref. Issue #77 2015-10-18 17:34:36 +02:00
Stephen Paul Weber c7e08195e4 Fix Pingback
This code was using the HTTPRequest helpers wrong.  This commit sets the body directly instead of jamming the XML in as a POST param.
2015-10-17 13:39:46 +00:00
Stephen Paul Weber d9d74ca96c Send URL we publish
Webmention and Pingback both need the exact URL we are going to claim to link to to be present in our HTML source, so send them our actual original link.

Webmention clients are supposed to resolve this link.  Pingback clients may still fail on shortened links.
2015-10-17 13:38:13 +00:00
abjectio aa5bbdf6e5 Bug in catch(Exception) - parameter wrongly written 2015-10-16 23:48:05 +02:00
Stephen Paul Weber 3b1792c8b5 Add webmention support 2015-10-15 00:29:53 +00:00
Stephen Paul Weber e4892d21b1 Note that we should handle relative URIs 2015-10-14 16:13:25 -05:00
Stephen Paul Weber 8edc5148d9 Normalize detection helpers
Will make it easier to see what's happening when we add a third one.
2015-10-14 15:54:47 -05:00
Stephen Paul Weber 63fd35dffa Notify replies and repeats
This is especially useful for partial federation with remote accounts
that are not fully OStatus-enabled but support a pingback protocol.
Such accounts will still be notified of replies and repeats of their
content even without OStatus support, thus adding to the federated
universe.
2015-10-14 15:47:00 -05:00
Stephen Paul Weber b43294ec6f Use the getter, not a direct access 2015-10-14 15:33:48 -05:00
Stephen Paul Weber a4a37d6fc9 More robust pingback link detection 2015-10-14 15:28:38 -05:00
abjectio 626333a59e geParent() method will fail if the parent notice does not exist in the notice table. See https://quitter.no/notice/709400 2015-10-14 18:50:39 +02:00
Mikael Nordfeldth 2c8536dbf0 Link source==share notices 2015-10-14 01:30:29 +02:00
Mikael Nordfeldth 401b774c2f Only set ->actor in a case where it has not yet been set
Otherwise it could overwrite it with the wrong actor (the "second round"
for share activities)
2015-10-14 01:20:50 +02:00
Mikael Nordfeldth d260808cd3 intval for type assurance 2015-10-14 01:16:22 +02:00
Mikael Nordfeldth 79c40bc73b Type-aware comparison is necessary for Notice is_local/scope 2015-10-14 00:42:15 +02:00
Mikael Nordfeldth b6aeff89c4 Call Notice::saveActivity instead of Ostatus_profile->processActivity 2015-10-14 00:10:54 +02:00
Mikael Nordfeldth 236bf0b0f5 Remote notice creators should not have notice is_local default to LOCAL_PUBLIC 2015-10-14 00:10:01 +02:00
Mikael Nordfeldth 005c108118 Shared activities were missing the actor 2015-10-13 23:40:35 +02:00
Mikael Nordfeldth 5b307c0417 Add a url test in Notice::saveActivity 2015-10-13 23:39:40 +02:00
Mikael Nordfeldth 65adefe170 Wrong variable names in SharePlugin 2015-10-13 23:18:13 +02:00
Mikael Nordfeldth 4b69ef41e2 Bad variable name in File_redirection 2015-10-13 22:57:45 +02:00
Mikael Nordfeldth e379c49d49 Removing excess debug logging 2015-10-13 22:55:27 +02:00
Mikael Nordfeldth c8a907c828 Bookmark:addNew did not add a proper rel=related 2015-10-13 12:31:35 +02:00
Mikael Nordfeldth 3f4d4cb7a0 Better error handling in Bookmark 2015-10-12 18:28:32 +02:00
Mikael Nordfeldth 67e7bc55ea Bookmarks are almost migrated
Now they are just not being saved in the bookmark table.
2015-10-12 17:48:23 +02:00
Mikael Nordfeldth 7834e67583 Just a functionifying of Notice->rendered 2015-10-12 17:16:13 +02:00
Mikael Nordfeldth 297d68f36c Change Bookmark plugin version details 2015-10-12 09:47:30 +02:00
Mikael Nordfeldth 0e588bdeca Woops, put the bookmark get* functions in the wrong file. 2015-10-11 22:08:28 +02:00
Mikael Nordfeldth 1dac0e709a First step of making Bookmark saveActivity-compatible 2015-10-10 23:47:43 +02:00
Mikael Nordfeldth b209276e72 Stricter typing for Bookmark plugin 2015-10-10 23:15:51 +02:00
Mikael Nordfeldth 5726459629 unmaintained plugins that accidentally got translations 2015-10-10 22:40:05 +02:00
mmn 0926316a76 Merge branch 'master' into 'nightly'
convert activity stream RFC3339 dates to mysql datetime format when saving remote event dates to db

See merge request !34
2015-10-10 20:38:01 +00:00
mmn 3255e2e1b8 Merge branch 'page_title_showstream' into 'nightly'
Show page title in user's profile page

Enable page title on user's profile page to make it consistent with all other pages and better orient users.

![Screenshot_-_250715_-_14_50_00](https://git.gnu.io/aroque/gnu-social/uploads/06e92b233e88fdb66047fbc0571f9831/Screenshot_-_250715_-_14_50_00.png)

See merge request !22
2015-10-10 20:36:59 +00:00
mmn 32f77dbf05 Merge branch 'translation-snapshot-october-2015' into 'nightly'
Snapshot of the Transifex translation project - October 2015

It's been 7 months since the last localization update, and the files in the repository are out of sync with the current state of the project. Our Transifex team has since grown to 63 translators, many of them are active members of the GNU social community. I don't know how we will resolve this situation, but it is clear that we have to act. If you plan to redesign the plugin system in the future to support external repository for localizations, that would work as well. But now, please let us do an update. It would be a serious disgrace to the community to throw all of their hard work away.

See merge request !32
2015-10-10 20:36:04 +00:00
mmn 89d3d9b2ce Merge branch 'usergroups_page' into 'nightly'
Improve display of user's groups page.

* Show page notice as for subscriptions
* Show instructions when user has no groups
* Add explanation of remote groups and link to skilledtest wiki

Here is how it looks when a logged in user is not following groups yet

![login_nogroups](https://git.gnu.io/aroque/gnu-social/uploads/34b1bdcdb9e7277ec3deff4594061c59/login_nogroups.png)

After following a group, you still see the instruction notice. This way you have links to searching groups and creating a new one.

![login_groups](https://git.gnu.io/aroque/gnu-social/uploads/cb50689bcdfca7adc5cdcbe620487aa4/login_groups.png)

Finally when logged out:

![nologin_groups](https://git.gnu.io/aroque/gnu-social/uploads/40d81ab909321f8729c2696dd3938d46/nologin_groups.png)

The current version on nightly has basically no text at all.

See merge request !25
2015-10-10 20:35:36 +00:00
mmn 77951647ce Merge branch 'oauth-default-icon' into 'nightly'
Add default icon to OAuth apps

When MySQL runs in strict mode, it doesn't seem possible to add a new OAuth app.

This is because:
 * The 'icon' field has no defaults and also has NOT NULL constraint.
 * GS uploads/sets the icon[1] (if provided) after the SQL insert[2]

The easiest fix seemed to be to provide a default icon value.
This change sets the default to the  "blue peg" default avatar from the base theme.

[1]
https://git.gnu.io/gnu/gnu-social/blob/7f30e614027fa27e83ecc32eb5443ee82d03f0f7/actions/newapplication.php#L176

[2]
https://git.gnu.io/gnu/gnu-social/blob/7f30e614027fa27e83ecc32eb5443ee82d03f0f7/actions/newapplication.php#L186

See merge request !29
2015-10-10 20:34:22 +00:00
mmn 238d2a3876 Merge branch 'link-atom-fix' into 'nightly'
atom: <link> urls should be attr, not content

Some activities (ex: repeats and follows) have <link>s like this:
<link rel="alternate" type="text/html">http://example.org</link>

This commit changes them to:
<link rel="alternate" type="text/html" href="http://example.org"/>

See merge request !30
2015-10-10 20:33:58 +00:00
Mikael Nordfeldth fe9457daea Syntax and minor fixes
Deleted_notice and Bookmark getByPK assocative array for example.
2015-10-10 22:23:24 +02:00
Mikael Nordfeldth 174586bd51 Some code aligning for consistency 2015-10-10 22:09:51 +02:00
Mikael Nordfeldth cae43344ec Start reworking Bookmark plugin for more modern code 2015-10-10 21:56:02 +02:00
Mikael Nordfeldth 18f07a48e8 Using some Managed_DataObject::getByPK calls for consistency 2015-10-10 21:40:02 +02:00
Mikael Nordfeldth 37f2da03e1 newUri might as well be put in Managed_DataObject 2015-10-10 21:31:26 +02:00
Mikael Nordfeldth 45bc192625 If that $options key wasn't set, this won't change anything anyway 2015-10-10 21:22:07 +02:00
Mikael Nordfeldth a793d211d2 Match parent class definition of clientError 2015-10-10 20:51:53 +02:00
Mikael Nordfeldth b4c51b2d39 Use an atom:link to ApiMediaUpload response instead of mediahref
'cause why not?
2015-10-10 20:41:14 +02:00
Mikael Nordfeldth 9728270acd Add mediahref in our incredibly arbitrary response 2015-10-10 17:15:29 +02:00
Mikael Nordfeldth 5d91c9a820 Don't send multiple error responses in ApiMediaUpload :) 2015-10-10 17:12:44 +02:00
Mikael Nordfeldth 2ad7c4313d Search engine fix because Directory did a 'join'
Colliding columns with a very lacking error message from DB ;)
2015-10-10 12:16:12 +02:00
Mikael Nordfeldth 6376b78a80 I think I have made the delete verb generate proper AS
ActivityStreams had a different/better definition than me
in how to define the Delete verb data:
http://wiki.activitystrea.ms/w/page/23541872/Delete
2015-10-10 11:08:17 +02:00
Hannes Mannerheim a9f879c2ba better explanation 2015-10-10 00:20:32 +02:00
Hannes Mannerheim b24191f9f9 convert activity stream RFC3339 dates to mysql datetime format when saving remote event dates to db 2015-10-10 00:11:54 +02:00
mmn 3154302b53 Merge branch 'master' into 'nightly'
make events federate

See merge request !33
2015-10-09 14:43:45 +00:00
Hannes Mannerheim 61ed36e446 make event urls federate 2015-10-09 16:22:47 +02:00
Mikael Nordfeldth dd149a76f3 AtomPub should work now, at least for post/note 2015-10-09 16:19:26 +02:00
Mikael Nordfeldth 2dfd34b12d Post verb default type is 'note' 2015-10-09 16:18:12 +02:00
Hannes Mannerheim 55655ba319 make event location federate 2015-10-09 16:16:13 +02:00
Hannes Mannerheim 827dffb94c make event dates federate 2015-10-09 16:00:33 +02:00
Mikael Nordfeldth 2d3f1ef520 You don't have to push objects as references 2015-10-09 15:45:23 +02:00
Mikael Nordfeldth 0bdbb32f3b Consistent camelcasing 2015-10-09 15:45:05 +02:00
Mikael Nordfeldth 5dc718c54d Make Bsaic Auth work properly with RW actions 2015-10-09 15:43:17 +02:00
Hannes Mannerheim 5a2d760177 update from upstream 2015-10-09 14:40:43 +02:00
Hannes Mannerheim 499d4aadbc make events federate 2015-10-09 13:10:48 +02:00
Mikael Nordfeldth 216a04df86 Switching variable access in ApiTimelineUser to GNUsocial improvements 2015-10-09 11:23:20 +02:00
Mikael Nordfeldth 3013b84e98 Don't enable StrictTransportSecurity by default
(but you should enable it if you use TLS, but there are many who do this
through their webserver and it's odd to have double headers etc...)
2015-10-09 10:55:12 +02:00
Mikael Nordfeldth 2d81df4760 Deleted_notice variable specification fixed 2015-10-08 13:20:17 +02:00
Mikael Nordfeldth 180958185f Found newer Diaspora protocol specifications
http://www.rubydoc.info/github/Raven24/diaspora-federation/master/DiasporaFederation/Salmon/EncryptedSlap
2015-10-05 12:49:54 +02:00
Mikael Nordfeldth ee6096cca8 FIXME: Diaspora has its own salmon slap semantics 2015-10-05 11:32:10 +02:00
Mikael Nordfeldth 3902dc963a Diaspora encloses magic envelope in <atom:entry>??!!?! 2015-10-05 11:22:23 +02:00
Mikael Nordfeldth 0ba53edd96 Can't use return-value in empty() 2015-10-04 22:32:14 +02:00
Mikael Nordfeldth ec19661312 Can't use return-value in empty() 2015-10-04 22:31:07 +02:00
digital dreamer d7fd6bac72 Snapshot of the Transifex translation project - October 2015 2015-10-04 18:23:01 +02:00
Mikael Nordfeldth af1b0915f4 Magic signature discovery and envelope changes 2015-10-04 17:26:35 +02:00
Mikael Nordfeldth 6afa091dca Change some Salmon events and similar
Use Profile instead of User and (if we know it) send along the target
profile, so a Diaspora plugin can encrypt to the receiver.
2015-10-04 17:26:23 +02:00
Mikael Nordfeldth f4ed171397 Make Magicsig capable of loading public PKCS1 keys 2015-10-04 17:22:19 +02:00
Mikael Nordfeldth 2970333adb Set otherwise undiscovered salmonuri on OStatus script update-profile.php 2015-10-04 17:21:56 +02:00
Mikael Nordfeldth 57f26a97fb var_export without true 2015-10-04 16:40:21 +02:00
Mikael Nordfeldth 4238875ebe autoloading of Crypt_AES and Crypt_RSA is easier 2015-10-04 15:57:11 +02:00
Mikael Nordfeldth 684b9419a0 Add an event to get plugin discovery hints from XRD 2015-10-04 14:46:45 +02:00
Mikael Nordfeldth 2aed59a02a Diaspora plugin is almost there (for remote salmon slaps at least) 2015-10-04 12:06:48 +02:00
Mikael Nordfeldth 9b461db4da Send the entire XMLStringer object in MagicEnvelope events. 2015-10-04 09:59:01 +02:00
Mikael Nordfeldth 184293c634 Break out MagicEnvelope->toXML() functionality to allow for plugin flexibility 2015-10-04 00:17:07 +02:00
Mikael Nordfeldth bc9e3b1843 Remove XSS attack vector in JoinListItem 2015-10-03 23:51:06 +02:00
Mikael Nordfeldth 30a4393afa Move around some code related to Magic_envelope and signing 2015-10-03 23:35:46 +02:00
Mikael Nordfeldth aab7667cd5 Sigh, copy-pasting when tired is a bad idea. 2015-10-03 16:19:38 +02:00
Mikael Nordfeldth 833abbb191 Fixes to Deleted_notice 2015-10-03 16:07:19 +02:00
Mikael Nordfeldth e6d7534a88 We haven't created the Deleted_notice yet, just use target URI directly 2015-10-03 15:39:57 +02:00
Mikael Nordfeldth db726ca294 Return the correct URI in Deleted_notice 2015-10-03 15:31:56 +02:00
Mikael Nordfeldth 7c68537b06 Deletes now federated. But might not be handled properly 2015-10-03 14:39:49 +02:00
Mikael Nordfeldth db9f68e651 Sigh, use the correct variable name... 2015-10-03 13:45:06 +02:00
Mikael Nordfeldth 66a1d63dd0 if is_local was not provided to Notice:saveActivity it wouldn't be set 2015-10-03 13:24:31 +02:00
Mikael Nordfeldth aba38d5586 bump to 1.2.0-beta1 as we have remote delete functionality now 2015-10-03 12:39:23 +02:00
Mikael Nordfeldth 1244e8d929 Somewhat better logging while still in trial phase 2015-10-03 12:33:33 +02:00
Mikael Nordfeldth 2e77a83816 Store delete verb as object_type=activity 2015-10-03 12:29:22 +02:00
Mikael Nordfeldth dac617d95a I think all the notice deletion calls are event-compatible now
This means we can handle DeleteNoticeAsProfile in plugins, such as
the ActivityModeration plugin.
2015-10-03 12:26:09 +02:00
Mikael Nordfeldth 88f7bb1ed5 Some work on ActivityModeration with notice deletion
Let's now create an event called DeleteNotice and also make sure we
handle the onNoticeDeleteRelated properly in ActivityModeration to
avoid possible endless loops etc.
2015-10-03 02:02:37 +02:00
Mikael Nordfeldth ae73baf4ee Undefined variable use 2015-10-03 01:47:40 +02:00
Mikael Nordfeldth 0c6fe78a73 Shorthand function for getActor 2015-10-03 00:43:34 +02:00
Mikael Nordfeldth b8f52965a9 StoreRemoteMedia plugin to enable locally served thumbs of remote images
Add addPlugin('StoreRemoteMedia'); in your config.php to enable.
2015-10-01 22:18:47 +02:00
Mikael Nordfeldth d52b7e3124 Oembed fiddling, nothing major 2015-10-01 22:18:33 +02:00
Mikael Nordfeldth 80bc7f0e25 File handling changes for better logic
Also prepares for StoreRemoteMediaPlugin, coming up...
2015-10-01 22:14:49 +02:00
Mikael Nordfeldth 5b7deee0cc InlineAttachmentListItem put into its own file 2015-10-01 21:40:05 +02:00
Mikael Nordfeldth 3a6c98ff16 NoResultException is common if reply_to was not cleared on parent deletion 2015-09-30 22:55:06 +02:00
Mikael Nordfeldth a09cf51b99 Move Ostatus_profile->processPost function into plugin 2015-09-29 15:19:13 +02:00
Mikael Nordfeldth 21a12a2f60 Some conversationRoot lookups failed with deleted notices 2015-09-28 22:36:04 +02:00
Mikael Nordfeldth 118a4f56ab Script to test remote oEmbed endpoints 2015-09-28 12:25:40 +02:00
Mikael Nordfeldth 34b6d37266 Revert "Accessibility fix, make yes button more explicit"
This reverts commit 1864a9de38.

The problem was another label that was missing (fixed in previous commit, the close button)
2015-09-28 00:49:26 +02:00
Mikael Nordfeldth d6e56924fe Accessibility improvement, title for popup close button
Apparently it read as "times" in screen readers.
2015-09-28 00:47:16 +02:00
Mikael Nordfeldth ad3b62cf2f ShowprofiletagAction now extends ShowstreamAction 2015-09-27 23:46:30 +02:00
Mikael Nordfeldth 0e24709989 Profile/Peopletag file splitting for autoload 2015-09-27 22:51:50 +02:00
Mikael Nordfeldth edb73ec480 Use exception instead of if-statement in File::saveNew 2015-09-27 12:29:38 +02:00
Mikael Nordfeldth 02418cffd8 Be harsher on database saving failure for File entry 2015-09-27 11:54:52 +02:00
Mikael Nordfeldth 0bd0c65b87 Bring back title to DocAction 2015-09-15 14:26:33 +02:00
Mikael Nordfeldth b209dcf8a7 DocAction now extends ManagedAction 2015-09-15 12:07:35 +02:00
Chimo 96a7bf2b90 atom: <link> urls should be attr, not content
Some activities (ex: repeats and follows) have <link>s like this:
<link rel="alternate" type="text/html">http://example.org</link>

This commit changes them to:
<link rel="alternate" type="text/html" href="http://example.org"/>
2015-09-14 21:34:56 -04:00
Mikael Nordfeldth 604ed1fd9a Prepare for ActivityModerationPlugin 2015-09-10 15:55:37 +02:00
Mikael Nordfeldth 9ad9b91efb Call it compareVerbs when comparing verbs 2015-09-10 15:27:40 +02:00
Mikael Nordfeldth 404d5781fc Annoying debug messages that were just meant to remind 2015-09-09 17:48:06 +02:00
Mikael Nordfeldth 52de57e2f6 Let's handle notice dataobjects instead, despite fetching twice from db
Actually the original object should be fixed here, but we'll handle the FIXME's later.
2015-09-09 17:03:52 +02:00
Mikael Nordfeldth 4b83d62750 Split classes into their own files 2015-09-09 16:30:14 +02:00
Mikael Nordfeldth a541533e04 Use Profile objects in Subscription::saveNew 2015-09-06 02:07:52 +02:00
Mikael Nordfeldth 917a547f91 Subscription::saveNew is a static function 2015-09-06 02:01:39 +02:00
Mikael Nordfeldth d448275713 Merge branch 'nightly' 2015-09-06 01:54:00 +02:00
Mikael Nordfeldth 4354ce21d1 introducing html_sprintf for easier sprintf'ing with htmlspecialchars 2015-09-06 01:53:11 +02:00
Chimo dc5dd69f2e Add default icon to OAuth apps
When MySQL runs in strict mode, it doesn't seem possible to add a new OAuth app.

This is because:
 * The 'icon' field has no defaults and also has NOT NULL constraint.
 * GS uploads/sets the icon[1] (if provided) after the SQL insert[2]

The easiest fix seemed to be to provide a default icon value.
This change sets the default to the  "blue peg" default avatar from the base theme.

[1]
https://git.gnu.io/gnu/gnu-social/blob/7f30e614027fa27e83ecc32eb5443ee82d03f0f7/actions/newapplication.php#L176

[2]
https://git.gnu.io/gnu/gnu-social/blob/7f30e614027fa27e83ecc32eb5443ee82d03f0f7/actions/newapplication.php#L186
2015-09-05 17:02:17 -04:00
Mikael Nordfeldth ea75e1c29c Notice_location class in db/core.php 2015-09-04 23:12:23 +02:00
Mikael Nordfeldth 7f30e61402 Oops, forgot Notice_location PHP file 2015-09-04 22:30:33 +02:00
Mikael Nordfeldth 3c86542a40 Move notice location data to Notice_location
Will probably take a _long_ time to do scripts/upgrade.php but don't
worry, it can be aborted and resumed.
2015-09-04 22:25:11 +02:00
Mikael Nordfeldth 476197569f sys_get_temp_dir was added in PHP 5 >= 5.2.1
Our requirements are higher than that, so let's just remove the workaround
2015-09-04 22:24:01 +02:00
Mikael Nordfeldth 1e07f8c045 Incorrect use of DataObject type matching after ->find() 2015-09-04 20:35:11 +02:00
mmn 57c87088d4 Merge branch 'configure-docs' into 'nightly'
Add a few missing 'attachments' config options

show_thumbs
show_html
filename_base

See merge request !27
2015-09-03 16:11:28 +00:00
mmn f4b0756e70 Merge branch 'nightly' into 'nightly'
Adding ChooseTheme plugin into the plugin repository

This merge request propose the plugin ChooseTheme as a part of the plugin repository for GNU social.

See merge request !9
2015-09-03 16:11:04 +00:00
mmn a597b28001 Merge branch 'nginx-sample' into 'nightly'
Add nginx sample configuration

See merge request !23
2015-09-03 16:10:23 +00:00
mmn 5f74ec6782 Merge branch 'webinstaller-faq-link' into 'nightly'
Fix broken link to FAQ in web installer

See merge request !24
2015-09-03 16:09:38 +00:00
Mikael Nordfeldth e06553b15b Suggested edits by hannes2peer 2015-09-03 18:04:13 +02:00
Mikael Nordfeldth 84a65c7189 Include PHP libraries from system if not packaged and they are installed.
Thanks to:
    "Bhuvan Krishna" <bhuvan@swecha.net>
    "Sunil Mohan" <sunil@medhas.org>
2015-09-03 17:56:11 +02:00
abjectio 91c1ab6017 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-08-18 22:55:28 +02:00
Mikael Nordfeldth c77bce12e5 Mf2 extlib update from https://github.com/indieweb/php-mf2/ 2015-08-15 11:48:39 +02:00
Hannes Mannerheim 76004660e9 make it possible to erase fields in the profile via the api 2015-08-11 22:18:57 +02:00
Mikael Nordfeldth c1e6e4e65b OpenID extlib updated: Fixes CVE-2014-8150 2015-08-02 13:41:57 +02:00
Mikael Nordfeldth b434243416 OpenID extlib updated: Fixes CVE-2014-8150 2015-08-02 13:39:38 +02:00
chimo 60e7dc1e39 Add a few missing 'attachments' config options
show_thumbs
show_html
filename_base
2015-08-01 09:24:05 -04:00
aroquen de1d49865c Add some bottom margin to space profile items 2015-07-26 19:10:01 +02:00
aroquen cd6ad8571f Make group lists look like profile ones in neo-quitter theme 2015-07-26 16:10:34 +02:00
aroquen 86ed4ac603 This margin is not needed anymore 2015-07-26 15:22:11 +02:00
aroquen 8056aec93e Remove bullets from user's groups list 2015-07-26 12:39:49 +02:00
aroquen dc9342f184 Group location on a new line as in profile lists 2015-07-26 12:39:48 +02:00
aroquen 31bcf8cfa2 Show full name close to nickname in subscribers list. For consistency with groups list 2015-07-26 12:39:48 +02:00
aroquen a416abb940 Beautify (a bit) groups list
* Reduce font size to fit and look better
* Group nickname is bold
* Add @ prefix to location
2015-07-26 12:39:47 +02:00
aroquen 7b04ee6a9b Align location label (fixes profile and group directory display) 2015-07-26 12:39:31 +02:00
aroquen a04b1cda45 Drop dead variable 2015-07-26 11:10:57 +02:00
aroquen b0abce9bc8 Page notice message as instructions class 2015-07-26 11:10:30 +02:00
aroquen c6f58d432c Improve display of user's groups page.
* Show page notice as for subscriptions
* Show instructions when user has no groups
* Add explanation of remote groups and link to skilledtest wiki
2015-07-25 21:38:38 +02:00
Chimo abde7a2682 Fix broken link to FAQ in web installer 2015-07-25 10:36:31 -04:00
Chimo 05b814ce68 Add nginx sample configuration 2015-07-25 09:39:55 -04:00
aroquen ad49158fb5 Show page title in user's profile page 2015-07-25 14:45:45 +02:00
Mikael Nordfeldth 266b032b17 UsergroupbyidAction now extends ManagedAction 2015-07-21 02:32:17 +02:00
Mikael Nordfeldth 7ce32619cc Missing getTarget function in targetedrss10action.php 2015-07-21 02:17:34 +02:00
Mikael Nordfeldth 5b09a150bc Increased debugging and fixing conversation stitching for saveActivity 2015-07-18 19:19:16 +02:00
Mikael Nordfeldth e0084a6fdf Exception handling regarding Foreign_link 2015-07-18 11:39:34 +02:00
Mikael Nordfeldth b609a3610f Some missed exception throwing since fixing Foreign_link and Foreign_user 2015-07-18 11:04:35 +02:00
Mikael Nordfeldth 6f62adedfc Infinite loop on CLI initiated profile deletion for local users
profile deleting user deleting profile deleting user...
2015-07-18 02:16:52 +02:00
Mikael Nordfeldth 9fdf6474f8 TwitterBridge working again (for signin and posting to Twitter at least)
Now we just need to make it include the newname suggestion if the form fails
(for example forgetting to check the license checkbox or so).
2015-07-18 02:16:15 +02:00
Mikael Nordfeldth beba2a25d0 Don't retry unhandled transports in OpportunisticQM
It'd continue trying xmpp transports forever, for example...
2015-07-18 01:09:50 +02:00
Mikael Nordfeldth e10d081a56 TwitterBridge is closer to working again 2015-07-17 21:03:37 +02:00
Mikael Nordfeldth 6cd7a4a400 TwitterBridge messing about, Twitter OAuth requires Authorization header now?
https://dev.twitter.com/oauth/reference/post/oauth/request_token says that
the request should be a GET with a specific HTTP header instead of query
string parameters for OAuth?
2015-07-17 18:54:39 +02:00
Mikael Nordfeldth 5933056a5b Twittersettings now works better as Profilesettings extension 2015-07-17 17:50:43 +02:00
Mikael Nordfeldth d6d06c8cbb SubMirror now works properly as extended from FormAction 2015-07-17 17:09:36 +02:00
Mikael Nordfeldth 712a6d49d0 Poll settings adapted to FormAction 2015-07-17 16:19:02 +02:00
Mikael Nordfeldth da168674f9 OpenID settings aligned with FormAction 2015-07-17 16:08:22 +02:00
Mikael Nordfeldth 8d2504a809 Early return in FacebookBridge settings action 2015-07-17 15:27:47 +02:00
Mikael Nordfeldth be0c10e8f6 Facebooksettings adapted to FormAction 2015-07-17 15:24:37 +02:00
Mikael Nordfeldth 992fe6896f Urlsettings now adapted to FormAction 2015-07-17 15:16:45 +02:00
Mikael Nordfeldth 8d516d7f08 Don't allow imports by default until it works well on large instances. 2015-07-17 14:40:09 +02:00
Mikael Nordfeldth 2dd979d3f8 SMS Settings now better adapted to FormAction 2015-07-17 14:29:07 +02:00
Mikael Nordfeldth a093dea38c ExtendedProfile is not something we want by default. 2015-07-17 12:46:24 +02:00
Mikael Nordfeldth 9045575e62 ExtendedProfile now works better as extended ProfilesettingsAction 2015-07-17 12:46:09 +02:00
Mikael Nordfeldth 9f82da07f1 ProfilesettingsAction and related stuff modernised 2015-07-17 12:20:11 +02:00
Mikael Nordfeldth 53e820b466 Maximum character limit with utf8mb4 is 191 in varchar 2015-07-17 11:22:25 +02:00
Mikael Nordfeldth cfaaf3c13c PasswordsettingsAction aligned with FormAction
Also made some changes in the password "munging" function call
common_munge_password to accept a profile instead of user ID (which
was only there because stoneage StatusNet used the ID to generate a
not-very-random salt, but nowadays we primarily use AuthCrypt plugin).
2015-07-17 01:47:43 +02:00
Mikael Nordfeldth 47ef917f62 oldschool settings adapted to FormAction
TODO: Rename this "Layout", "Display" or something, since it might
actually be interesting to have non-threaded views for some users.
2015-07-17 01:18:28 +02:00
Mikael Nordfeldth a6e299a2fc OAuth stuff adapted for FormAction
TODO: Break OAuth out into a plugin.
2015-07-17 01:07:19 +02:00
Mikael Nordfeldth ba5a43f2f9 If XMLOutputter $output arg is null, use php://output
Since pushing a null value to the argument actually sets it to null
and not the default fallback (previously $output='php://output');
2015-07-16 23:58:04 +02:00
Mikael Nordfeldth f1d9d8a6ed ImSettings adapted to FormAction inheritance
TODO: Get separate Form classes and move User_im_prefs to Profile_prefs
2015-07-16 21:18:50 +02:00
Mikael Nordfeldth 647171e089 EmailSettingsAction adapted to FormAction
TODO: EmailSettingsForm as a separate class would be good!
2015-07-16 21:17:22 +02:00
Mikael Nordfeldth fd2efbc6f8 AvatarSettings more aligned to FormAction
TODO: Make classes called AvatarCropForm and AvatarUploadForm
2015-07-16 19:21:12 +02:00
Mikael Nordfeldth 2d44400cfc SettingsAction now extends FormAction (and thus ManagedAction) 2015-07-16 19:03:53 +02:00
Mikael Nordfeldth 673bef2fda OAuth widgets separated into their own files 2015-07-16 18:52:43 +02:00
Mikael Nordfeldth 94d54ebc29 Function declarations to match parent class 2015-07-16 18:45:59 +02:00
Mikael Nordfeldth 44dc00a58c Non-replies cannot harvest parent notice nicknames
A feature we use of parent notices is that if you use the same @user
as the parent notice, the same @user will be notified, regardless if
there might be @user@site.com as well as @user@example.com and you're
subscribed to just one of them (or both, or none of them!).

But this threw an exception since we tested this on new notice threads.
2015-07-16 12:53:10 +02:00
Mikael Nordfeldth cd23c78800 Less redundant code. 2015-07-15 19:21:21 +02:00
Mikael Nordfeldth 01a4ab30dc Removing MicroID as well as simplifying profileaction
sorry, forgot to commit in between
2015-07-14 16:52:20 +02:00
abjectio c10a4cf6d2 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-07-12 10:40:24 +02:00
Mikael Nordfeldth e868ac41cd userrss action didn't call parent preparation method 2015-07-11 19:48:18 +02:00
Mikael Nordfeldth c5a5eaf288 Do we update feeduri and salmonuri for Ostatus_profile now?
When changing from HTTP to HTTPS, following up on commit
59763ceecb
where http to https Ostatus_profile URI changing was first introduced.
2015-07-11 19:46:01 +02:00
Mikael Nordfeldth ac98600640 More RESTish URL (/notice/:notice/delete) for notice delete
Also returns to 'top' now after notice deletion.
2015-07-11 11:26:48 +02:00
Mikael Nordfeldth 7d524307d2 DeletenoticeForm is its own class now 2015-07-11 11:26:44 +02:00
Mikael Nordfeldth 9101a1db3d No limit argument to Rss10Action->getNotices() (use $this->limit) 2015-07-11 11:09:16 +02:00
Mikael Nordfeldth 2a1be57470 Merge branch 'nightly' into deletenotice_form_fix 2015-07-11 10:49:41 +02:00
Mikael Nordfeldth e439ace944 bump alpha number to ease remote debugging help 2015-07-11 01:00:04 +02:00
Mikael Nordfeldth fae79b5812 Forgot to push TargetedRss10Action 2015-07-11 00:32:05 +02:00
Mikael Nordfeldth bb29d18017 ShowfavoritesAction now extends ShowstreamAction 2015-07-11 00:28:32 +02:00
Mikael Nordfeldth 5929b629e5 define Subscription_queue::exists as static 2015-07-11 00:08:23 +02:00
Mikael Nordfeldth 76396041e2 $notices and $notice is not the same, silly! 2015-07-10 23:30:59 +02:00
Mikael Nordfeldth 64fbc93217 ApiAction::dateTwitter was called statically from a plugin 2015-07-10 23:30:17 +02:00
Mikael Nordfeldth 24b1e26406 MagicEnvelope called DOMDocument::loadXML statically
but apparently we shouldn't do this, despite recommended on https://secure.php.net/manual/en/domdocument.loadxml.php
2015-07-10 23:24:50 +02:00
Mikael Nordfeldth 961031bc28 Cleaning up Directory plugin lists 2015-07-10 23:19:54 +02:00
Mikael Nordfeldth ad453785f0 FoafAction now a ManagedAction 2015-07-10 23:10:24 +02:00
Mikael Nordfeldth 08bd4fa6a8 ShowstreamAction no longer has public ->profile 2015-07-10 23:09:44 +02:00
Mikael Nordfeldth 3900a739b9 Forgotten migrations of ->profile and ->user to ->getTarget()
GalleryAction extends ProfileAction which no longer uses ->profile and ->user
2015-07-10 23:05:02 +02:00
Mikael Nordfeldth 55b2d124bc The 'target' is an argument to common_local_url not the target profile 2015-07-10 22:49:38 +02:00
Mikael Nordfeldth a964ea61cd Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-07-10 16:03:41 +02:00
mmn c037f04d17 Merge branch 'jquery-cookie-undefined' into 'nightly'
Updates jquery.cookie usage to match changes from v1.4.0

`$.cookie('name')` returns `undefined` instead of `null` when cookie is not present.

This fixes a problem where the browser was never asking for location,
and the JSON.parse call was throwing an exception when the geolocation
cookie wasn't present.

Deleting a cookie should use `$.removeCookie('name')` instead of `$.cookie('name', null)`.

[Reference](https://github.com/carhartl/jquery-cookie/blob/7f88a4e631aba8a8c688fd8999ce6b9bcfd50718/CHANGELOG.md#140).

See merge request !20
2015-07-10 14:03:30 +00:00
Mikael Nordfeldth 7c4e550e31 Merge branch 'master' into nightly 2015-07-10 16:02:55 +02:00
mmn 204f6bb503 Merge branch 'permissions-fix' into 'master'
Permissions fix

During Debian packaging I noticed that executable permissions on several files are incorrect.  In the fist case files such as .gitignore, .png, .ico were wrongly set as executable.  In the second case, files that are meant to be running on the command line such as maintenance scripts starting with "#!/usr/bin/env php" do not have executable permissions.  These files were identified by lintian automatic checking program.  This merge request aims to fix the problem.

See merge request !21
2015-07-10 14:01:49 +00:00
Mikael Nordfeldth 6c4985476e Merge branch 'nightly' into deletenotice_form_fix 2015-07-10 13:54:06 +02:00
Mikael Nordfeldth 9a92b58057 ShowstreamAction tidying up
Lots of these changes mean that we're requiring certain values to
either by typed properly or return the expected value. If it doesn't
there should be a fatal exception thrown which we can followup in the
logs and won't go silently suppressed.
2015-07-10 13:44:47 +02:00
Mikael Nordfeldth f8877e015b static definition of User::getByNickname 2015-07-10 12:59:19 +02:00
Mikael Nordfeldth 50c297bcbe ShowstreamAction fixes so it's not as horrible 2015-07-10 12:34:06 +02:00
Mikael Nordfeldth 6a36121a56 Spiff up the PersonalTagCloudSection class
missing a fix in actions/showstream.php for the switched position
of arguments in the constructor
2015-07-10 12:23:55 +02:00
Mikael Nordfeldth f9d82a6ac5 Easy comparison of two Profile objects 2015-07-10 12:19:55 +02:00
Mikael Nordfeldth e567406c9f RedirecturlAction now extends ManagedAction 2015-07-10 12:08:33 +02:00
Bhuvan Krishna 1ab4c9998a Add executable permission to script missing it 2015-07-10 14:46:08 +05:30
Bhuvan Krishna d6924f7680 Remove executable permissions where unnecessary 2015-07-10 14:36:34 +05:30
Mikael Nordfeldth 76432b958b delete notice form fix 2015-07-10 00:52:22 +02:00
Mikael Nordfeldth e46b2803a7 Introducing TargetedRss10Action for simplifying RSS 1.0 2015-07-10 00:28:36 +02:00
Mikael Nordfeldth 1cbf2510e7 /:nickname/all/rss had to be before /:tagger/all/:tag
...though this makes it impossible to get a list called "rss"

so FIXME, the RSS 1.0 actions should be in the API or something
2015-07-10 00:27:26 +02:00
Mikael Nordfeldth 8cc85f684b Need to supply data to NoSuchUserException 2015-07-10 00:08:09 +02:00
Mikael Nordfeldth b5b7a27f9b Rss10Action migrated to ManagedAction 2015-07-09 23:29:30 +02:00
Mikael Nordfeldth 06f60b57c1 StartpageAction essentially duplicated TopAction 2015-07-09 23:01:50 +02:00
Mikael Nordfeldth 37e8b027f9 PEAR's Mail_mimeDecode updated 2015-07-09 22:29:23 +02:00
Mikael Nordfeldth ed248f7f5a No static calls (PEAR sucks ass) 2015-07-09 22:26:03 +02:00
Mikael Nordfeldth 90565cc44d searchsubmenu item() function definition 2015-07-09 22:19:19 +02:00
Mikael Nordfeldth 9fb3ea3ce6 static function definitions and minor simplifying 2015-07-09 22:16:14 +02:00
Mikael Nordfeldth d63bca9d3c Rss10Action now in an autodetected file. 2015-07-09 14:22:22 +02:00
Mikael Nordfeldth 9b8ac2d404 CSS can handle alternating row colouring now 2015-07-09 14:10:38 +02:00
Mikael Nordfeldth 65f1f74f2b Type controlling in lib/atomnoticefeed.php 2015-07-09 13:56:02 +02:00
Mikael Nordfeldth 43cec8eaac API actions are not ManagedAction yet 2015-07-09 13:46:03 +02:00
Mikael Nordfeldth 2103075ffa Delete notice script added. Give an ID or URI. 2015-07-08 12:30:21 +02:00
Mikael Nordfeldth f939485b52 Gravatar relies on closed source 3rd party 2015-07-08 07:57:27 +02:00
Mikael Nordfeldth 77957372ab File_redirection static fixes and simplifying 2015-07-07 20:16:05 +02:00
Mikael Nordfeldth 33dc06ae21 handle function declaration to match parent 2015-07-07 20:02:41 +02:00
Mikael Nordfeldth d0458b824a File_redirection minor coding layout fix 2015-07-07 19:59:43 +02:00
Mikael Nordfeldth 45ee2060fa File_redirection is called statically 2015-07-07 19:48:18 +02:00
Mikael Nordfeldth 6919dda958 RobotstxtAction migrated to ManagedAction 2015-07-07 19:45:01 +02:00
Mikael Nordfeldth acdcb2ad8d prepare and handle function to match parents 2015-07-07 19:34:42 +02:00
Mikael Nordfeldth edef6f929a Don't statically call Validate functions 2015-07-07 19:30:14 +02:00
Mikael Nordfeldth 62c6ed58ba DirectMessagePlugin actions modernified 2015-07-07 19:18:45 +02:00
Mikael Nordfeldth ed3022adc1 Janrain OpenID extlib updated
From their tree on a4090d0b30f850044413630333341cd327cbb55a
Source: https://github.com/openid/php-openid
2015-07-05 23:07:41 +02:00
Mikael Nordfeldth 3b6a424c9f Mismatching function declarations. 2015-07-04 19:51:36 +02:00
Mikael Nordfeldth 9054bb69e9 I had some inheritance the wrong way around. 2015-07-04 19:48:35 +02:00
Mikael Nordfeldth 5424c82423 Forgot NoticestreamAction, thanks roland. 2015-07-04 00:02:05 +02:00
Mikael Nordfeldth 3f3482f017 Stronger typing and fixes in RequireValidatedEmail 2015-07-03 10:17:15 +02:00
Mikael Nordfeldth d5a24da167 only variables can be sent by reference (strict standards) 2015-06-25 20:13:27 +02:00
Mikael Nordfeldth 030b570051 non-static method was called statically, now defined static 2015-06-23 13:24:19 +02:00
Mikael Nordfeldth 3a74f49182 stricter typing in GroupsNav menu widget 2015-06-23 12:56:19 +02:00
Mikael Nordfeldth 748bd825e7 SelftagWidget had mismatching url() definition 2015-06-23 12:37:00 +02:00
Mikael Nordfeldth e6507a0f18 FeedList widget had mismatching show() definition 2015-06-23 12:26:44 +02:00
Mikael Nordfeldth 1864a9de38 Accessibility fix, make yes button more explicit 2015-06-22 23:40:51 +02:00
Chimo a25d952ef9 $.cookie('n', null) -> $.removeCookie as of 1.4.0 2015-06-20 19:39:12 -04:00
Chimo 9e1d4bfbf0 jquery-cookie returns undefined as of 1.4.0
when a cookie isn't set.

This fixes a problem where the browser was never asking for location,
and the JSON.parse call was throwing an exception when the geolocation cookie wasn't
present.
2015-06-20 19:38:58 -04:00
Mikael Nordfeldth fde3b99e8e Less redundant code, please 2015-06-21 01:37:29 +02:00
mmn 29620619b5 Merge branch 'plugins-documentation' into 'nightly'
Plugins documentation

* Bring content from https://web.archive.org/web/20140821102047/http://status.net/wiki/HOWTO_Make_a_Plugin
* Point link on Plugins Admin Panel page to plugins/README.md ( Ref #53 )
* Add link to "Community Plugins"

See merge request !19
2015-06-20 22:49:31 +00:00
mmn 46cf5aa2a4 Merge branch 'remove_broken_plugins_from_default' into 'nightly'
Drop QnA from default plugins

Since it doesn't work (at least at the moment) it shouldn't be proposed as default plugin

See merge request !15
2015-06-20 22:48:49 +00:00
mmn ee9176f20d Merge branch 'drop_corporate_text' into 'nightly'
Drop corporate text plus minor rewording

Following [this discussion](https://gnusocial.no/conversation/190441#notice-190441) I only fixed corporate-only occurrences. I suggest People instead of User directory. Moreover I fixed a minor inconsistency (Trends should be preferred to Trending topics).

The full locale folder should be fixed once we have digitaldreamer's feedback. But we can at least start from this.

See merge request !16
2015-06-20 22:48:31 +00:00
mmn 1d11153396 Merge branch 'character_count' into 'nightly'
Fix #31 character count floats in replies

See merge request !17
2015-06-20 22:47:22 +00:00
Mikael Nordfeldth 7c373edf4d implement javascript callbacks (no remove yet) 2015-06-14 23:14:00 +02:00
Mikael Nordfeldth 41fe435553 oops forgot an alert() 2015-06-14 22:04:57 +02:00
Mikael Nordfeldth 01cbe744b6 Move some javascript out to an E (Event) object 2015-06-14 21:57:39 +02:00
chimo e32cd2dd15 Add link to 'community plugins' 2015-06-14 12:05:54 -04:00
chimo 39462c3a2e Documentation about plugins
* Content in plugins/doc/Plugin_development.md from:
https://web.archive.org/web/20140821102047/http://status.net/wiki/HOWTO_Make_a_Plugin

* Point link on Plugins Admin Panel page to plugins/README.md
2015-06-14 11:59:46 -04:00
abjectio e9a6d5be51 Removed the full AGPL license file 2015-06-13 11:11:50 +02:00
abjectio fca53a56b4 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-06-13 11:10:10 +02:00
Mikael Nordfeldth a03249dd99 No reason to have makeRegex protected 2015-06-12 17:15:39 +02:00
abjectio 437dc3d713 Added .pot file and Norwegian translation 2015-06-10 22:11:34 +02:00
abjectio ea076a8783 Bug in use of gettext/locale string 2015-06-10 22:10:14 +02:00
abjectio 965cd92a72 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-06-10 22:09:30 +02:00
aroquen 204ebe607d Fix #31 character count floats in replies 2015-06-07 22:44:33 +02:00
aroquen 267a49103e Rewording: trends instead of trending topics for consistency with other occurrences 2015-06-07 22:28:19 +02:00
aroquen a42d74a238 Rewording: people instead of user directory 2015-06-07 22:27:31 +02:00
aroquen f9c51c2478 No corporate-only strings in code base anymore 2015-06-07 22:24:14 +02:00
aroquen 776b82e6e8 Drop QnA from default plugins 2015-06-07 14:05:51 +02:00
Mikael Nordfeldth 8a002e98bc File-related functions not declared static 2015-06-07 10:01:28 +02:00
Mikael Nordfeldth 4fc62a8bf5 Another function not matching parent declaration 2015-06-07 09:26:12 +02:00
abjectio 3bdcdfd114 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-06-06 23:32:10 +02:00
mmn f7769c17b5 Merge branch 'subscribers_as_addressees' into 'nightly'
Add subscribers as addressees to toselector

Populate the dropdown recipient menu first with groups, then with followed users. There is no alphabetical sorting (perhaps to be added later?). See this discussion https://gnusocial.no/conversation/190705#notice-190705. Thanks to @chimo.

Hope it is good now.

See merge request !14
2015-06-06 21:14:50 +00:00
Chimo 76c9971c31 Show nickname if user has oldschool option enabled 2015-06-06 23:07:34 +02:00
aroquen e46dcc0cc4 Add subscribed users to dropdown menu. 2015-06-06 23:07:13 +02:00
abjectio 9dc8250956 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-06-06 22:27:51 +02:00
mmn 3a910d8c8c Merge branch 'doc-src' into 'nightly'
Small updates to doc-src files

* Remove mentions of GTalk since it's been replaced by Hangouts which doesn't do XMPP
* Update URLS, use HTTPS where possible

See merge request !11
2015-06-06 20:27:00 +00:00
mmn e203271d95 Merge branch 'nightly' into 'nightly'
fixed realtime action buttons and marker in base, adjusted settings in neo-quitter

fixed realtime action buttons and marker in base so that all neo themes benefit from it, adjusted settings in neo-quitter

See merge request !12
2015-06-06 20:20:52 +00:00
Mikael Nordfeldth 6267e7a930 Merge branch 'hackfest' into nightly 2015-06-06 22:15:39 +02:00
Mikael Nordfeldth d76d37340a Function declarations not matching their parents 2015-06-06 22:14:56 +02:00
Mikael Nordfeldth 871912a00a Plugins didn't match lib/plugin.php onPluginVersion function definition
I ran:
for i in `grep -R onPluginVersion...version plugins/|cut -d: -f1`; do sed -i '{ s/\(onPluginVersion(\)\(\&\$versions\)/\1array \2/ }' $i; done
2015-06-06 22:04:01 +02:00
Mikael Nordfeldth 628e7fa583 ApiOAuthAction functions didn't match parents 2015-06-06 21:57:42 +02:00
Mikael Nordfeldth 15643c802b EndActionExecute event should only run if the Action is not overridden 2015-06-06 20:13:11 +02:00
Mikael Nordfeldth 814696c202 DB_DataObject delete function calls PEAR::isError directly, ignore E_STRICT 2015-06-06 20:01:03 +02:00
Mikael Nordfeldth 50070c9b0a GS_DataObject overrides DB_DataObject insert() too 2015-06-06 19:59:01 +02:00
Mikael Nordfeldth 06503cc11b joinAdd calls DB_DataObject::factory directly so no GS_DataObject override 2015-06-06 19:41:23 +02:00
Mikael Nordfeldth daaafd86e2 DB_DataObject recommends using ->tableName() 2015-06-06 19:35:10 +02:00
Mikael Nordfeldth 9e52b6f2d1 DB_DataObject v1.11.4 made some functions static (finally!) 2015-06-06 19:30:53 +02:00
Marcus Moeller fae8e38616 fixed realtime action buttons and marker in base, adjusted settings in neo-quitter 2015-06-06 19:18:20 +02:00
Mikael Nordfeldth 4cba7a4002 DB_DataObject v1.11.4, finally! 2015-06-06 19:13:57 +02:00
Mikael Nordfeldth 9712a92853 MITM the DB_DataObject to avoid PEAR::DB strict standards warnings 2015-06-06 18:29:15 +02:00
abjectio 28eb441812 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-06-06 18:15:17 +02:00
Mikael Nordfeldth 3c2a720b21 Found a remnant staticGet call 2015-06-06 17:39:25 +02:00
Mikael Nordfeldth 6478034e92 Diaspora-compatible Salmon slap receival
We're not all the way there yet, there is something which seems to bugger
up profile discovery from their end.
2015-06-06 17:14:38 +02:00
Mikael Nordfeldth faf14197cd Diaspora doesn't understand our Salmon POST, so send again 2015-06-06 16:57:29 +02:00
Mikael Nordfeldth b63054cb1d OStatus update-profile.php script now finds Diaspora salmon URLs 2015-06-06 16:18:22 +02:00
Mikael Nordfeldth 4de125dd84 Moved FeedSubException parent class to own file 2015-06-06 16:02:25 +02:00
Mikael Nordfeldth 268b901048 Maintainer change for Ostatus_profile 2015-06-06 15:58:08 +02:00
Chimo 136c3140c2 doc-src: Update URLs 2015-06-06 09:12:30 -04:00
Chimo 7e90103f21 "im" doc-src: GTalk has been deprecated 2015-06-06 09:10:42 -04:00
Mikael Nordfeldth d4fc064e44 Include the Diaspora GUID string in our XRD metadata 2015-06-06 14:49:39 +02:00
Mikael Nordfeldth 623a7eee57 Diaspora seeds tend to give the key type in 'type' attribute 2015-06-06 14:46:17 +02:00
Mikael Nordfeldth 57943cad99 Magicsig gets toFingerprint output
We give this as a lowercase, sha256 hexadecimal digest of the string:
TYPE + "." + BASE64(modulus as bytes) + "." + BASE64(exponent as bytes)

Where TYPE in all our cases up until now at least are "RSA"
2015-06-06 14:35:48 +02:00
Mikael Nordfeldth c5f79fd2f3 Magicsig gets toFingerprint function. 2015-06-06 14:33:43 +02:00
Mikael Nordfeldth e212f2ae77 Moved Diaspora specific metadata to own plugin 2015-06-06 13:49:27 +02:00
mmn a39f51c044 Merge branch 'tagprofile-ajax-fix' into 'nightly'
Only serve tagprofile HTML if we aren't POSTing via ajax

This fixes an issue where POSTing the selftag form in the
profile_block sidebar via AJAX would generate an XML response
containing both the content from doPost() and showPage(),
resulting in invalid XML.

These changes make it so that if we're POSTing via AJAX,
we serve content from doPost(), otherwise we serve showPage()
but never both.

See merge request !8
2015-06-06 10:26:43 +00:00
abjectio 8abf96cfd8 Edited the readme file to be more inline with the core repo 2015-06-06 12:14:50 +02:00
abjectio b0a598ba7b Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-06-06 11:31:18 +02:00
abjectio e269a3fad9 Added ChooseTheme plugin to the repository 2015-06-06 11:28:34 +02:00
Chimo 47c83f4c49 Only serve tagprofile HTML if we aren't POSTing via ajax
This fixes an issue where POSTing the selftag form in the
profile_block sidebar via AJAX would generate an XML response
containing both the content from doPost() and showPage(),
resulting in invalid XML.

These changes make it so that if we're POSTing via AJAX,
we serve content from doPost(), otherwise we serve showPage()
but never both.
2015-06-06 00:22:14 -04:00
mmn 1635d459ec Merge branch 'threaded_replies_nightly' into 'nightly'
Fix threaded replies floating

Following Marcus fixes for neo-quitter, I think the floating of replies should be fixed directly in the base theme. What do you think? This issue affects all derived themes (although sometimes only marginally) see https://gnusocial.no/conversation/126588.

These commits implement some of Marcus floating fixes directly in base plus the fav, reply icons are better aligned with the permalink and timestamp (notice-options change).

See merge request !7
2015-06-05 22:38:13 +00:00
aroquen 77db161aca Threaded replies and conversations do not float left 2015-06-06 00:23:54 +02:00
aroquen b3667c72c7 Align notice-options with timestamp and permalink 2015-06-06 00:23:23 +02:00
mmn e3b1d401fd Merge branch 'nightly' into 'nightly'
Updated neo-quitter

Updated neo-quitter to match the colors of the default theme
Fixed alignment issues
Changed threaded view to inline in order to make it more readable

See merge request !6
2015-06-05 21:44:49 +00:00
Mikael Nordfeldth ad7cd155fb floating elements CSS fix by aroque 2015-06-05 23:44:59 +02:00
Mikael Nordfeldth 882ce56cf4 buttle's local/plugins translation file fix 2015-06-05 23:43:28 +02:00
Mikael Nordfeldth 29e1203609 Merge request for documentation and URLs 2015-06-05 23:16:22 +02:00
mmn a3011febdf Merge branch 'nightly' into 'nightly'
Fixing broken links during end of installation #26 - https://git.gnu.io/gnu/gnu-social/issues/26

See merge request !2
2015-06-05 21:10:53 +00:00
Mikael Nordfeldth 6e28524647 Extensions of GalleryActions enabled again (nickname check) 2015-06-05 21:50:00 +02:00
Mikael Nordfeldth c26e08d6a6 some more extensions of ShowstreamAction broke in last commit 2015-06-05 21:49:34 +02:00
Mikael Nordfeldth 9376a6d75a ModPlus plugin now links to remote profiles with UserbyidAction 2015-06-05 21:30:50 +02:00
Mikael Nordfeldth 8ad81a6aa3 Allow showing profiles with UserbyidAction (/user/:id) 2015-06-05 21:24:41 +02:00
abjectio c00b2ecc4b Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-06-05 20:57:28 +02:00
root dd2fb27316 improved favocin 2015-06-05 19:12:17 +02:00
Marcus Moeller bc7eb792f4 updated favicon color 2015-06-05 17:08:35 +02:00
Marcus Moeller abfa052861 use none instead of unset 2015-06-05 16:54:55 +02:00
Marcus Moeller dbfc8092d7 even display threads inline if no user is logged in 2015-06-05 16:47:41 +02:00
Marcus Moeller 6137d301be set threaded view to inline to make it more readable 2015-06-05 16:37:34 +02:00
Marcus Moeller af87552e04 updated neo-quitter colours to match the default theme, fixed some alignment and margin issues 2015-06-05 16:21:04 +02:00
Mikael Nordfeldth 94f5247f91 $this->client_ip was not always set in AntiBrutePlugin onEndCheckPassword 2015-06-05 15:34:14 +02:00
Mikael Nordfeldth dee4ca37ab GROUPS_PER_MINILIST was undefined in profileaction.php 2015-06-05 14:07:03 +02:00
Mikael Nordfeldth b24d711f55 Network wide feed link would NEVER show! 2015-06-05 14:01:03 +02:00
Mikael Nordfeldth 50f0235654 Oops, don't forget to remove var_dump(...) 2015-06-04 22:34:28 +02:00
Mikael Nordfeldth cafab14f2b Modernize File_redirection to use Managed_DataObject functions 2015-06-04 22:33:36 +02:00
Mikael Nordfeldth 63251fb9d0 Modernize File_thumbnail to use Managed_DataObject functions 2015-06-04 22:29:40 +02:00
Mikael Nordfeldth fc9de94cbd Modernize Queue_item to use Managed_DataObject functions 2015-06-04 22:27:53 +02:00
Mikael Nordfeldth f9698598c6 Modernize Profile_prefs to use Managed_DataObject functions 2015-06-04 22:26:31 +02:00
Mikael Nordfeldth d1afc78124 Modernize File_to_post to use Managed_DataObject functions 2015-06-04 22:22:49 +02:00
Mikael Nordfeldth ebdd792b6f getByPK (primary key) lookup for Managed_DataObject instances 2015-06-04 22:17:40 +02:00
Mikael Nordfeldth ca19a5cd6d Easier pkeyCols call to get primary key columns 2015-06-04 21:51:56 +02:00
Mikael Nordfeldth 20145092ce Publish OAuth data in host-meta 2015-06-04 18:54:09 +02:00
Mikael Nordfeldth 5718f812d9 Network public publicgroupnav link would always show 2015-06-04 17:39:23 +02:00
Mikael Nordfeldth fe6498e7c8 Send objects instead of integers to File_to_post::processNew 2015-06-04 17:36:11 +02:00
Mikael Nordfeldth 5358fb3cce Use the same cache string in all places for file:notice-ids 2015-06-04 17:02:45 +02:00
Mikael Nordfeldth 9449235765 Remove some clutter from OMB plugin 2015-06-04 01:14:26 +02:00
Mikael Nordfeldth a4739b0107 Move some last OpenID stuff into the OpenID plugin (XRDS) 2015-06-04 01:08:03 +02:00
Mikael Nordfeldth bdd15cfe63 don't double the output for some PublicAction->extraHead 2015-06-04 00:56:46 +02:00
Mikael Nordfeldth 26631bf9e6 Show network public feed link in PublicGroupNav 2015-06-04 00:53:35 +02:00
Mikael Nordfeldth 551c69ed56 Extend Networkpublic and Public actions from SitestreamAction 2015-06-04 00:51:07 +02:00
Mikael Nordfeldth 2b2ebfc254 bump version to 1.2.0-alpha1
since we fixed the search issue and updated jquery
2015-06-03 22:57:58 +02:00
Mikael Nordfeldth fd121f371a case insensitive indexing for content and nick/fullnames (search)
This broke when changing the database to utf8mb4 instead of utf8,
since utf8_general_ci wasn't accepted and the engine fell back to
utf8mb4_bin. Now we're back in case insensitive search business!
2015-06-03 22:43:51 +02:00
Mikael Nordfeldth c5da7306bd return logic tidied up for command interpretation 2015-06-02 14:25:45 +02:00
Mikael Nordfeldth 2bf0ec719d initialize command interpretation result to false 2015-06-02 14:17:59 +02:00
Mikael Nordfeldth 7e388e697d fallback to local URL if reply->getUrl() is missing
Remote Activity notices generally don't have a proper HTTP URL associated.
2015-06-02 13:55:13 +02:00
Mikael Nordfeldth 0726dcd06c Start using NoParentNoticeException more widely 2015-06-02 13:50:52 +02:00
Mikael Nordfeldth c84b21008e Notice->getParent code reuse
...not entirely sure whether to allow getParent calls on Notice
objects which have not been created, but we'll leave that in for now...
2015-06-02 13:46:23 +02:00
Mikael Nordfeldth 6b9a8b7b19 Reuse code from our classes, don't write own algorithms 2015-06-02 13:45:22 +02:00
Mikael Nordfeldth e728e2aa81 typing, added typing to some common_* calls in util.php 2015-06-02 13:19:12 +02:00
Mikael Nordfeldth 2096c18e57 use array_key_exists instead of empty to test array key 2015-06-02 13:14:57 +02:00
Mikael Nordfeldth 2cebbead75 Accidentally presented Atom feed as ActivityStreams JSON 2015-06-02 12:58:30 +02:00
Mikael Nordfeldth a2ddcc124f No redirect follow on HEAD request (bump to PHP5.5 minimum requirement)
We're using the try-catch-finally clause where "finally" wasn't introduced
until PHP 5.5, so our minimum requirement for GNU social is bumped to that.
2015-06-02 11:07:11 +02:00
Mikael Nordfeldth 82f9b6908c Fake recovery by email address, to hide registrants on the site 2015-05-30 23:29:58 +02:00
Mikael Nordfeldth 731d283159 Password recovery logic cleaned up 2015-05-30 23:18:17 +02:00
abjectio 1d85fd35a2 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social 2015-05-30 17:21:52 +02:00
Mikael Nordfeldth b4b8cb57b3 slugify console.php prompt name
since PHP thought it was fun to crash on Quitter España and I
couldn't be bothered messing with readline
2015-05-30 16:40:00 +02:00
Mikael Nordfeldth 3294d704a4 scripts/nukefile.php for blasting crap from the server
Deletes notices and the locally stored file based on File id, as
you may want to just get rid of shit sometimes.
2015-05-30 15:41:04 +02:00
Mikael Nordfeldth f926e27a65 urlhash will _be_ NULL on update, so NOT NULL won't work 2015-05-27 22:37:20 +02:00
Mikael Nordfeldth c31d6608a8 remove _all_ file URLs not just the duplicates 2015-05-27 21:54:51 +02:00
Mikael Nordfeldth cd0b70dbc1 upgrade fix for file URLs longer than 191 chars 2015-05-27 21:31:29 +02:00
Mikael Nordfeldth 0e6b80ded3 more debugging info on failed schema.php runSqlSet 2015-05-27 20:21:05 +02:00
abjectio 19e7cf5f4a Merge branch 'master' of git.gnu.io:gnu/gnu-social 2015-05-26 22:27:27 +02:00
abjectio 0200b1d784 Merge branch 'nightly' of git.gnu.io:gnu/gnu-social into nightly 2015-05-26 22:25:49 +02:00
Mikael Nordfeldth 6b717a6a69 Throw exception if Local_group has no corresponding User_group 2015-05-26 13:14:26 +02:00
Mikael Nordfeldth 925aacec1a Throw exception when a Conversation is not found 2015-05-26 13:11:08 +02:00
Mikael Nordfeldth bb8d377b91 Redirect to group URL for /nickname pattern 2015-05-26 13:10:37 +02:00
aroquen f7176e7aef Textarea resizes only vertically. 2015-05-25 00:31:55 +02:00
buttle ef0385a25c fix for ./local/plugins/* translation files
translations for 3rd party plugins were not being detected
2015-05-21 09:35:52 +02:00
abjectio 5675f328b6 Fixing broken links during end of installation #26 - https://git.gnu.io/gnu/gnu-social/issues/26 2015-05-20 00:02:19 +02:00
abjectio 63ca11fc7d Changed URLs in README to reflect new host git.gnu.io 2015-05-19 00:00:22 +02:00
Mikael Nordfeldth 4a6f509aa5 More automated htaccess.sample 2015-05-10 19:41:36 +02:00
Mikael Nordfeldth d010c5a581 magnet URL linkify support 2015-05-09 15:54:09 +02:00
Mikael Nordfeldth e1822c2b66 schemacheck hint in newly installed config.php 2015-05-03 23:07:31 +02:00
Mikael Nordfeldth cd42ee7e85 Allow adding preload token to HSTS header
Use by adding this to config.php:

addPlugin('StrictTransportSecurity', array('preloadToken'=>true));
2015-05-03 23:05:47 +02:00
Mikael Nordfeldth 6d72800098 StrictTransportSecurity syntax fix 2015-05-03 22:50:44 +02:00
Mikael Nordfeldth 2b58d6b774 Merge branch 'quitagram' into nightly
Fixes that make quitagram work better amongst other things.
2015-04-22 22:17:50 +02:00
Mikael Nordfeldth 7e2caa0bb1 Make it easier to hide attachments list header 2015-04-22 22:13:55 +02:00
Mikael Nordfeldth 51ecd6be15 Fix some ProfileAction stuff, add function profileActionPreparation
Split up files with multiple classes to multiple files for autoload, sorry
for baking this into this commit.
2015-04-22 21:22:38 +02:00
Mikael Nordfeldth 7601e10b6a getFullname function on Profile class
No need to fix it for User since we shouldn't use that mostly.
2015-04-22 20:57:05 +02:00
Mikael Nordfeldth 4210096a6f MobileProfile plugin cleanup 2015-04-22 19:50:56 +02:00
Mikael Nordfeldth f642da201d Easier to modify DTD for HTMLOutputter 2015-04-22 19:44:58 +02:00
Mikael Nordfeldth 0a0455b8d2 minor coding fixes 2015-04-22 18:41:54 +02:00
Mikael Nordfeldth 529b2f6613 deleteuser script changed to deleteprofile
Delete remote profiles by providing their ID if known, or you can
provide their profile URI with --uri=https://...

Useful for cleaning up old, long gone and no longer desired profiles
and their notices.
2015-04-21 23:47:55 +02:00
Mikael Nordfeldth f9f7c46751 Better typing in lib/framework.php 2015-04-20 00:26:16 +02:00
Mikael Nordfeldth 8a119dc970 We already throw exceptions for PEAR errors 2015-04-20 00:26:00 +02:00
Mikael Nordfeldth b75e88f65f Get better PEAR:DB error logging (debuginfo included) 2015-04-20 00:02:13 +02:00
Mikael Nordfeldth 1194c47c5d ksort on commands array to avoid converting to numerical array 2015-04-19 21:12:26 +02:00
Mikael Nordfeldth a55d1df585 Clearer warning message on non-existing file 2015-04-16 00:22:09 +02:00
Mikael Nordfeldth 0337a7b866 file_redirection duplicates are removed too in maintenance script 2015-04-15 23:56:23 +02:00
Mikael Nordfeldth 5f1e9e80c2 remove duplicate file URLs script 2015-04-15 23:26:24 +02:00
Mikael Nordfeldth c5715bc756 File_to_post indexing and cleaning preparations 2015-04-15 23:25:12 +02:00
Mikael Nordfeldth e4a17fedc6 Translation contained bad HTML 2015-04-14 22:01:22 +02:00
Mikael Nordfeldth ee96a08700 latest php-gettext from https://code.launchpad.net/~danilo/php-gettext/ 2015-04-14 21:40:09 +02:00
Mikael Nordfeldth 4526c3f712 If /var/run was unwritable stopdaemons did not find pid file 2015-04-13 21:51:35 +02:00
Mikael Nordfeldth eefef44378 filename is never used for indexing so let's make it text
varchar is pretty limited so let's avoid it if we can
2015-04-10 22:16:44 +02:00
Mikael Nordfeldth d7d96806a4 removed unused config setting 2015-04-10 13:15:12 +02:00
Mikael Nordfeldth 5e834e8119 We're logging this already elsewhere 2015-04-09 12:27:04 +02:00
Mikael Nordfeldth cbabab273f ImPlugin classes generally require background daemons in CLI
If someone designs an ImPlugin which _doesn't_ require the queues to be
handled in background daemons then they can set the requires_cli property
to false in their class.
2015-04-09 12:17:31 +02:00
Mikael Nordfeldth 0bd16b521c OpportunisticQM shouldn't try to handle what it can't find 2015-04-09 12:15:34 +02:00
Mikael Nordfeldth 07d92acfd0 Fix "unique notice form ID" code for reply forms 2015-04-06 17:35:29 +02:00
Mikael Nordfeldth ef1f17fc2a Don't use <object> for application/ogg
...this was actually because it would autoplay in Iceweasel/Firefox
despite all parameters for autoplay/autostart being set to false or 0.
2015-04-05 21:35:54 +02:00
Mikael Nordfeldth 5081477e95 enclosures in Atom were not included 2015-04-05 20:24:17 +02:00
Mikael Nordfeldth f094918cf6 Revert "Inverse logic error in OembedPlugin"
This reverts commit 9ab996d9e6.
2015-04-05 15:44:04 +02:00
Mikael Nordfeldth c94d9994d8 Merge branch 'nightly'
Conflicts:
	INSTALL
2015-04-05 15:35:54 +02:00
Mikael Nordfeldth f6432fdf48 File_thumbnail->getUrl now gives Attachment_thumbnail action URL
That in turn redirects to the statically stored file.
2015-04-03 21:21:39 +02:00
Mikael Nordfeldth 4fc4f91b9e Allow oEmbed data from all sites by default 2015-04-03 21:00:19 +02:00
Mikael Nordfeldth 9ab996d9e6 Inverse logic error in OembedPlugin 2015-04-03 20:59:56 +02:00
Mikael Nordfeldth 3cf5fe8795 bad URL is a clientError 2015-04-03 20:58:12 +02:00
Mikael Nordfeldth 94d3f50aee oEmbed Action logic simplified (early return) 2015-04-03 20:47:08 +02:00
Mikael Nordfeldth 3dc30b6b8f oEmbed helper never finished because of "break 2;" 2015-04-03 20:11:55 +02:00
Mikael Nordfeldth 8439efe77d Filter out img, video and audio tags in notice HTML
Because we don't want to auto-fetch items from a remote server. Such
items should be delivered as attachment metadata and portrayed in the
way the local instance chooses.

Choices for portrayal are either simply nullifying this and embedding
the data, linking the file remotely requiring a manual click or maybe
use remote oEmbed data etc. to download files locally so no remote
requests have to be made.
2015-03-15 14:35:29 +01:00
Mikael Nordfeldth a1098fa153 Marcus Moeller fixed some layout bugs I introduced 2015-03-15 14:22:36 +01:00
Mikael Nordfeldth 0b81fbd590 imitate ->boolean with $def=false 2015-03-14 16:04:03 +01:00
Mikael Nordfeldth f92fe73d03 php5-intl is required 2015-03-13 21:02:39 +01:00
Mikael Nordfeldth 4f2095ea00 No need to do pkeyGet if not repeated (thanks hannes)
Kind of reverts commit d9ed2a0
2015-03-13 09:49:09 +01:00
Mikael Nordfeldth d9ed2a0fae repeated did not always find the Notice (deleted?) 2015-03-13 00:19:08 +01:00
Mikael Nordfeldth 4d6b5e70df Add repeated_id to SimpleStatusArray for Qvitter's benefit 2015-03-13 00:02:48 +01:00
Mikael Nordfeldth a647a4f6b3 Moving some more repeat stuff into the Share plugin 2015-03-12 22:56:25 +01:00
Mikael Nordfeldth 2821be2bce Notice properties set in bad order on activityobject saving 2015-03-12 22:17:08 +01:00
Mikael Nordfeldth 0ff11ac978 Share never actually set the repeat_of value 2015-03-12 21:56:18 +01:00
Mikael Nordfeldth 5a235ffbf9 Event fixes for activityhandlerplugin 2015-03-12 21:53:44 +01:00
Mikael Nordfeldth 642f7f850d repeat actions to Share plugin 2015-03-12 21:46:10 +01:00
Mikael Nordfeldth 1adf5f2863 Merge branch 'nightly' into repeat_as_shareplugin 2015-03-12 20:54:06 +01:00
Mikael Nordfeldth 3ee673ac91 ImageFile->resize now totally replaced with resizeTo 2015-03-12 20:47:07 +01:00
Mikael Nordfeldth 20f8dd6565 Repeats shown in threaded noticelist now handled by plugin 2015-03-12 19:49:20 +01:00
Mikael Nordfeldth 940737a958 Finalize move of 'repeat' Command 2015-03-12 19:22:05 +01:00
Mikael Nordfeldth 1350987e2e Why did I keep these functions from FavoritePlugin? 2015-03-12 17:07:24 +01:00
Mikael Nordfeldth dc31a3d7d6 Receiving Share activity fixes
Forgot to translate 'self' to 'Ostatus_profile' etc.
2015-03-12 16:59:50 +01:00
Mikael Nordfeldth dcfcceb6f2 Share plugin now handles showing form in NoticeOptionItems 2015-03-12 16:33:34 +01:00
Mikael Nordfeldth d24c4f349f Move share command interpretation to SharePlugin
Some fixes to the SharePlugin.php file came along
2015-03-12 15:58:57 +01:00
Mikael Nordfeldth c85e78ac3c Remove unnecessary require lines and definitions
ProfileNoticeList and ProfileNoticeListItem are in their own files now too
2015-03-12 15:53:59 +01:00
Mikael Nordfeldth 7ddf586da7 Add ProfileNoticeList[Item] as separate lib class files 2015-03-12 15:53:28 +01:00
Mikael Nordfeldth 4e9e3cf0d5 Moving Ostatus_profile processShare to SharePlugin 2015-03-12 15:47:21 +01:00
Mikael Nordfeldth 5bea746fa8 Merge branch 'nightly' into repeat_as_shareplugin 2015-03-12 15:21:23 +01:00
Mikael Nordfeldth 5c8e56e8d2 Repeat confirmation dialogbox fix
until we use jQuery UI dialog stuff
2015-03-12 12:52:07 +01:00
Mikael Nordfeldth 6f0f8cd6c7 Initial work on making the Share verb handled in plugin 2015-03-12 12:27:49 +01:00
Mikael Nordfeldth 2a32af084f ImageFile $id argument is only for File objects
Remember to eliminate the Avatar/group logo call to ImageFile->resize!
2015-03-11 00:20:48 +01:00
Mikael Nordfeldth 6f76c8b59d Same as last commit, don't give ID if it's not for a File object 2015-03-11 00:14:14 +01:00
Mikael Nordfeldth 88411fb1ca ImageFile should not have an $id set if not a File 2015-03-10 23:52:50 +01:00
Mikael Nordfeldth 3302067aad javascript fixes for reply form fetching
It doesn't update the ID properly yet, which should be done to avoid
creating duplicate forms which are identical to HTML parsers...
2015-03-10 21:47:28 +01:00
Mikael Nordfeldth 0a2c51510c FormAction wants getInstructions to be protected
only showInstructions is public
2015-03-10 21:46:33 +01:00
Mikael Nordfeldth c79b9a2289 more descriptive setting name 2015-03-10 18:10:27 +01:00
Mikael Nordfeldth 8cfe72c683 SiteNoticeInSidebar widget did not define divId() 2015-03-10 17:33:58 +01:00
Mikael Nordfeldth 9ef224fceb ActivityVerb is a core plugin 2015-03-10 17:24:23 +01:00
Mikael Nordfeldth af67f15cf2 FavoritePlugin is now an "ActivityVerbHandlerPlugin" 2015-03-10 15:39:35 +01:00
Mikael Nordfeldth e338931ffa Let the creator decide which HTML tag to use for NoticeListItem 2015-03-10 13:07:36 +01:00
Mikael Nordfeldth 502f26299b Notice elements don't need to be floating...
Maybe it was originally meant to be without a comma between .notice and .profile?
2015-03-10 12:09:20 +01:00
Mikael Nordfeldth 8a273eef20 Move AlreadyFulfilled check to Fave::addNew 2015-03-10 11:56:23 +01:00
Mikael Nordfeldth fa080328cf favorite and like are synonyms of each other 2015-03-09 18:47:44 +01:00
Mikael Nordfeldth fa3457f391 First ActivityVerbPlugin sketch 2015-03-09 17:36:21 +01:00
Mikael Nordfeldth aa27c45230 Notice class got exception throwing getById
Less code, more happy.
2015-03-09 17:33:20 +01:00
Mikael Nordfeldth f321c3c2ea Make 'activity' a blacklisted nickname
Will add a plugin called ActivityVerb which makes activity interaction
more standardized.
2015-03-09 17:08:10 +01:00
Mikael Nordfeldth 9bb648739b The argument formatting regexps are the third argument 2015-03-09 15:31:07 +01:00
Mikael Nordfeldth 3287ecc8d3 Delete Faves onProfileDeleteRelated instead of User 2015-03-09 15:01:05 +01:00
Mikael Nordfeldth 1e89540c3f Merge branch 'nightly', beginning of 1.2.x
Conflicts:
	plugins/APC/locale/APC.pot
	plugins/APC/locale/ast/LC_MESSAGES/APC.po
	plugins/APC/locale/be-tarask/LC_MESSAGES/APC.po
	plugins/APC/locale/br/LC_MESSAGES/APC.po
	plugins/APC/locale/de/LC_MESSAGES/APC.po
	plugins/APC/locale/es/LC_MESSAGES/APC.po
	plugins/APC/locale/eu/LC_MESSAGES/APC.po
	plugins/APC/locale/fr/LC_MESSAGES/APC.po
	plugins/APC/locale/gl/LC_MESSAGES/APC.po
	plugins/APC/locale/he/LC_MESSAGES/APC.po
	plugins/APC/locale/ia/LC_MESSAGES/APC.po
	plugins/APC/locale/id/LC_MESSAGES/APC.po
	plugins/APC/locale/it/LC_MESSAGES/APC.po
	plugins/APC/locale/mk/LC_MESSAGES/APC.po
	plugins/APC/locale/ms/LC_MESSAGES/APC.po
	plugins/APC/locale/nb/LC_MESSAGES/APC.po
	plugins/APC/locale/nl/LC_MESSAGES/APC.po
	plugins/APC/locale/pl/LC_MESSAGES/APC.po
	plugins/APC/locale/pt/LC_MESSAGES/APC.po
	plugins/APC/locale/pt_BR/LC_MESSAGES/APC.po
	plugins/APC/locale/ru/LC_MESSAGES/APC.po
	plugins/APC/locale/tl/LC_MESSAGES/APC.po
	plugins/APC/locale/uk/LC_MESSAGES/APC.po
	plugins/APC/locale/zh_CN/LC_MESSAGES/APC.po
	plugins/Adsense/locale/Adsense.pot
	plugins/Adsense/locale/be-tarask/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/br/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/ca/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/de/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/es/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/eu/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/fr/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/gl/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/he/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/ia/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/it/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/ja/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/ka/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/lb/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/lt/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/mk/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/ms/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/nb/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/nl/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/pl/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/pt/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/pt_BR/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/ru/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/sv/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/tl/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/tr/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/uk/LC_MESSAGES/Adsense.po
	plugins/Adsense/locale/zh_CN/LC_MESSAGES/Adsense.po
	plugins/Aim/locale/Aim.pot
	plugins/Aim/locale/af/LC_MESSAGES/Aim.po
	plugins/Aim/locale/ca/LC_MESSAGES/Aim.po
	plugins/Aim/locale/de/LC_MESSAGES/Aim.po
	plugins/Aim/locale/es/LC_MESSAGES/Aim.po
	plugins/Aim/locale/eu/LC_MESSAGES/Aim.po
	plugins/Aim/locale/fi/LC_MESSAGES/Aim.po
	plugins/Aim/locale/fr/LC_MESSAGES/Aim.po
	plugins/Aim/locale/gl/LC_MESSAGES/Aim.po
	plugins/Aim/locale/ia/LC_MESSAGES/Aim.po
	plugins/Aim/locale/it/LC_MESSAGES/Aim.po
	plugins/Aim/locale/mk/LC_MESSAGES/Aim.po
	plugins/Aim/locale/ms/LC_MESSAGES/Aim.po
	plugins/Aim/locale/nl/LC_MESSAGES/Aim.po
	plugins/Aim/locale/pl/LC_MESSAGES/Aim.po
	plugins/Aim/locale/pt/LC_MESSAGES/Aim.po
	plugins/Aim/locale/sv/LC_MESSAGES/Aim.po
	plugins/Aim/locale/tl/LC_MESSAGES/Aim.po
	plugins/Aim/locale/uk/LC_MESSAGES/Aim.po
	plugins/Blog/locale/Blog.pot
	plugins/Blog/locale/ar/LC_MESSAGES/Blog.po
	plugins/Blog/locale/br/LC_MESSAGES/Blog.po
	plugins/Blog/locale/ca/LC_MESSAGES/Blog.po
	plugins/Blog/locale/de/LC_MESSAGES/Blog.po
	plugins/Blog/locale/es/LC_MESSAGES/Blog.po
	plugins/Blog/locale/eu/LC_MESSAGES/Blog.po
	plugins/Blog/locale/fr/LC_MESSAGES/Blog.po
	plugins/Blog/locale/gl/LC_MESSAGES/Blog.po
	plugins/Blog/locale/ia/LC_MESSAGES/Blog.po
	plugins/Blog/locale/it/LC_MESSAGES/Blog.po
	plugins/Blog/locale/lt/LC_MESSAGES/Blog.po
	plugins/Blog/locale/mk/LC_MESSAGES/Blog.po
	plugins/Blog/locale/nl/LC_MESSAGES/Blog.po
	plugins/Blog/locale/tl/LC_MESSAGES/Blog.po
	plugins/Blog/locale/tr/LC_MESSAGES/Blog.po
	plugins/Irc/locale/Irc.pot
	plugins/Irc/locale/ca/LC_MESSAGES/Irc.po
	plugins/Irc/locale/de/LC_MESSAGES/Irc.po
	plugins/Irc/locale/es/LC_MESSAGES/Irc.po
	plugins/Irc/locale/eu/LC_MESSAGES/Irc.po
	plugins/Irc/locale/fi/LC_MESSAGES/Irc.po
	plugins/Irc/locale/fr/LC_MESSAGES/Irc.po
	plugins/Irc/locale/gl/LC_MESSAGES/Irc.po
	plugins/Irc/locale/ia/LC_MESSAGES/Irc.po
	plugins/Irc/locale/it/LC_MESSAGES/Irc.po
	plugins/Irc/locale/ja/LC_MESSAGES/Irc.po
	plugins/Irc/locale/mk/LC_MESSAGES/Irc.po
	plugins/Irc/locale/nl/LC_MESSAGES/Irc.po
	plugins/Irc/locale/sv/LC_MESSAGES/Irc.po
	plugins/Irc/locale/tl/LC_MESSAGES/Irc.po
	plugins/Irc/locale/tr/LC_MESSAGES/Irc.po
	plugins/Irc/locale/uk/LC_MESSAGES/Irc.po
	plugins/Spotify/locale/Spotify.pot
	plugins/Spotify/locale/de/LC_MESSAGES/Spotify.po
	plugins/Spotify/locale/es/LC_MESSAGES/Spotify.po
	plugins/Spotify/locale/fr/LC_MESSAGES/Spotify.po
	plugins/Spotify/locale/gl/LC_MESSAGES/Spotify.po
	plugins/Spotify/locale/he/LC_MESSAGES/Spotify.po
	plugins/Spotify/locale/ia/LC_MESSAGES/Spotify.po
	plugins/Spotify/locale/mk/LC_MESSAGES/Spotify.po
	plugins/Spotify/locale/nl/LC_MESSAGES/Spotify.po
	plugins/Spotify/locale/sv/LC_MESSAGES/Spotify.po
	plugins/Spotify/locale/tl/LC_MESSAGES/Spotify.po
	plugins/TinyMCE/locale/TinyMCE.pot
	plugins/TinyMCE/locale/ca/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/de/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/eo/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/es/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/fr/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/gl/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/he/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/ia/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/id/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/ja/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/mk/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/ms/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/nb/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/nl/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/pt/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/pt_BR/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/ru/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/tl/LC_MESSAGES/TinyMCE.po
	plugins/TinyMCE/locale/uk/LC_MESSAGES/TinyMCE.po
	plugins/XCache/locale/XCache.pot
	plugins/XCache/locale/ast/LC_MESSAGES/XCache.po
	plugins/XCache/locale/br/LC_MESSAGES/XCache.po
	plugins/XCache/locale/de/LC_MESSAGES/XCache.po
	plugins/XCache/locale/es/LC_MESSAGES/XCache.po
	plugins/XCache/locale/eu/LC_MESSAGES/XCache.po
	plugins/XCache/locale/fi/LC_MESSAGES/XCache.po
	plugins/XCache/locale/fr/LC_MESSAGES/XCache.po
	plugins/XCache/locale/gl/LC_MESSAGES/XCache.po
	plugins/XCache/locale/he/LC_MESSAGES/XCache.po
	plugins/XCache/locale/ia/LC_MESSAGES/XCache.po
	plugins/XCache/locale/id/LC_MESSAGES/XCache.po
	plugins/XCache/locale/mk/LC_MESSAGES/XCache.po
	plugins/XCache/locale/ms/LC_MESSAGES/XCache.po
	plugins/XCache/locale/nb/LC_MESSAGES/XCache.po
	plugins/XCache/locale/nl/LC_MESSAGES/XCache.po
	plugins/XCache/locale/pl/LC_MESSAGES/XCache.po
	plugins/XCache/locale/pt/LC_MESSAGES/XCache.po
	plugins/XCache/locale/pt_BR/LC_MESSAGES/XCache.po
	plugins/XCache/locale/ru/LC_MESSAGES/XCache.po
	plugins/XCache/locale/tl/LC_MESSAGES/XCache.po
	plugins/XCache/locale/tr/LC_MESSAGES/XCache.po
	plugins/XCache/locale/uk/LC_MESSAGES/XCache.po
	plugins/YammerImport/locale/YammerImport.pot
	plugins/YammerImport/locale/br/LC_MESSAGES/YammerImport.po
	plugins/YammerImport/locale/de/LC_MESSAGES/YammerImport.po
	plugins/YammerImport/locale/es/LC_MESSAGES/YammerImport.po
	plugins/YammerImport/locale/eu/LC_MESSAGES/YammerImport.po
	plugins/YammerImport/locale/fr/LC_MESSAGES/YammerImport.po
	plugins/YammerImport/locale/gl/LC_MESSAGES/YammerImport.po
	plugins/YammerImport/locale/ia/LC_MESSAGES/YammerImport.po
	plugins/YammerImport/locale/mk/LC_MESSAGES/YammerImport.po
	plugins/YammerImport/locale/ms/LC_MESSAGES/YammerImport.po
	plugins/YammerImport/locale/nl/LC_MESSAGES/YammerImport.po
	plugins/YammerImport/locale/pl/LC_MESSAGES/YammerImport.po
	plugins/YammerImport/locale/ru/LC_MESSAGES/YammerImport.po
	plugins/YammerImport/locale/tl/LC_MESSAGES/YammerImport.po
	plugins/YammerImport/locale/tr/LC_MESSAGES/YammerImport.po
	plugins/YammerImport/locale/uk/LC_MESSAGES/YammerImport.po
2015-03-09 11:01:17 +01:00
Mikael Nordfeldth 5a3a3420e3 Merge commit 'refs/merge-requests/56' of https://gitorious.org/social/mainline into merge-requests/56 2015-03-09 10:39:27 +01:00
Mikael Nordfeldth 8ae1328e71 DB_DataObject won't save value 0 because it is "false"
A bug which we fix here and there by sending the string '0' instead.
We will be able to remove these hacks ("booleanintstring") when the
next release of DB_DataObject comes as I patched it for them.
2015-03-08 23:32:56 +01:00
Mikael Nordfeldth 6f61b4488e Make the OpenID settings page use more of HTMLOutputter functions 2015-03-08 23:31:35 +01:00
Mikael Nordfeldth 474c8bef0a Don't display labels by default in notice forms
There are either descriptive placeholders or informational text next to
the elements.
2015-03-08 23:30:54 +01:00
Mikael Nordfeldth 7aa1e02d06 Don't use a placeholder value on the nickname field
(because the placeholder would be 'Nickname', and it might confuse
someone who thinks they can use capital letters...)
2015-03-08 23:29:38 +01:00
Mikael Nordfeldth b41c6824c5 Let text inputs have placeholder values. 2015-03-08 23:29:16 +01:00
Mikael Nordfeldth 05006f687a Move more POST handling into ManagedAction 2015-03-08 21:08:27 +01:00
Mikael Nordfeldth 1ea876296d A bunch of FormAction and ManagedAction synchronization 2015-03-08 20:41:42 +01:00
Mikael Nordfeldth 55894f02c7 TagProfileAction and OStatusPlugin now use less redundant code 2015-03-08 20:14:46 +01:00
Mikael Nordfeldth 32dacb9369 ROLLBACK queries in the proper order 2015-03-08 19:44:23 +01:00
Mikael Nordfeldth d6423bbbc8 Sensitive-test _is_ done in index.php 2015-03-08 19:17:01 +01:00
Mikael Nordfeldth 1442ca16b4 Some reply buttons wouldn't work the first time they were clicked. 2015-03-08 12:54:08 +01:00
Mikael Nordfeldth 1a1b992858 RepliesAction migrated to extend ManagedAction 2015-03-08 12:38:15 +01:00
digital dreamer a452a3b1a0 Snapshot of the Transifex translation project - February 2015 2015-03-08 09:34:38 +01:00
Mikael Nordfeldth 3c5383b11c All the AJAX calls should be made with $.ajax
because we're gonna want to expect application/xml or text/xml back.

There's a weird thing in Firefox where the call on line ~703 makes the
web developer console output "not well formed" which is for the returned
data. It is assumed to be text/xml - which it is - but the doctype says
"html" (because it is first <?xml..?> followed by <!DOCTYPE html ...->

This doesn't cause any malfunction right now, just the output in the
console. I'm not exactly sure how to fix it. Probably remove the DOCTYPE
output for AJAX calls, but I'm not sure that's the best way. Could this
maybe even be a browser/javascript/whatever bug? Because the Content-Type
from the server _is_ right...
2015-03-08 01:36:59 +01:00
Mikael Nordfeldth 77190c9a87 Need to run the NoticeFormSetup if forms are prerendered 2015-03-07 23:42:27 +01:00
Mikael Nordfeldth 75d45dace9 Don't put submit button in reply field edge-to-edge 2015-03-07 23:38:03 +01:00
Mikael Nordfeldth b604630a74 Don't put reply in a popup, it was undesired for users
Maybe could make that optional or something in the DefaultLayout plugin...
2015-03-07 23:36:27 +01:00
Mikael Nordfeldth 9deff7afaf Email settings fix for the DB_DataObject bug for saving value 0 2015-03-07 21:57:43 +01:00
Mikael Nordfeldth 4e682f3d88 Reply popup works now
...WHY does javascript let me define the same value twice in the same
definition without warning about it? I hate Javascript. :(
2015-03-07 20:35:05 +01:00
Mikael Nordfeldth 196df7d8a4 Change the title of NewnoticeAction if replying 2015-03-07 20:34:46 +01:00
Mikael Nordfeldth 98b65763b0 input elements outside of label elements
HTML lets us put the input element inside the label and then they
are automatically paired, but this is more explicit and clear imho.
2015-03-07 20:11:13 +01:00
Mikael Nordfeldth aefaef3ead jquery-ui updated to 1.11.3
Checked all checkboxes on http://jqueryui.com/download/
2015-03-07 14:14:19 +01:00
Mikael Nordfeldth be15ab47dc jquery infieldlabel.js removed from script list 2015-03-07 12:32:24 +01:00
Mikael Nordfeldth bc1d667784 jQuery cookie plugin updated
Source: https://plugins.jquery.com/cookie/
2015-03-07 01:00:07 +01:00
Mikael Nordfeldth 395c2cc075 JSON in JavaScript library updated
...why we now need a JSON library... _in_ Javascript?!
Source: http://www.json.org/js.html
2015-03-07 00:57:21 +01:00
Mikael Nordfeldth a6c03e3127 jQuery Form Plugin updated
Source: http://malsup.com/jquery/form/
2015-03-07 00:55:17 +01:00
Mikael Nordfeldth 6080f6673e "infield labels" should be migrated to HTML5 placeholder 2015-03-07 00:49:05 +01:00
Mikael Nordfeldth fab08278ea jQuery v2.1.3 seems to work fine 2015-03-07 00:48:43 +01:00
Mikael Nordfeldth 6b147175bb Start working a bit more consistently with "notice-options"
Let's get the AJAX response and present it to the user with the same
mechanisms for all actions, instead of having a bunch of javascript
for various circumstances (fave, repeat, delete should all be the same
behaviour for example).
2015-03-07 00:32:26 +01:00
Mikael Nordfeldth 503c05b749 No need for NoticeFormMaster anymore 2015-03-07 00:00:02 +01:00
Mikael Nordfeldth 1303943424 Choose whether to prerender the inline reply forms
The DefaultLayout plugin will come with options to render various parts
of the page by default or not. The expected default behaviour will try
to imitate the original StatusNet/GNU social looks as far as possible.
2015-03-06 23:52:25 +01:00
Mikael Nordfeldth 8cf0628f28 Replies to replies without reloading page now work 2015-03-06 23:47:03 +01:00
Mikael Nordfeldth c48a9191c8 Hide the threaded-replies gray line. 2015-03-06 23:46:08 +01:00
Mikael Nordfeldth 38f977d2f3 Make sure we save 0 as '0' because of DB_DataObject bug 2015-03-06 23:21:57 +01:00
Mikael Nordfeldth 45861c6d9c Reply notice forms are functional again, but not AJAX 2015-03-06 21:20:46 +01:00
Mikael Nordfeldth 8abc2d3b8d Remove some more reply-placeholder stuff 2015-03-06 20:42:50 +01:00
Mikael Nordfeldth 0da7512597 No separate placeholder input element for replyforms
Also we're moving the rendering of these out into a separate plugin. Not
done yet, some javascript should be moved out as well.
2015-03-06 20:22:01 +01:00
Mikael Nordfeldth 13c331fa81 Make NoticeForm return the proper placeholder text
Also fixes some comments and uncertainties in the beginning of the
class definition.
2015-03-06 20:04:09 +01:00
Mikael Nordfeldth 62596d462b Get the values from the correct object. 2015-03-06 00:47:18 +01:00
Mikael Nordfeldth f35ea45e09 Values of 0 would not be updated because of DB_DataObject
Upstream bug causing (int)0 to be interpreted as a "null string":
https://pear.php.net/bugs/bug.php?id=20291
2015-03-06 00:44:00 +01:00
Mikael Nordfeldth 72015d499f Actually show all images as <img /> tags.
Browsers should be secure enough by now for this.
2015-03-05 11:59:31 +01:00
Mikael Nordfeldth 3755faf558 SVG files can be used as thumbnails I guess 2015-03-05 11:59:11 +01:00
Mikael Nordfeldth ff6969302b Some SVG files are "text/html" according to 'file' 2015-03-05 11:54:30 +01:00
Mikael Nordfeldth d7fd507d99 ImageMagick sucks at vector graphics, so only use for rasterization 2015-03-05 11:53:52 +01:00
Mikael Nordfeldth 4c2bbf2354 ImageMagick plugin can now make thumbnails of SVG files 2015-03-04 13:50:20 +01:00
Mikael Nordfeldth 22dbeaef29 Used ->find(true) on wrong object 2015-03-04 13:46:51 +01:00
Mikael Nordfeldth 9720fd8250 Reset imgPath variable if VideoThumbnails failed 2015-03-04 13:45:42 +01:00
Mikael Nordfeldth f6df1f1dd3 Documentation and more understandable code. 2015-03-04 13:29:18 +01:00
Mikael Nordfeldth 286b54e527 Use getUrl() on File and File_thumbnail instead of ->url 2015-03-04 13:13:20 +01:00
Mikael Nordfeldth a4af51b5ba Move thumbnail algorithm mainly to ImageFile class 2015-03-04 13:12:42 +01:00
Mikael Nordfeldth dcfb813066 Free ImageMagick object from memory when done with it 2015-03-04 12:18:44 +01:00
Mikael Nordfeldth fe9dc8e901 ImageMagickPlugin refactored so we can more easily add new formats 2015-03-04 12:09:22 +01:00
Mikael Nordfeldth 284705eeb8 Subscription_queue::start does not mean Subscription exists 2015-03-04 11:49:54 +01:00
Mikael Nordfeldth ec4e432d55 Subscription::ensureStart skips AlreadyFulfilledException
Sometimes we just want to accept the user's wrong, but when it comes
to remote APIs etc. we probably want to let the client know it has
done something already (in this case multiple identical subscription
requests - which might indicate to it that it should refresh the sub
lists or something).
2015-03-04 11:38:04 +01:00
Mikael Nordfeldth 8c933a6c06 FillImageFileMetadata event documented 2015-03-02 20:37:59 +01:00
Mikael Nordfeldth 325199b5e6 Bug tracker link updated. 2015-03-01 16:48:01 +01:00
Mikael Nordfeldth 80bf185ad5 Blog depended on TinyMCE which was unmaintained 2015-03-01 14:32:48 +01:00
Mikael Nordfeldth 19bf975e56 Aahhh, gotta run php -l before pushing stuff!!! 2015-03-01 12:47:48 +01:00
Mikael Nordfeldth 1227d2d710 Forgot to make syntax edits on last commit. 2015-03-01 12:45:58 +01:00
Mikael Nordfeldth bece816ec7 User class throws exception on register failure 2015-03-01 12:36:19 +01:00
Mikael Nordfeldth 7fdf2f50f4 Allow changing nick on EmailRegistration
Nothing said that the EmailRegistration plugin was meant to restrict
the nickname to the local part of the email address. Let users change
it before they actually register the user.
2015-03-01 12:31:52 +01:00
Mikael Nordfeldth 746e658f3e Don't log every included config file
but let us retrieve the list by running GNUsocial::configFiles()
2015-02-28 13:04:17 +01:00
Mikael Nordfeldth caa0dd549e Avatar table url field now 'text', maybe use filename as unique key? 2015-02-28 12:56:42 +01:00
Mikael Nordfeldth 49cf19ccfe INSTALL file overhaul, mostly done. 2015-02-27 16:06:05 +01:00
Mikael Nordfeldth 6abcc24834 htaccess.sample updating 2015-02-27 15:42:45 +01:00
Mikael Nordfeldth fd53bb404f ssh key based easy upgrade method documentation 2015-02-27 15:07:44 +01:00
Mikael Nordfeldth dceb67c247 Better UPGRADE documentation for GS->GS upgrade 2015-02-27 15:03:07 +01:00
Mikael Nordfeldth b3e299b931 StatusNet 1.1.x to GNU social 1.2.x instructions updated 2015-02-27 14:47:54 +01:00
Mikael Nordfeldth 818e895af1 UPGRADE file had incorrect commands 2015-02-27 14:12:01 +01:00
Mikael Nordfeldth 7e65f4f6ea StatusNet to GNU social renaming in minor places 2015-02-27 12:55:25 +01:00
Mikael Nordfeldth 8fac7a9f6c StatusNet class renamed GNUsocial
also added backward compatible StatusNet class for the two calls I know
third party plugins use, isHTTPS and getActivePlugins
2015-02-27 12:44:15 +01:00
Mikael Nordfeldth f25e5e3860 Start and EndActionExecute added/fixed/documented 2015-02-27 12:11:43 +01:00
Mikael Nordfeldth 1cc96cd334 1.2.x branch started (utf8mb4 support is reason enough) 2015-02-27 10:09:57 +01:00
Mikael Nordfeldth 4e26527447 Change branch to 1.2.x since we're utf8mb4 now 2015-02-27 10:04:29 +01:00
Mikael Nordfeldth c214aa5149 Merge branch 'master' into nightly
Conflicts:
	lib/apiaction.php
2015-02-27 10:01:55 +01:00
Mikael Nordfeldth 48f8f3f5cf php5-intl is recommended but not required 2015-02-26 22:58:36 +01:00
Mikael Nordfeldth 0b09e4bfcb Normalize username on AuthCrypt login
Because users login with mixed casing and whatnot.
2015-02-26 00:45:17 +01:00
Mikael Nordfeldth 4eab52ee75 Attachment list items have more sane margins around them 2015-02-26 00:12:34 +01:00
Mikael Nordfeldth b8e4f41987 Notice character count now adapts to resized textbox 2015-02-25 16:40:59 +01:00
Mikael Nordfeldth f7553d73a2 501 Not Implemented on timelines for remote users. 2015-02-25 16:31:02 +01:00
Mikael Nordfeldth b0e767eaf1 NoticeOptions above NoticeAttachments 2015-02-25 16:22:59 +01:00
Mikael Nordfeldth 82ef687730 Removing some plugins that were moved to plugins-unmaintained
See https://gitorious.org/social/plugins-unmaintained/
2015-02-25 15:47:14 +01:00
Mikael Nordfeldth 7e6ba94241 Documentation + filename uniqueness in File class 2015-02-25 15:19:27 +01:00
Mikael Nordfeldth 46a41f48ca Merge commit 'refs/merge-requests/55' of https://gitorious.org/social/mainline into merge-requests/55 2015-02-25 12:59:19 +01:00
Mikael Nordfeldth 86a8f4c5c7 Removed Lato font from themes where it was unnecessary 2015-02-25 12:56:41 +01:00
Mikael Nordfeldth afbb3ec37a Merge commit 'refs/merge-requests/51' of https://gitorious.org/social/mainline into merge-requests/51 2015-02-25 12:52:35 +01:00
Mikael Nordfeldth d0ef37a487 trailing whitespace 2015-02-25 12:50:56 +01:00
Mikael Nordfeldth 611e5ab421 Merge commit 'refs/merge-requests/49' of https://gitorious.org/social/mainline into merge-requests/49 2015-02-25 12:49:58 +01:00
Mikael Nordfeldth 38729133e2 HTML5 media <source> tags are short tags 2015-02-25 12:49:15 +01:00
Mikael Nordfeldth ce0b221573 avconv required -f image2 not -f mjpeg at least on my server 2015-02-25 01:44:00 +01:00
Mikael Nordfeldth 95b61a5e12 Only local files to be passed through VideoThumbnails 2015-02-25 01:37:57 +01:00
Mikael Nordfeldth 3bbb748a08 VideoThumbnails changed to use 'exec' call to avconv 2015-02-25 01:36:14 +01:00
Mikael Nordfeldth 9a843548c0 Save thumbnails with proper extension
This might cause double extensions, but that's ok since the filename
is stored in the database. We might want to look at it later though.
2015-02-25 01:34:00 +01:00
Mikael Nordfeldth 220a13b87f mimetype added to ImageFile 2015-02-25 01:33:32 +01:00
Mikael Nordfeldth 4b8301d39e ImageFile constructor changed to align with existing code
Noone passed type, width or height to new ImageFile(...) and
in all instances, both parameters were set (though $id is null on occasion).
2015-02-25 01:31:44 +01:00
Mikael Nordfeldth 0854a84eb9 Throw more explicit exception in ImageFile 2015-02-25 01:14:27 +01:00
Mikael Nordfeldth ce91f1c0e6 Hide posts from users with private_stream in scoping streams
For example the public timeline would show notices from a user with
private_stream configured. (previously it would only hide _new_ notices
by this user as they would be the only ones with notice scoping set).
2015-02-24 22:59:58 +01:00
Mikael Nordfeldth 060dbe1b56 Removing whitespace and creating an early-return in inScope 2015-02-24 22:44:43 +01:00
buttle b9d4a9c9f9 added DocNav EVENT
Event to overide DocNav
two small css changes to indent notice footer correctly.
2015-02-24 21:51:31 +01:00
Mikael Nordfeldth 325e784ccd Don't store duplicates of files.
If a new file is uploaded, it will be matched with a previously uploaded
file so we don't have to store duplicates. SHA256 is random enough and
also unlikely enough to cause collisions.
2015-02-24 21:11:25 +01:00
Mikael Nordfeldth 0d577584c3 Script to delete file table entries which have disappeared locally 2015-02-24 19:29:28 +01:00
Mikael Nordfeldth 27bc654b5b RSSCloud URL field too long for utf8mb4
Should be the last one. If any URLs are longer than 191 chars, it might
require more manual interaction. Any instance with problems running
scripts/upgrade.php will get special treatment, help and a lollipop.
2015-02-21 16:43:21 +01:00
Mikael Nordfeldth c1e3cfe7a7 ensureFeedURL will return Ostatus_profile early if already stored 2015-02-20 14:47:12 +01:00
Mikael Nordfeldth 96099807e1 Default install to site profile community 2015-02-20 01:00:28 +01:00
Mikael Nordfeldth b639a25856 Emoji support through utf8mb4 seems to be done!
scripts/upgrade.php will take a _long_ time though! But it's worth it.
2015-02-19 22:13:42 +01:00
Mikael Nordfeldth 0e6c83e521 Had to avoid using indexes in the migration phase
File and File_redirection still had their indexes in the temporary migration table definition.
2015-02-19 22:06:43 +01:00
Mikael Nordfeldth 987232a0a6 Remove common_debug call that slipped by 2015-02-19 21:26:55 +01:00
Mikael Nordfeldth b54710950f unique keys and indexes must be NOT NULL or MySQL fucks up
If this merge throws exception on scripts/upgrade.php and you recently
tried a nightly (i.e. during 2015-02-19) then just go back a commit or two
and try again.

Or delete the duplicate entries. Find the entries like this:

SELECT COUNT(*), urlhash FROM file_redirection
    GROUP BY urlhash
    HAVING COUNT(*) > 1;

then for each urlhash (or come up with a smart SQL query) do:
DELETE FROM file_redirection WHERE urlhash='hashfrompreviousquery' LIMIT 1;

You'll have to remove duplicates more than once if you have >2 identical
urlhash entries. LIMIT -1 might do that for you. I'm not sure.
2015-02-19 21:21:39 +01:00
Mikael Nordfeldth d061e1065e Some loose table definitions which needed 191 char indexes
because we want utf8mb4 so badly!
2015-02-19 21:02:14 +01:00
Mikael Nordfeldth 0590f2975e Merge branch 'utf8mb4' into nightly
Conflicts because of urlhash fixes:
	classes/File.php
	classes/File_redirection.php
	classes/File_thumbnail.php
2015-02-19 20:50:40 +01:00
Mikael Nordfeldth 5471c65c9a less newlines for the scripts/upgrade.php output 2015-02-19 19:40:36 +01:00
Mikael Nordfeldth e299583eee Bad check on existing urlhash key 2015-02-19 19:36:59 +01:00
Mikael Nordfeldth 8ac8e2e734 Use new ::getByUrl for File and File_redirection
and make use of the exceptions instead endless if statements
2015-02-19 19:29:55 +01:00
Mikael Nordfeldth 5b940f255f Mediafile updated to insert urlhash and lookup properly 2015-02-19 19:19:47 +01:00
Mikael Nordfeldth c05e9b118c function is hashurl, variable is urlhash 2015-02-19 19:07:43 +01:00
Mikael Nordfeldth 45dc76de26 File and File_redirection adhoc storage methods updated for urlhash 2015-02-19 19:05:24 +01:00
Mikael Nordfeldth 0dfe39ac87 File_thumbnail url is not an index 2015-02-19 18:59:13 +01:00
Mikael Nordfeldth 27480d8e8e File_redirection also got urlhash column 2015-02-19 18:34:48 +01:00
Mikael Nordfeldth 176bde269f Merge branch 'nightly' into file_urlhash 2015-02-19 18:13:09 +01:00
Mikael Nordfeldth df2cc09362 $this->scoped->getUser() instead of common_current_user(); 2015-02-19 17:46:37 +01:00
Mikael Nordfeldth 042cb1604a ROLLBACK if query failed in email settings savePreferences 2015-02-19 17:43:08 +01:00
Mikael Nordfeldth 0acf3e0e30 Profile table cleaning script. 2015-02-18 14:01:35 +01:00
Mikael Nordfeldth 4ad7e8f459 UserdirectoryAction now ManagedAction and better SQL 2015-02-18 13:37:06 +01:00
Mikael Nordfeldth d445e0c877 No need for return true 2015-02-18 13:18:32 +01:00
Mikael Nordfeldth e64ac4c418 GroupdirectoryAction now has no direct SQL queries
also various fixes uppers
2015-02-18 12:17:26 +01:00
Mikael Nordfeldth 94e19e1ac6 escapedTableName for SQL query easy access 2015-02-18 12:15:46 +01:00
Mikael Nordfeldth a254f38a23 Turn GroupdirectoryAction into a ManagedAction 2015-02-18 11:15:30 +01:00
Mikael Nordfeldth 52e0ce8b06 Directory group search code cleanup 2015-02-18 11:13:10 +01:00
Mikael Nordfeldth b039d960f5 Make group search in Directory use PEAR::DB
No more direct SQL queries please.
2015-02-18 11:08:11 +01:00
Mikael Nordfeldth 66df043c19 Add php5-intl dependency to Installer class 2015-02-18 00:47:00 +01:00
Mikael Nordfeldth 8fbdb4b9ac New dependency: php5-intl
Internationalization support is required for transliteration, which is
currently used when creating the slugs for hashtags and such. It is a
much more stable and efficient solution than having an unmaintainable
list of unciode characters in an array...
2015-02-18 00:28:45 +01:00
Mikael Nordfeldth 0deaf6c50c use common_purify to purify HTML, one function to rule them all 2015-02-18 00:14:28 +01:00
Mikael Nordfeldth 3dce6d9f6a Implement a common_purify for htmLawed and more
We're removing unicode formatting characters as well, such as RTL marks.
For more info on why we're because extra cautious (but may accept the
characters in later versions) you can read:
https://blog.malwarebytes.org/online-security/2014/01/the-rtlo-method/
2015-02-18 00:10:31 +01:00
Mikael Nordfeldth 9aa59c7f62 forgot primary key column to updateWithKeys in SalmonAction 2015-02-17 21:31:35 +01:00
Mikael Nordfeldth 7ba7f43199 Don't linkify bare domains by default
It's too farfetched to assume any text.com in a notice is an HTTP URL.
For example stuff like pasting from log entries, with domain.com:1234
where 1234 is a _PID_ or something, not a port number for http://...
2015-02-17 20:54:32 +01:00
Mikael Nordfeldth c31c2d10b9 PHP>=5.4.0 lets us use Transliterator, tags now asciified!
For example: #REVOLUCIÓN becomes #revolucion instead of #revolución
2015-02-17 20:17:22 +01:00
Mikael Nordfeldth 5a8f24eb46 urlhash first steps, including scripts/upgrade.php 2015-02-17 18:55:12 +01:00
Mikael Nordfeldth 59763ceecb SalmonAction now updates remote URI if it was stale.
After doublechecking two identities so that they match (like one that was
previously http:// but now is https://) we update the URI in our database
to match.

This has to be verified so it's not easy to fool our script and thus make
us replace legitimate URIs with fake ones. I believe the callback method
is safe, but I'm not sure how well it handles HTTP MITM attacks etc.
2015-02-17 17:35:45 +01:00
Mikael Nordfeldth 282f4d6a89 Various $this->scoped fixes and protected prepare/handle in API actions 2015-02-17 17:20:00 +01:00
Mikael Nordfeldth 6cdedf6049 Replace $this->user/auth_user with $this->scoped in lib/apiaction.php
We prefer handling a Profile class rather than the User class, as some
functions might be useful for remote users as well, which cannot be
handled via the User class.
2015-02-17 17:16:33 +01:00
Mikael Nordfeldth 61aa71ed34 Subscription class gets exception throwing getSubscription function 2015-02-17 17:15:47 +01:00
Mikael Nordfeldth 901a825b61 Non-functional "retweeted to me" API call modified (but not fixed)
For some reason the "retweeted to me" part of the Twitter API was removed
when Evan made some inbox changes back in the StatusNet days. We might
recover this functionality, but not yet. The proper function calls are
however fixed in this commit.
2015-02-17 16:48:24 +01:00
Mikael Nordfeldth 75f35bcfe7 apiauth action with ->user changed to ->scoped 2015-02-17 16:39:27 +01:00
Mikael Nordfeldth 406b6148f5 CSS: notice images no wider than 100%
We should actually not allow remote images to be given in the src attribute
because they can be used for tracking and other nasty stuff without being
seen by the enduser.

Also, allowing remote images linked like this won't work for users who run
plugins like RequestPolicy etc. anyway. A better method would be to make
them listed as attachments instead. Then we can use that subsystem for
making thumbnails to store locally, hotlinking sources and whatnot.
2015-02-17 01:26:18 +01:00
Marcus Moeller f7b41625e5 opacity is not needed as it's transparent
use alignment instead of padding for padlock symbol
2015-02-16 17:50:43 +01:00
Marcus Moeller 0168fddae5 updated font settings to match qvitter 2015-02-16 17:37:13 +01:00
Chimo ef780d5034 Move people tag autocomplete JS to plugin
As discussed in https://gitorious.org/social/mainline/merge_requests/47
2015-02-15 19:10:05 -05:00
Mikael Nordfeldth 6862184956 Merge commit 'refs/merge-requests/47' of https://gitorious.org/social/mainline into merge-requests/47 2015-02-15 23:06:22 +01:00
Mikael Nordfeldth 2b181b40f7 Merge commit 'refs/merge-requests/48' of https://gitorious.org/social/mainline into merge-requests/48 2015-02-15 22:54:48 +01:00
Marcus Moeller 4c457c82ef removed text beside lock icon and fixed alignment 2015-02-15 22:47:34 +01:00
Chimo 3f8a519980 JS: Fixes jQueryUI autocomplete 'undefined' errors
data("autocomplete") was renamed to data("ui-autocomplete") starting
from v1.9:
http://jqueryui.com/upgrade-guide/1.9/#changed-naming-convention-for-data-keys
2015-02-15 16:11:23 -05:00
Chimo fb03fc073a ApiTimelineList: Fixes ServerErrorAction
"No matches for action 'ApiTimelineList' with arguments 'format=atom
id=1'"

for 'api/:user/lists/:id/statuses.:format' URLs
2015-02-15 16:00:23 -05:00
Mikael Nordfeldth 2b93643277 Don't default to publishing http: alias!
It seems to have caused a problem with at least an older codebase of
remote GNU social sites, but either way we shouldn't present the user
as aliased on an insecure connection if there is no real reason to.
2015-02-15 13:33:36 +01:00
Mikael Nordfeldth 396f1e92ca Present http:// alias by default in WebFinger output
because it might help us (and especially StatusNet sites) to recognize
profiles that have migrated from HTTP to HTTPS!
2015-02-15 13:17:51 +01:00
Mikael Nordfeldth c60b6bdb38 Wrong order of start/end events. My hobby OCD was disturbed. 2015-02-14 17:37:35 +01:00
Mikael Nordfeldth 9c83ddc122 Fixed some recently added EVENTS documentation 2015-02-14 17:35:34 +01:00
Mikael Nordfeldth b6b9036821 StartSubMenu and EndSubMenu events 2015-02-14 17:32:35 +01:00
Mikael Nordfeldth dc0b62f636 Merge commit 'refs/merge-requests/45' of https://gitorious.org/social/mainline into merge-requests/45 2015-02-14 16:45:04 +01:00
Mikael Nordfeldth 9102429a13 neo-quitter unuglification by marcus, merge-request 44 2015-02-14 16:42:44 +01:00
Marcus Moeller 1fcb7afd3a fixed alignment of textarea
fixed event view
2015-02-13 23:09:34 +01:00
Marcus Moeller fe14c64e5e just make sure that input box and input box label are the same color 2015-02-13 18:09:43 +01:00
Marcus Moeller 107ca92458 use Genericons and fontawesome instead of images 2015-02-13 18:00:57 +01:00
buttle 9a8ccbaef2 Call HomeStubNav instead of duplicating code
adminpanelnav.php adds a homeStub but does not use the code created for the job.
2015-02-13 16:38:22 +01:00
buttle d0347bb98f Removing home stub if empty
Added an Event HomeStubNavItems
menu->subMenu() returns false if empty
2015-02-13 16:26:41 +01:00
Marcus Moeller 3fcb79bc1e moved profile/group patch from core to profile_list 2015-02-12 23:07:49 +01:00
Marcus Moeller 41da1d6403 updated neo-quitter favicon to match the theme style 2015-02-12 22:55:01 +01:00
Marcus Moeller 41baba9ed3 lock icon style fixed to match quitter style 2015-02-12 22:26:34 +01:00
Mikael Nordfeldth 2f86cd8602 utf8mb4 conversion on database with index adjusts 2015-02-12 18:18:55 +01:00
Marcus Moeller a1061c7145 fixed neo-quitter web view 2015-02-11 09:58:28 +01:00
buttle 2a0a0287d4 Added EVENT to homestubnav
Changed menu->submenu(). if (! $menu->getItems()) then do nothing
2015-02-10 19:20:01 +01:00
9106 arquivos alterados com 1080215 adições e 360654 exclusões
-1
Ver Arquivo
@@ -1,5 +1,4 @@
avatar/*
background/*
files/*
file/*
local/*
+9 -31
Ver Arquivo
@@ -100,6 +100,10 @@ ssl: Whether to use SSL and https:// URLs for some or all pages.
(don't use it for any pages), or 'sometimes' (use it for
sensitive pages that include passwords like login and registration,
but not for regular pages). Default to 'never'.
sslproxy: Whether to force GNUsocial to think it is HTTPS when the
server gives no such information. I.e. when you're using a reverse
proxy that adds the encryption layer but the webserver that runs PHP
isn't configured with a key and certificate.
sslserver: use an alternate server name for SSL URLs, like
'secure.example.org'. You should be careful to set cookie
parameters correctly so that both the SSL server and the
@@ -563,6 +567,11 @@ sslserver: if specified, this server will be used when creating HTTPS
sslpath: if this and the sslserver are specified, this path will be used
when creating HTTPS URLs. Otherwise, the attachments|path value
will be used.
show_thumbs: show thumbnails in notice lists for uploaded images, and photos
and videos linked remotely that provide oEmbed info. Defaults to true.
show_html: show (filtered) text/html attachments (and oEmbed HTML etc.).
Doesn't affect AJAX calls. Defaults to false.
filename_base: for new files, choose one: 'upload', 'hash'. Defaults to hash.
group
-----
@@ -601,23 +610,6 @@ handle: boolean. Whether we should register our own PHP session-handling
debug: whether to output debugging info for session storage. Can help
with weird session bugs, sometimes. Default false.
background
----------
Users can upload backgrounds for their pages; this section defines
their use.
server: the server to use for background. Using a separate (even
virtual) server for this can speed up load times. Default is
null; same as site server.
dir: directory to write backgrounds too. Default is '/background/'
subdir of install dir.
path: path to backgrounds. Default is sub-path of install path; note
that you may need to change this if you change site-path too.
sslserver: SSL server to use when page is HTTPS-encrypted. If
unspecified, site ssl server and so on will be used.
sslpath: If sslserver if defined, path to use when page is HTTPS-encrypted.
ping
----
@@ -627,20 +619,6 @@ notify third-party servers of updates.
notify: an array of URLs for ping endpoints. Default is the empty
array (no notification).
design
------
Default design (colors and background) for the site. Actual appearance
depends on the theme. Null values mean to use the theme defaults.
backgroundcolor: Hex color of the site background.
contentcolor: Hex color of the content area background.
sidebarcolor: Hex color of the sidebar background.
textcolor: Hex color of all non-link text.
linkcolor: Hex color of all links.
backgroundimage: Image to use for the background.
disposition: Flags for whether or not to tile the background image.
notice
------
+36 -2
Ver Arquivo
@@ -2,6 +2,13 @@ InitializePlugin: a chance to initialize a plugin in a complete environment
CleanupPlugin: a chance to cleanup a plugin at the end of a program
StartActionExecute: Right before the "prepare" call of the current Action
- $action: the current Action object
- &$args: array of arguments, referenced so you can modify the array
EndActionExecute: Right after the "handle" call of the current Action
- $action: the current Action object
StartPrimaryNav: Showing the primary nav menu
- $action: the current action
@@ -608,12 +615,12 @@ EndCheckPassword: After checking a username/password pair
- $authenticatedUser: User object if credentials match a user, else null.
StartChangePassword: Before changing a password
- $user: user
- Profile $target: The profile of the User that is changing password
- $oldpassword: the user's old password
- $newpassword: the desired new password
EndChangePassword: After changing a password
- $user: user
- Profile $target: The profile of the User that just changed its password
StartHashPassword: Generate a hashed version of the password (like a salted crypt)
- &$hashed: Hashed version of the password, later put in the database
@@ -1444,6 +1451,9 @@ StartResizeImageFile: Hook to resize an image and output it to a file. No matchi
- $outpath: string with output filepath
- $box: array with size ('width', 'height') and boundary box('x', 'y', 'w', 'h').
FillImageFileMetadata: Get more metadata about the ImageFile if it is perhaps not a real local file
- $imagefile ImageFile object which we're getting metadata for (such as animated status, width/height etc.)
StartShowAttachmentRepresentation: Attachment representation, full file (or in rare cases thumbnails/previews).
- $out: HTMLOutputter class to use for outputting HTML.
- $file: 'File' object which we're going to show representation for.
@@ -1463,3 +1473,27 @@ StartNotifyMentioned: During notice distribution, we send notifications (email,
EndNotifyMentioned: During notice distribution, we send notifications (email, im...) to the profiles who were somehow mentioned.
- $stored: Notice object that is being distributed.
- $mentioned_ids: Array of profile IDs (not just for local users) who got mentioned by the notice.
StartHomeStubNavItems: Go back Home nav items. Default includes just one item 'home'
- $out: HTMLOutputter used to output (usually an Action, but not always!)
- &$items: Referenced array of items in the nav (add if desired)
EndHomeStubNavItems:
- $out: HTMLOutputter used to output (usually an Action, but not always!)
- $items: array of menu items
StartSubMenu: Before outputting a submenu (including enclosing tags) to HTML
- $out: HTMLOutputter used to output (usually an Action, but not always!)
- $menu: The Menu object outputted as a submenu.
- $label: Localized text which represents the menu item.
EndSubMenu: After outputting a submenu (including enclosing tags) to HTML
- $out: HTMLOutputter used to output (usually an Action, but not always!)
- $menu: The Menu object outputted as a submenu.
- $label: Localized text which represents the menu item.
StartDocNav: Before outputting the docs Nav
- $nav: The DoclNav widget
EndDocNav: After outputting the docs Nav
- $nav: The DoclNav widget
+129 -131
Ver Arquivo
@@ -6,13 +6,16 @@ TABLE OF CONTENTS
* Installation
- Getting it up and running
- Fancy URLs
- Themes
- Private
* Extra features
- Sphinx
- SMS
- Queues and daemons
- Themes
- Translation
- Queues and daemons
* After installation
- Backups
- Private
- Upgrading
Prerequisites
=============
@@ -23,7 +26,7 @@ PHP modules
The following software packages are *required* for this software to
run correctly.
- PHP 5.4+ For newer versions, some functions that are used may be
- PHP 5.5+ For newer versions, some functions that are used may be
disabled by default, such as the pcntl_* family. See the
section on 'Queues and daemons' for more information.
- MariaDB 5+ GNU Social uses, by default, a MariaDB server for data
@@ -41,9 +44,10 @@ functional setup of GNU Social:
- php5-curl Fetching files by HTTP.
- php5-gd Image manipulation (scaling).
- php5-gmp For Salmon signatures (part of OStatus).
- php5-intl Internationalization support (transliteration et al).
- php5-json For WebFinger lookups and more.
- php5-mysqlnd The native driver for PHP5 MariaDB connections. If you
use MySQL, 'mysql' or 'mysqli' may work.
use MySQL, 'php5-mysql' or 'php5-mysqli' may be enough.
The above package names are for Debian based systems. In the case of
Arch Linux, PHP is compiled with support for most extensions but they
@@ -68,7 +72,7 @@ For some functionality, you will also need the following extensions:
You may also experience better performance from your site if you configure
a PHP cache/accelerator. Most distributions come with "opcache" support.
Enable it in your php.ini, it is documented there together with its settings.
Enable it in your php.ini where it is documented together with its settings.
Installation
============
@@ -105,11 +109,13 @@ especially if you've previously installed PHP/MariaDB packages.
will enable "Fancy URL" support, which you can read more about if you
scroll down a bit in this document.
3. Make your target directory writeable by the Web server.
3. Make your target directory writeable by the Web server, please note
however that 'a+w' will give _all_ users write access and securing the
webserver is not within the scope of this document.
chmod a+w /var/www/gnusocial/
On some systems, this will probably work:
On some systems, this will work as a more secure alternative:
chgrp www-data /var/www/gnusocial/
chmod g+w /var/www/gnusocial/
@@ -118,21 +124,20 @@ especially if you've previously installed PHP/MariaDB packages.
that user's default group instead. As a last resort, you can create
a new group like "gnusocial" 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
4. You should also take this moment to make your 'avatar' and 'file' sub-
directories writeable by the Web server. The _insecure_ way to do
this is:
chmod a+w /var/www/gnusocial/avatar
chmod a+w /var/www/gnusocial/background
chmod a+w /var/www/gnusocial/file
You can also make the avatar, background, and file directories
writeable by the Web server group, as noted above.
You can also make the avatar, and file directories just writable by
the Web server group, as noted above.
5. Create a database to hold your site data. Something like this
should work:
should work (you will be prompted for your database password):
mysqladmin -u "root" --password="rootpassword" create gnusocial
mysqladmin -u "root" -p create social
Note that GNU Social should have its own database; you should not share
the database with another program. You can name it whatever you want,
@@ -146,17 +151,17 @@ especially if you've previously installed PHP/MariaDB packages.
database. If you have shell access, this will probably work from the
MariaDB shell:
GRANT ALL on gnusocial.*
TO 'gnusocial'@'localhost'
GRANT ALL on social.*
TO 'social'@'localhost'
IDENTIFIED BY 'agoodpassword';
You should change the user identifier 'gnusocial' and 'agoodpassword'
You should change the user identifier 'social' and 'agoodpassword'
to your preferred new database username and password. You may want to
test logging in to MariaDB as this new user.
7. In a browser, navigate to the GNU Social install script; something like:
http://social.example.net/install.php
https://social.example.net/install.php
Enter the database connection information and your site name. The
install program will configure your site and install the initial,
@@ -170,55 +175,102 @@ Fancy URLs
----------
By default, GNU Social will use URLs that include the main PHP program's
name in them. For example, a user's home profile might be found at:
name in them. For example, a user's home profile might be found at either
of these URLS depending on the webserver's configuration and capabilities:
http://example.net/gnusocial/index.php/gnusocial/fred
https://social.example.net/index.php/fred
https://social.example.net/index.php?p=fred
On certain systems that don't support this kind of syntax, they'll
look like this:
It's possible to configure the software to use fancy URLs so it looks like
this instead:
http://example.net/gnusocial/index.php?p=gnusocial/fred
It's possible to configure the software so it looks like this instead:
http://example.net/gnusocial/fred
https://social.example.net/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
mod_rewrite enabled, -OR- know how to configure "url redirection" in
your server (like lighttpd or nginx).
1. Copy the htaccess.sample file to .htaccess in your StatusNet
directory.
2. Change the "RewriteBase" in the new .htaccess file to be the URL path
to your GNU Social installation on your server. Typically this will
be the path to your GNU Social directory relative to your Web root.
If you are installing it in the root directory, leave it as '/'.
3. Add, uncomment or change a line in your config.php file so it says:
1. See the instructions for each respective webserver software:
* For Apache, inspect the "htaccess.sample" file and save it as
".htaccess" after making any necessary modifications. Our sample
file is well commented.
* For lighttpd, inspect the lighttpd.conf.example file and apply the
appropriate changes in your virtualhost configuration for lighttpd.
* For nginx, inspect the nginx.conf.sample file and apply the appropriate
changes.
* For other webservers, we gladly accept contributions of
server configuration examples.
2. Assuming your webserver is properly configured and have its settings
applied (remember to reload/restart it), you can add this to your
GNU social's config.php file:
$config['site']['fancy'] = true;
You should now be able to navigate to a "fancy" URL on your server,
like:
http://example.net/gnusocial/main/register
https://social.example.net/main/register
If you changed your HTTP server configuration, you may need to restart
the server first.
Themes
------
If it doesn't work, double-check that AllowOverride for the GNU Social
directory is 'All' in your Apache configuration file. This is usually
/etc/httpd.conf, /etc/apache/httpd.conf, or (on Debian and Ubuntu)
/etc/apache2/sites-available/default. See the Apache documentation for
.htaccess files for more details:
As of right now, your ability change the theme is limited to CSS
stylesheets and some image files; you can't change the HTML output,
like adding or removing menu items, without the help of a plugin.
http://httpd.apache.org/docs/2.2/howto/htaccess.html
You can choose a theme using the $config['site']['theme'] element in
the config.php file. See below for details.
Also, check that mod_rewrite is installed and enabled:
You can add your own theme by making a sub-directory of the 'theme'
subdirectory with the name of your theme. Each theme can have the
following files:
http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html
display.css: a CSS2 file for "default" styling for all browsers.
logo.png: a logo image for the site.
default-avatar-profile.png: a 96x96 pixel image to use as the avatar for
users who don't upload their own.
default-avatar-stream.png: Ditto, but 48x48. For streams of notices.
default-avatar-mini.png: Ditto ditto, but 24x24. For subscriptions
listing on profile pages.
You may want to start by copying the files from the default theme to
your own directory.
Private
-------
A GNU social node can be configured as "private", which means it will not
federate with other nodes in the network. It is not a recommended method
of using GNU social and we cannot at the current state of development
guarantee that there are no leaks (what a public network sees as features,
private sites will likely see as bugs).
Private nodes are however an easy way to easily setup collaboration and
image sharing within a workgroup or a smaller community where federation
is not a desired feature. Also, it is possible to change this setting and
instantly gain full federation features.
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. Use this command as an initial guideline to create it:
mkdir /var/www/gnusocial-files
2. Make the file uploads directory writeable by the web server. An
insecure way to do this is (to do it properly, read up on UNIX file
permissions and configure your webserver accordingly):
chmod a+x /var/www/gnusocial-files
3. Tell GNU social to use this directory for file uploads. Add a line
like this to your config.php:
$config['attachments']['dir'] = '/var/www/gnusocial-files';
Extra features
==============
Sphinx
------
@@ -283,7 +335,21 @@ For this to work, there *must* be a domain or sub-domain for which all
$config['mail']['domain'] = 'yourdomain.example.net';
Translations
------------
For info on helping with translations, see the platform currently in use
for translations: https://www.transifex.com/projects/p/gnu-social/
Translations use the gettext system <http://www.gnu.org/software/gettext/>.
If you for some reason do not wish to sign up to the Transifex service,
you can review the files in the "locale/" sub-directory of GNU social.
Each plugin also has its own translation files.
To get your own site to use all the translated languages, and you are
tracking the git repo, you will need to install at least 'gettext' on
your system and then run:
$ make translations
Queues and daemons
------------------
@@ -300,12 +366,12 @@ Two mechanisms are available to achieve offline operations:
### OpportunisticQM plugin
This plugin is enabled by default. It tries its best to do background
job during regular HTTP requests, like API or HTML pages calls.
jobs during regular HTTP requests, like API or HTML pages calls.
Since queueing system is enabled by default, notices to be broadcasted
will be stored, by default, into DB (table queue_item).
Each time it can, OpportunisticQM will try to handle some of them.
Whenever it has time, OpportunisticQM will try to handle some of them.
This is a good solution whether you:
@@ -345,16 +411,13 @@ separate server is probably a good idea for high-volume sites.
.htaccess file, but make sure that your config.php file is close
to, or identical to, your Web server's version.
3. In your config.php files (both the Web server and the queues
server!), set the following variable:
3. In your config.php files (on the server where you run the queue
daemon), set the following variable:
$config['queue']['enabled'] = true;
$config['queue']['daemon'] = true;
You may also want to look at the 'daemon' section of this file for
more daemon options. Note that if you set the 'user' and/or 'group'
options, you'll need to create that user and/or group by hand.
They're not created automatically.
You may also want to look at the 'Queues and Daemons' section in
this file for more background processing options.
4. On the queues server, run the command scripts/startdaemons.sh.
@@ -384,85 +447,20 @@ It is also possible to use a STOMP server instead of our kind of hacky
home-grown DB-based queue solution. This is strongly recommended for
best response time, especially when using XMPP.
Themes
------
Older themes (version 0.9.x and below) no longer work with StatusNet
1.0.x, due to major changes in the site layout. We ship with three new
themes for this version, 'neo', 'neo-blue' and 'neo-light'.
As of right now, your ability to change the theme is site-wide; users
can't choose their own theme. Additionally, the only thing you can
change in the theme is CSS stylesheets and some image files; you can't
change the HTML output, like adding or removing menu items.
You can choose a theme using the $config['site']['theme'] element in
the config.php file. See below for details.
You can add your own theme by making a sub-directory of the 'theme'
subdirectory with the name of your theme. Each theme can have the
following files:
display.css: a CSS2 file for "default" styling for all browsers.
logo.png: a logo image for the site.
default-avatar-profile.png: a 96x96 pixel image to use as the avatar for
users who don't upload their own.
default-avatar-stream.png: Ditto, but 48x48. For streams of notices.
default-avatar-mini.png: Ditto ditto, but 24x24. For subscriptions
listing on profile pages.
You may want to start by copying the files from the default theme to
your own directory.
Translation
-----------
Translations in StatusNet use the gettext system <http://www.gnu.org/software/gettext/>.
Theoretically, you can add your own sub-directory to the locale/
subdirectory to add a new language to your system. You'll need to
compile the ".po" files into ".mo" files, however.
Contributions of translation information to StatusNet are very easy:
you can use the Web interface at translatewiki.net to add one
or a few or lots of new translations -- or even new languages. You can
also download more up-to-date .po files there, if you so desire.
For info on helping with translations, see http://status.net/wiki/Translations
After installation
==================
Backups
-------
There is no built-in system for doing backups in StatusNet. You can make
There is no built-in system for doing backups in GNU social. You can make
backups of a working StatusNet system by backing up the database and
the Web directory. To backup the database use mysqldump <http://ur1.ca/7xo>
the Web directory. To backup the database use mysqldump <https://mariadb.com/kb/en/mariadb/mysqldump/>
and to backup the Web directory, try tar.
Private
-------
Upgrading
---------
The administrator can set the "private" flag for a site so that it's
not visible to non-logged-in users. (This is the default for new installs of version 1.0!)
This might be useful for workgroups who want to share a social
networking site for project management, but host it on a public
server.
Total privacy is attempted but not guaranteed or ensured. Private sites
currently don't work well with OStatus federation.
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/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/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/statusnet-files';
Upgrading is strongly recommended to stay up to date with security fixes
and new features. For instructions on how to upgrade GNU social code,
please see the UPGRADE file.
+2 -2
Ver Arquivo
@@ -1,7 +1,7 @@
Plugins
=======
Beginning with the 0.7.x branch, StatusNet has supported a simple but
GNU social supports a simple but
powerful plugin architecture. Important events in the code are named,
like 'StartNoticeSave', and other software can register interest
in those events. When the events happen, the other software is called
@@ -37,7 +37,7 @@ can enable a plugin with the following line in config.php:
This will look for and load files named 'ExamplePlugin.php' or
'Example/ExamplePlugin.php' either in the plugins/ directory (for
plugins that ship with StatusNet) or in the local/ directory (for
plugins that ship with GNU social) or in the local/ directory (for
plugins you write yourself or that you get from somewhere else) or
local/plugins/.
+13 -9
Ver Arquivo
@@ -1,5 +1,5 @@
# GNU social 1.1.3
February 2015-02-27
# GNU social 1.2.x
2015
(c) Free Software Foundation, Inc
(c) StatusNet, Inc
@@ -100,15 +100,19 @@ for additional terms.
## New this version
This is a security fix and bug fix release since 1.1.3-beta2.
All 1.1.x sites should upgrade to this version.
This is the development branch for the 1.2.x version of GNU social.
All daring 1.1.x admins should upgrade to this version.
So far it includes the following changes:
- Backing up a user's account is more and more complete.
- Emojis 😸 (utf8mb4 support)
The last release, 1.1.3, gave us these improvements:
- XSS security fix (thanks Simon Waters, <https://www.surevine.com/>)
- Many improvements to ease adoption of the Qvitter front-end <https://github.com/hannesmannerheim/qvitter>
- Protocol adaptions for improved performance and stability
- Backing up a user's account now appears to work as it should
Upgrades from _StatusNet_ 1.1.1 will also experience these improvements:
@@ -140,13 +144,13 @@ to install the development version of GNU social.
To get it, use the git version control tool
<http://git-scm.com/> like so:
git clone git@gitorious.org:social/mainline.git
git clone git@git.gnu.io:gnu/gnu-social.git
In the current phase of development it is probably
recommended to use git as a means to stay up to date
with the source code. You can choose between these
branches:
- 1.1.x "stable", few updates, well tested code
- 1.2.x "stable", few updates, well tested code
- master "testing", more updates, usually working well
- nightly "unstable", most updates, not always working
@@ -162,8 +166,8 @@ There are several ways to get more information about GNU social.
* Following us on GNU social -- <https://quitter.se/gnusocial>
* GNU social has a bug tracker for any defects you may find, or ideas for
making things better. <https://bugz.foocorp.net/>
* Patches are welcome, preferrably to our repository on Gitorious. <https://gitorious.org/social/mainline>
making things better. <https://git.gnu.io/gnu/gnu-social/issues/>
* Patches are welcome, preferrably to our repository on git.gnu.io. <https://git.gnu.io/gnu/gnu-social>
Credits
=======
+77 -79
Ver Arquivo
@@ -1,99 +1,97 @@
Upgrading
=========
StatusNet 1.1.1 to GNU social
-----------------------------
GNU social 1.1.x to GNU social 1.2.x
------------------------------------
If you are tracking the GNU social git repository, we currently recommend
using the "master" branch (or nightly if you want to use latest features)
and follow this procedure:
0. Backup your data. The StatusNet upgrade discussions below have some
guidelines to back up the database and files (mysqldump and rsync).
1. Stop your queue daemons (you can run this command even if you do not
use the queue daemons):
$ bash scripts/stopdaemons.sh
2. Run the command to fetch the latest sourcecode:
$ git pull
If you are not using git we recommend following the instructions below
for upgrading "StatusNet 1.1.x to GNU social 1.2.x" as they are similar.
3. Run the upgrade script:
$ php scripts/upgrade.php
The upgrade script will likely take a long time because it will
upgrade the tables to another character encoding and make other
automated upgrades. Make sure it ends without errors. If you get
errors, create a new task on https://git.gnu.io/gnu/gnu-social/issues
4. Start your queue daemons again (you can run this command even if you
do not use the queue daemons):
$ bash scripts/startdaemons.sh
5. Report any issues at https://git.gnu.io/gnu/gnu-social/issues
If you are using ssh keys to log in to your server, you can make this
procedure pretty painless (assuming you have automated backups already).
Make sure you "cd" into the correct directory (in this case "htdocs")
and use the correct login@hostname combo:
$ ssh social@domain.example 'cd htdocs
&& bash scripts/stopdaemons.sh
&& git pull
&& time php scripts/upgrade.php
&& bash scripts/startdaemons.sh'
StatusNet 1.1.x to GNU social 1.2.x
-----------------------------------
We cannot support migrating from any other version of StatusNet than
1.1.1. If you are running a StatusNet version lower than this, please
follow the upgrade procedures for each respective StatusNet version.
You are now running StatusNet 1.1.1 and want to migrate to GNU social.
Beware there may be changes in minimum required version of PHP and the
modules used, so double-check the INSTALL file's requirements list.
You are now running StatusNet 1.1.1 and want to migrate to GNU social
1.2.x. Beware there may be changes in minimum required version of PHP
and the modules required, so review the INSTALL file (php5-intl is a
newly added dependency for example).
Before you begin: Make backups. Always make backups. Of your entire
* Before you begin: Make backups. Always make backups. Of your entire
directory structure and the database too. All tables. All data. Alles.
0. Stop your queue daemons 'php scripts/stopdaemon.php' should do it.
Not everyone runs queue daemons, but the above command won't hurt.
0. Make a backup of everything. To backup the database, you can use a
variant of this command (you will be prompted for the database password):
$ mysqldump -u dbuser -p dbname > social-backup.sql
1. Unpack your GNU social code to a fresh directory.
2. Synchronize your local files to the GNU social directory. These
will be the local files such as avatars, config and files:
1. Stop your queue daemons 'bash scripts/stopdaemons.sh' should do it.
Not everyone runs queue daemons, but the above command won't hurt.
avatar/*
background/*
file/*
local/*
.htaccess
config.php
2. Unpack your GNU social code to a fresh directory. You can do this
by cloning our git repository:
$ git clone https://git.gnu.io/gnu/gnu-social.git gnusocial
3. Replace your old StatusNet directory with the new GNU social
directory in your webserver root.
4. Run the upgrade script: 'php scripts/upgrade.php'
5. Start your queue daemons: 'php scripts/startdaemons.php'
6. Report any issues at https://bugz.foocorp.net/ (tag GNU social)
3. Synchronize your local files to the GNU social directory. These
will be the local files such as avatars, config and files:
avatar/*
file/*
local/*
.htaccess
config.php
Legacy StatusNet instructions
-----------------------------
This command will point you in the right direction on how to do it:
$ rsync -avP statusnet/{.htaccess,avatar,file,local,config.php} gnusocial/
These instructions are here for historical and perhaps informational
purposes.
4. Replace your old StatusNet directory with the new GNU social
directory in your webserver root.
If you've been using StatusNet 1.0 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. Try these step-by-step
instructions; read to the end first before trying them.
5. Run the upgrade script: 'php scripts/upgrade.php'
The upgrade script will likely take a long time because it will
upgrade the tables to another character encoding and make other
automated upgrades. Make sure it ends without errors. If you get
errors, create a new task on https://git.gnu.io/gnu/gnu-social/issues
0. Download StatusNet and set up all the prerequisites as if you were
doing a new install.
1. Make backups of both your database and your Web directory. UNDER NO
CIRCUMSTANCES should you try to do an upgrade without a known-good
backup. You have been warned.
2. Shut down Web access to your site, either by turning off your Web
server or by redirecting all pages to a "sorry, under maintenance"
page.
3. Shut down XMPP access to your site, typically by shutting down the
xmppdaemon.php process and all other daemons that you're running.
If you've got "monit" or "cron" automatically restarting your
daemons, make sure to turn that off, too.
4. Shut down SMS and email access to your site. The easy way to do
this is to comment out the line piping incoming email to your
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 "statusnet.bak".
7. Unpack your StatusNet 1.1.1 tarball and move it to "statusnet" or
wherever your code used to be.
8. Copy the config.php file and the contents of the avatar/, background/,
file/, and local/ subdirectories 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. Upgrade the database.
6. Start your queue daemons: 'bash scripts/startdaemons.sh'
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!
In your new StatusNet 1.1.1 directory and AFTER YOU MAKE A
BACKUP run the upgrade.php script like this:
php ./scripts/upgrade.php
11. Use mysql or psql client to log into your database and make sure that
the notice, user, profile, subscription etc. tables are non-empty.
12. Turn back on the Web server, and check that things still work.
13. Turn back on XMPP bots and email maildaemon.
NOTE: the 1.0.0 version of StatusNet changed the URLs for all admin
panels from /admin/* to /panel/*. This now allows the (popular)
username 'admin', but blocks the considerably less popular username
'panel'. If you have an existing user named 'panel', you should rename
them before upgrading.
7. Report any issues at https://git.gnu.io/gnu/gnu-social/issues
+20 -43
Ver Arquivo
@@ -35,38 +35,24 @@
* @link http://status.net
*/
if (!defined('GNUSOCIAL') && !defined('STATUSNET')) { exit(1); }
if (!defined('GNUSOCIAL')) { exit(1); }
class AllAction extends ProfileAction
class AllAction extends ShowstreamAction
{
var $notice;
protected function prepare(array $args=array())
public function getStream()
{
parent::prepare($args);
$user = common_current_user();
if (!empty($user) && $user->streamModeOnly()) {
if ($this->scoped instanceof Profile && $this->scoped->isLocal() && $this->scoped->getUser()->streamModeOnly()) {
$stream = new InboxNoticeStream($this->target, $this->scoped);
} else {
$stream = new ThreadingInboxNoticeStream($this->target, $this->scoped);
}
$this->notice = $stream->getNotices(($this->page-1)*NOTICES_PER_PAGE,
NOTICES_PER_PAGE + 1);
if ($this->page > 1 && $this->notice->N == 0) {
// TRANS: Client error when page not found (404).
$this->clientError(_('No such page.'), 404);
}
return true;
return $stream;
}
function title()
{
if (!empty($this->scoped) && $this->scoped->id == $this->target->id) {
if (!empty($this->scoped) && $this->scoped->sameAs($this->target)) {
// TRANS: Title of a user's own start page.
return _('Home timeline');
} else {
@@ -83,44 +69,44 @@ class AllAction extends ProfileAction
common_local_url(
'ApiTimelineFriends', array(
'format' => 'as',
'id' => $this->target->nickname
'id' => $this->target->getNickname()
)
),
// TRANS: %s is user nickname.
sprintf(_('Feed for friends of %s (Activity Streams JSON)'), $this->target->nickname)),
sprintf(_('Feed for friends of %s (Activity Streams JSON)'), $this->target->getNickname())),
new Feed(Feed::RSS1,
common_local_url(
'allrss', array(
'nickname' =>
$this->target->nickname)
$this->target->getNickname())
),
// TRANS: %s is user nickname.
sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->target->nickname)),
sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->target->getNickname())),
new Feed(Feed::RSS2,
common_local_url(
'ApiTimelineFriends', array(
'format' => 'rss',
'id' => $this->target->nickname
'id' => $this->target->getNickname()
)
),
// TRANS: %s is user nickname.
sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->target->nickname)),
sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->target->getNickname())),
new Feed(Feed::ATOM,
common_local_url(
'ApiTimelineFriends', array(
'format' => 'atom',
'id' => $this->target->nickname
'id' => $this->target->getNickname()
)
),
// TRANS: %s is user nickname.
sprintf(_('Feed for friends of %s (Atom)'), $this->target->nickname))
sprintf(_('Feed for friends of %s (Atom)'), $this->target->getNickname()))
);
}
function showEmptyListMessage()
{
// TRANS: Empty list message. %s is a user nickname.
$message = sprintf(_('This is the timeline for %s and friends but no one has posted anything yet.'), $this->target->nickname) . ' ';
$message = sprintf(_('This is the timeline for %s and friends but no one has posted anything yet.'), $this->target->getNickname()) . ' ';
if (common_logged_in()) {
if ($this->target->id === $this->scoped->id) {
@@ -130,12 +116,12 @@ class AllAction extends ProfileAction
} else {
// TRANS: %1$s is user nickname, %2$s is user nickname, %2$s is user nickname prefixed with "@".
// TRANS: This message contains Markdown links. Keep "](" together.
$message .= sprintf(_('You can try to [nudge %1$s](../%2$s) from their profile or [post something to them](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->target->nickname, $this->target->nickname, '@' . $this->target->nickname);
$message .= sprintf(_('You can try to [nudge %1$s](../%2$s) from their profile or [post something to them](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->target->getNickname(), $this->target->getNickname(), '@' . $this->target->getNickname());
}
} else {
// TRANS: Encouragement displayed on empty timeline user pages for anonymous users.
// TRANS: %s is a user nickname. This message contains Markdown links. Keep "](" together.
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->target->nickname);
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->target->getNickname());
}
$this->elementStart('div', 'guide');
@@ -146,19 +132,10 @@ class AllAction extends ProfileAction
function showContent()
{
if (Event::handle('StartShowAllContent', array($this))) {
$profile = null;
$current_user = common_current_user();
if (!empty($current_user)) {
$profile = $current_user->getProfile();
}
if (!empty($current_user) && $current_user->streamModeOnly()) {
if ($this->scoped instanceof Profile && $this->scoped->isLocal() && $this->scoped->getUser()->streamModeOnly()) {
$nl = new PrimaryNoticeList($this->notice, $this, array('show_n'=>NOTICES_PER_PAGE));
} else {
$nl = new ThreadedNoticeList($this->notice, $this, $profile);
$nl = new ThreadedNoticeList($this->notice, $this, $this->scoped);
}
$cnt = $nl->show();
@@ -169,7 +146,7 @@ class AllAction extends ProfileAction
$this->pagination(
$this->page > 1, $cnt > NOTICES_PER_PAGE,
$this->page, 'all', array('nickname' => $this->target->nickname)
$this->page, 'all', array('nickname' => $this->target->getNickname())
);
Event::handle('EndShowAllContent', array($this));
+9 -69
Ver Arquivo
@@ -28,11 +28,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
require_once INSTALLDIR.'/lib/rssaction.php';
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* RSS feed for user and friends timeline.
@@ -46,52 +42,12 @@ require_once INSTALLDIR.'/lib/rssaction.php';
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*/
class AllrssAction extends Rss10Action
class AllrssAction extends TargetedRss10Action
{
var $user = null;
/**
* Initialization.
*
* @param array $args Web and URL arguments
*
* @return boolean false if user doesn't exist
*
*/
function prepare($args)
protected function getNotices()
{
parent::prepare($args);
$nickname = $this->trimmed('nickname');
$this->user = User::getKV('nickname', $nickname);
if (!$this->user) {
// TRANS: Client error when user not found for an rss related action.
$this->clientError(_('No such user.'));
} else {
$this->notices = $this->getNotices($this->limit);
return true;
}
}
/**
* Get notices
*
* @param integer $limit max number of notices to return
*
* @return array notices
*/
function getNotices($limit=0)
{
$stream = new InboxNoticeStream($this->user->getProfile());
$notice = $stream->getNotices(0, $limit, null, null);
$notices = array();
while ($notice->fetch()) {
$notices[] = clone($notice);
}
return $notices;
$stream = new InboxNoticeStream($this->target);
return $stream->getNotices(0, $this->limit)->fetchAll();
}
/**
@@ -101,33 +57,17 @@ class AllrssAction extends Rss10Action
*/
function getChannel()
{
$user = $this->user;
$c = array('url' => common_local_url('allrss',
array('nickname' =>
$user->nickname)),
$this->target->getNickname())),
// TRANS: Message is used as link title. %s is a user nickname.
'title' => sprintf(_('%s and friends'), $user->nickname),
'title' => sprintf(_('%s and friends'), $this->target->getNickname()),
'link' => common_local_url('all',
array('nickname' =>
$user->nickname)),
$this->target->getNickname())),
// 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')));
$this->target->getNickname(), common_config('site', 'name')));
return $c;
}
/**
* Get image.
*
* @return string user avatar URL or null
*/
function getImage()
{
$user = $this->user;
$profile = $user->getProfile();
if (!$profile) {
return null;
}
return $profile->avatarUrl(AVATAR_PROFILE_SIZE);
}
}
+3 -6
Ver Arquivo
@@ -31,9 +31,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* We don't have a rate limit, but some clients check this method.
@@ -58,9 +56,9 @@ class ApiAccountRateLimitStatusAction extends ApiBareAuthAction
*
* @return void
*/
function handle($args)
protected function handle()
{
parent::handle($args);
parent::handle();
if (!in_array($this->format, array('xml', 'json'))) {
$this->clientError(
@@ -69,7 +67,6 @@ class ApiAccountRateLimitStatusAction extends ApiBareAuthAction
404,
$this->format
);
return;
}
$reset = new DateTime();
+22 -32
Ver Arquivo
@@ -1,5 +1,4 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
@@ -132,9 +131,6 @@ class ApiAccountRegisterAction extends ApiAction
!common_valid_http_url($homepage)) {
// TRANS: Form validation error displayed when trying to register with an invalid homepage URL.
$this->clientError(_('Homepage is not a valid URL.'), 400);
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
// TRANS: Form validation error displayed when trying to register with a too long full name.
$this->clientError(_('Full name is too long (maximum 255 characters).'), 400);
} else if (Profile::bioTooLong($bio)) {
// TRANS: Form validation error on registration page when providing too long a bio text.
// TRANS: %d is the maximum number of characters for bio; used for plural.
@@ -142,9 +138,6 @@ class ApiAccountRegisterAction extends ApiAction
'Bio is too long (maximum %d characters).',
Profile::maxBio()),
Profile::maxBio()), 400);
} else if (!is_null($location) && mb_strlen($location) > 255) {
// TRANS: Form validation error displayed when trying to register with a too long location.
$this->clientError(_('Location is too long (maximum 255 characters).'), 400);
} else if (strlen($password) < 6) {
// TRANS: Form validation error displayed when trying to register with too short a password.
$this->clientError(_('Password must be 6 or more characters.'), 400);
@@ -152,34 +145,31 @@ class ApiAccountRegisterAction extends ApiAction
// TRANS: Form validation error displayed when trying to register with non-matching passwords.
$this->clientError(_('Passwords do not match.'), 400);
} else {
// annoy spammers
sleep(7);
if ($user = User::register(array('nickname' => $nickname,
'password' => $password,
'email' => $email,
'fullname' => $fullname,
'homepage' => $homepage,
'bio' => $bio,
'location' => $location,
'code' => $this->code))) {
if (!$user instanceof User) {
// TRANS: Form validation error displayed when trying to register with an invalid username or password.
$this->clientError(_('Invalid username or password.'), 400);
}
Event::handle('EndRegistrationTry', array($this));
// annoy spammers
sleep(7);
if (Event::handle('APIStartRegistrationTry', array($this))) {
try {
$user = User::register(array('nickname' => $nickname,
'password' => $password,
'email' => $email,
'fullname' => $fullname,
'homepage' => $homepage,
'bio' => $bio,
'location' => $location,
'code' => $this->code));
Event::handle('EndRegistrationTry', array($this));
$this->initDocument('json');
$this->showJsonObjects($this->twitterUserArray($user->getProfile()));
$this->endDocument('json');
$this->initDocument('json');
$this->showJsonObjects($this->twitterUserArray($user->getProfile()));
$this->endDocument('json');
} else {
// TRANS: Form validation error displayed when trying to register with an invalid username or password.
$this->clientError(_('Invalid username or password.'), 400);
}
}
} catch (Exception $e) {
$this->clientError($e->getMessage(), 400);
}
}
}
}
/**
+10 -13
Ver Arquivo
@@ -96,21 +96,12 @@ class ApiAccountUpdateProfileAction extends ApiAuthAction
$original = clone($profile);
if (!empty($this->name)) {
$profile->fullname = $this->name;
}
if (!empty($this->url)) {
$profile->homepage = $this->url;
}
if (!empty($this->description)) {
$profile->bio = $this->description;
}
$profile->fullname = $this->name;
$profile->homepage = $this->url;
$profile->bio = $this->description;
$profile->location = $this->location;
if (!empty($this->location)) {
$profile->location = $this->location;
$loc = Location::fromName($this->location);
if (!empty($loc)) {
@@ -119,6 +110,12 @@ class ApiAccountUpdateProfileAction extends ApiAuthAction
$profile->location_id = $loc->location_id;
$profile->location_ns = $loc->location_ns;
}
} else {
// location is empty so reset the extrapolated information too
$profile->lat = '';
$profile->lon = '';
$profile->location_id = '';
$profile->location_ns = '';
}
$result = $profile->update($original);
+2 -9
Ver Arquivo
@@ -49,16 +49,9 @@ class ApiconversationAction extends ApiAuthAction
protected $conversation = null;
protected $notices = null;
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
protected function prepare(array $args=array())
{
parent::prepare($argarray);
parent::prepare($args);
$convId = $this->trimmed('id');
+5 -7
Ver Arquivo
@@ -29,9 +29,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Allows the authenticating users to follow (subscribe) the user specified in
@@ -90,7 +88,7 @@ class ApiFriendshipsCreateAction extends ApiAuthAction
$this->clientError(_('Could not follow user: profile not found.'), 403);
}
if ($this->user->isSubscribed($this->other)) {
if ($this->scoped->isSubscribed($this->other)) {
$errmsg = sprintf(
// TRANS: Client error displayed when trying to follow a user that's already being followed.
// TRANS: %s is the nickname of the user that is already being followed.
@@ -101,9 +99,9 @@ class ApiFriendshipsCreateAction extends ApiAuthAction
}
try {
Subscription::start($this->user->getProfile(), $this->other);
} catch (Exception $e) {
$this->clientError($e->getMessage(), 403);
Subscription::start($this->scoped, $this->other);
} catch (AlreadyFulfilledException $e) {
$this->clientError($e->getMessage(), 409);
}
$this->initDocument($this->format);
+14 -33
Ver Arquivo
@@ -29,9 +29,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Allows the authenticating users to unfollow (unsubscribe) the user specified in
@@ -48,7 +46,9 @@ if (!defined('STATUSNET')) {
*/
class ApiFriendshipsDestroyAction extends ApiAuthAction
{
var $other = null;
protected $needPost = true;
protected $other = null;
/**
* Take arguments for running
@@ -58,12 +58,11 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction
* @return boolean success flag
*
*/
function prepare($args)
protected function prepare(array $args=array())
{
parent::prepare($args);
$this->user = $this->auth_user;
$this->other = $this->getTargetProfile($this->arg('id'));
$this->other = $this->getTargetProfile($this->arg('id'));
return true;
}
@@ -73,58 +72,40 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction
*
* Check the format and show the user info
*
* @param array $args $_REQUEST data (unused)
*
* @return void
*/
function handle($args)
protected function handle()
{
parent::handle($args);
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError(
// TRANS: Client error. POST is a HTTP command. It should not be translated.
_('This method requires a POST.'),
400,
$this->format
);
return;
}
parent::handle();
if (!in_array($this->format, array('xml', 'json'))) {
$this->clientError(
// TRANS: Client error displayed when coming across a non-supported API method.
_('API method not found.'),
404,
$this->format
404
);
return;
}
if (empty($this->other)) {
if (!$this->other instanceof Profile) {
$this->clientError(
// TRANS: Client error displayed when trying to unfollow a user that cannot be found.
_('Could not unfollow user: User not found.'),
403,
$this->format
403
);
return;
}
// Don't allow unsubscribing from yourself!
if ($this->user->id == $this->other->id) {
if ($this->scoped->id == $this->other->id) {
$this->clientError(
// TRANS: Client error displayed when trying to unfollow self.
_("You cannot unfollow yourself."),
403,
$this->format
403
);
return;
}
// throws an exception on error
Subscription::cancel($this->user->getProfile(), $this->other);
Subscription::cancel($this->scoped, $this->other);
$this->initDocument($this->format);
$this->showProfile($this->other, $this->format);
+5 -11
Ver Arquivo
@@ -29,9 +29,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Tests for the existence of friendship between two users. Will return true if
@@ -57,7 +55,7 @@ class ApiFriendshipsExistsAction extends ApiPrivateAuthAction
*
* @return boolean success flag
*/
function prepare($args)
protected function prepare(array $args=array())
{
parent::prepare($args);
@@ -72,22 +70,18 @@ class ApiFriendshipsExistsAction extends ApiPrivateAuthAction
*
* Check the format and show the user info
*
* @param array $args $_REQUEST data (unused)
*
* @return void
*/
function handle($args)
protected function handle()
{
parent::handle($args);
parent::handle();
if (empty($this->profile_a) || empty($this->profile_b)) {
$this->clientError(
// TRANS: Client error displayed when supplying invalid parameters to an API call checking if a friendship exists.
_('Two valid IDs or nick names must be supplied.'),
400,
$this->format
400
);
return;
}
$result = Subscription::exists($this->profile_a, $this->profile_b);
+4 -8
Ver Arquivo
@@ -29,9 +29,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Outputs detailed information about the relationship between two users
@@ -56,7 +54,7 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction
*
* @return boolean success flag
*/
function prepare($args)
protected function prepare(array $args=array())
{
parent::prepare($args);
@@ -109,13 +107,11 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction
*
* Check the format and show the user info
*
* @param array $args $_REQUEST data (unused)
*
* @return void
*/
function handle($args)
protected function handle()
{
parent::handle($args);
parent::handle();
if (!in_array($this->format, array('xml', 'json'))) {
// TRANS: Client error displayed when coming across a non-supported API method.
+2 -3
Ver Arquivo
@@ -115,11 +115,10 @@ class ApiListMembershipsAction extends ApiBareAuthAction
function getLists()
{
$profile = $this->target;
$fn = array($profile, 'getOtherTags');
$fn = array($this->target, 'getOtherTags');
# 20 lists
list($this->lists, $this->next_cursor, $this->prev_cursor) =
Profile_list::getAtCursor($fn, array($this->auth_user), $this->cursor, 20);
Profile_list::getAtCursor($fn, array($this->scoped), $this->cursor, 20);
}
}
+1 -1
Ver Arquivo
@@ -185,7 +185,7 @@ class ApiListsAction extends ApiBareAuthAction
list($this->lists,
$this->next_cursor,
$this->prev_cursor) = Profile_list::getAtCursor($fn, array($this->auth_user), $cursor, $count);
$this->prev_cursor) = Profile_list::getAtCursor($fn, array($this->scoped), $cursor, $count);
}
function isReadOnly($args)
+105 -28
Ver Arquivo
@@ -30,7 +30,7 @@ if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Upload an image via the API. Returns a shortened URL for the image
* to the user.
* to the user. Apparently modelled after a former Twitpic API.
*
* @category API
* @package StatusNet
@@ -42,17 +42,20 @@ class ApiMediaUploadAction extends ApiAuthAction
{
protected $needPost = true;
/**
* 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
*/
protected function prepare(array $args=array())
{
parent::prepare($args);
// fallback to xml for older clients etc
if (empty($this->format)) {
$this->format = 'xml';
}
if (!in_array($this->format, ['json', 'xml'])) {
throw new ClientException('This API call does not support the format '._ve($this->format));
}
return true;
}
protected function handle()
{
parent::handle();
@@ -69,14 +72,31 @@ class ApiMediaUploadAction extends ApiAuthAction
$msg = _m('The server was unable to handle that much POST data (%s byte) due to its current configuration.',
'The server was unable to handle that much POST data (%s bytes) due to its current configuration.',
intval($_SERVER['CONTENT_LENGTH']));
$this->clientError(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
throw new ClientException(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
}
// we could catch "NoUploadedMediaException" as "no media uploaded", but here we _always_ want an upload
$upload = MediaFile::fromUpload('media', $this->scoped);
try {
$upload = MediaFile::fromUpload('media', $this->scoped);
} catch (NoUploadedMediaException $e) {
common_debug('No media file was uploaded to the _FILES array');
$fh = tmpfile();
if ($this->arg('media')) {
common_debug('Found media parameter which we hope contains a media file!');
fwrite($fh, $this->arg('media'));
} elseif ($this->arg('media_data')) {
common_debug('Found media_data parameter which we hope contains a base64-encoded media file!');
fwrite($fh, base64_decode($this->arg('media_data')));
} else {
common_debug('No media|media_data POST parameter was supplied');
fclose($fh);
throw $e;
}
common_debug('MediaFile importing the uploaded file with fromFilehandle');
$upload = MediaFile::fromFilehandle($fh, $this->scoped);
}
common_debug('MediaFile completed and saved us fileRecord with id=='._ve($upload->fileRecord->id));
// Thumbnails will be generated/cached on demand when accessed (such as with /attachment/:id/thumbnail)
$this->showResponse($upload);
}
@@ -88,14 +108,61 @@ class ApiMediaUploadAction extends ApiAuthAction
*
* @return void
*/
function showResponse(MediaFile $upload)
protected function showResponse(MediaFile $upload)
{
$this->initDocument();
$this->elementStart('rsp', array('stat' => 'ok'));
$this->initDocument($this->format);
switch ($this->format) {
case 'json':
return $this->showResponseJson($upload);
case 'xml':
return $this->showResponseXml($upload);
default:
throw new ClientException('This API call does not support the format '._ve($this->format));
}
$this->endDocument($this->format);
}
protected function showResponseJson(MediaFile $upload)
{
$enc = $upload->fileRecord->getEnclosure();
// note that we use media_id instead of mediaid which XML users might've gotten used to (nowadays we service media_id in both!)
$output = [
'media_id' => $upload->fileRecord->id,
'media_id_string' => (string)$upload->fileRecord->id,
'media_url' => $upload->shortUrl(),
'size' => $upload->fileRecord->size,
];
if (common_get_mime_media($enc->mimetype) === 'image') {
$output['image'] = [
'w' => $enc->width,
'h' => $enc->height,
'image_type' => $enc->mimetype,
];
}
print json_encode($output);
}
protected function showResponseXml(MediaFile $upload)
{
$this->elementStart('rsp', array('stat' => 'ok', 'xmlns:atom'=>Activity::ATOM));
$this->element('mediaid', null, $upload->fileRecord->id);
$this->element('mediaurl', null, $upload->shortUrl());
$this->element('media_url', null, $upload->shortUrl());
$this->element('size', null, $upload->fileRecord->size);
$enclosure = $upload->fileRecord->getEnclosure();
$this->element('atom:link', array('rel' => 'enclosure',
'href' => $enclosure->url,
'type' => $enclosure->mimetype));
// Twitter specific metadata expected in response since Twitter's Media upload API v1.1 (even though Twitter doesn't use XML)
$this->element('media_id', null, $upload->fileRecord->id);
$this->element('media_id_string', null, (string)$upload->fileRecord->id);
if (common_get_mime_media($enclosure->mimetype) === 'image') {
$this->element('image', ['w'=>$enclosure->width, 'h'=>$enclosure->height, 'image_type'=>$enclosure->mimetype]);
}
$this->elementEnd('rsp');
$this->endDocument();
}
/**
@@ -103,16 +170,26 @@ class ApiMediaUploadAction extends ApiAuthAction
*
* @param String $msg an error message
*/
function clientError($msg)
function clientError($msg, $code=400, $format=null)
{
$this->initDocument();
$this->elementStart('rsp', array('stat' => 'fail'));
$this->initDocument($this->format);
switch ($this->format) {
case 'json':
$error = ['errors' => array()];
$error['errors'][] = ['message'=>$msg, 'code'=>131];
print json_encode($error);
break;
case 'xml':
$this->elementStart('rsp', array('stat' => 'fail'));
// @todo add in error code
$errAttr = array('msg' => $msg);
// @todo add in error code
$errAttr = array('msg' => $msg);
$this->element('err', $errAttr, null);
$this->elementEnd('rsp');
$this->endDocument();
$this->element('err', $errAttr, null);
$this->elementEnd('rsp');
break;
}
$this->endDocument($this->format);
exit;
}
}
+1 -1
Ver Arquivo
@@ -327,7 +327,7 @@ class ApiSearchAtomAction extends ApiPrivateAuthAction
'rel' => 'alternate',
'href' => $nurl));
$this->element('title', null, common_xml_safe_str(trim($notice->content)));
$this->element('content', array('type' => 'html'), $notice->rendered);
$this->element('content', array('type' => 'html'), $notice->getRendered());
$this->element('updated', null, common_date_w3dtf($notice->created));
$this->element('link', array('type' => 'image/png',
// XXX: Twitter uses rel="image" (not valid)
+1 -1
Ver Arquivo
@@ -124,7 +124,7 @@ class ApiStatusesDestroyAction extends ApiAuthAction
if ($this->user->id == $this->notice->profile_id) {
if (Event::handle('StartDeleteOwnNotice', array($this->user, $this->notice))) {
$this->notice->delete();
$this->notice->deleteAs($this->scoped);
Event::handle('EndDeleteOwnNotice', array($this->user, $this->notice));
}
$this->showNotice();
+36 -63
Ver Arquivo
@@ -74,16 +74,21 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
$this->notice_id = (int)$this->trimmed('id');
$this->notice = Notice::getKV('id', $this->notice_id);
if (!$this->notice instanceof Notice) {
$deleted = Deleted_notice::getKV('id', $this->notice_id);
if ($deleted instanceof Deleted_notice) {
$this->notice = null;
try {
$this->notice = Notice::getByID($this->notice_id);
} catch (NoResultException $e) {
// No such notice was found, maybe it was deleted?
$deleted = null;
Event::handle('IsNoticeDeleted', array($this->notice_id, &$deleted));
if ($deleted === true) {
// TRANS: Client error displayed trying to show a deleted notice.
$this->clientError(_('Notice deleted.'), 410);
throw new ClientException(_('Notice deleted.'), 410);
}
// TRANS: Client error displayed trying to show a non-existing notice.
$this->clientError(_('No such notice.'), 404);
throw new ClientException(_('No such notice.'), 404);
}
if (!$this->notice->inScope($this->scoped)) {
// TRANS: Client exception thrown when trying a view a notice the user has no access to.
throw new ClientException(_('Access restricted.'), 403);
@@ -128,43 +133,20 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
*/
function showNotice()
{
if (!empty($this->notice)) {
switch ($this->format) {
case 'xml':
$this->showSingleXmlStatus($this->notice);
break;
case 'json':
$this->show_single_json_status($this->notice);
break;
case 'atom':
$this->showSingleAtomStatus($this->notice);
break;
default:
// TRANS: Exception thrown requesting an unsupported notice output format.
// TRANS: %s is the requested output format.
throw new Exception(sprintf(_("Unsupported format: %s."), $this->format));
}
} else {
// XXX: Twitter just sets a 404 header and doens't bother
// to return an err msg
$deleted = Deleted_notice::getKV($this->notice_id);
if (!empty($deleted)) {
$this->clientError(
// TRANS: Client error displayed requesting a deleted status.
_('Status deleted.'),
410,
$this->format
);
} else {
$this->clientError(
// TRANS: Client error displayed requesting a status with an invalid ID.
_('No status with that ID found.'),
404,
$this->format
);
}
switch ($this->format) {
case 'xml':
$this->showSingleXmlStatus($this->notice);
break;
case 'json':
$this->show_single_json_status($this->notice);
break;
case 'atom':
$this->showSingleAtomStatus($this->notice);
break;
default:
// TRANS: Exception thrown requesting an unsupported notice output format.
// TRANS: %s is the requested output format.
throw new Exception(sprintf(_("Unsupported format: %s."), $this->format));
}
}
@@ -188,11 +170,7 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
*/
function lastModified()
{
if (!empty($this->notice)) {
return strtotime($this->notice->created);
}
return null;
return strtotime($this->notice->created);
}
/**
@@ -205,20 +183,15 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
*/
function etag()
{
if (!empty($this->notice)) {
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
$this->notice->id,
strtotime($this->notice->created))
)
. '"';
}
return null;
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_language(),
$this->notice->id,
strtotime($this->notice->created))
)
. '"';
}
function deleteNotice()
@@ -236,7 +209,7 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
}
if (Event::handle('StartDeleteOwnNotice', array($this->auth_user, $this->notice))) {
$this->notice->delete();
$this->notice->deleteAs($this->scoped);
Event::handle('EndDeleteOwnNotice', array($this->auth_user, $this->notice));
}
+24 -3
Ver Arquivo
@@ -152,6 +152,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction
var $in_reply_to_status_id = null;
var $lat = null;
var $lon = null;
var $media_ids = array(); // file_id in the keys
/**
* Take arguments for running
@@ -167,6 +168,19 @@ class ApiStatusesUpdateAction extends ApiAuthAction
$this->status = $this->trimmed('status');
$this->lat = $this->trimmed('lat');
$this->lon = $this->trimmed('long');
$matches = array();
common_debug(get_called_class().': media_ids=='._ve($this->trimmed('media_ids')));
if (preg_match_all('/\d+/', $this->trimmed('media_ids'), $matches) !== false) {
foreach (array_unique($matches[0]) as $match) {
try {
$this->media_ids[$match] = File::getByID($match);
} catch (EmptyIdException $e) {
// got a zero from the client, at least Twidere does this on occasion
} catch (NoResultException $e) {
// File ID was not found. Do we abort and report to the client?
}
}
}
$this->in_reply_to_status_id
= intval($this->trimmed('in_reply_to_status_id'));
@@ -211,7 +225,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction
$this->clientError(_('No such user.'), 404);
}
/* Do not call shortenlinks until the whole notice has been build */
/* Do not call shortenLinks until the whole notice has been build */
// Check for commands
@@ -244,17 +258,24 @@ class ApiStatusesUpdateAction extends ApiAuthAction
}
}
foreach(array_keys($this->media_ids) as $media_id) {
// FIXME: Validation on this... Worst case is that if someone sends bad media_ids then
// we'll fill the notice with non-working links, so no real harm, done, but let's fix.
// The File objects are in the array, so we could get URLs from them directly.
$this->status .= ' ' . common_local_url('attachment', array('attachment' => $media_id));
}
$upload = null;
try {
$upload = MediaFile::fromUpload('media', $this->scoped);
$this->status .= ' ' . $upload->shortUrl();
/* Do not call shortenlinks until the whole notice has been build */
/* Do not call shortenLinks until the whole notice has been build */
} catch (NoUploadedMediaException $e) {
// There was no uploaded media for us today.
}
/* Do call shortenlinks here & check notice length since notice is about to be saved & sent */
$status_shortened = $this->auth_user->shortenlinks($this->status);
$status_shortened = $this->auth_user->shortenLinks($this->status);
if (Notice::contentTooLong($status_shortened)) {
if ($upload instanceof MediaFile) {
+8 -26
Ver Arquivo
@@ -51,19 +51,10 @@ class ApiTimelineTagAction extends ApiPrivateAuthAction
{
var $notices = null;
/**
* Take arguments for running
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*/
function prepare($args)
protected function prepare(array $args=array())
{
parent::prepare($args);
common_debug("apitimelinetag prepare()");
$this->tag = $this->arg('tag');
$this->notices = $this->getNotices();
@@ -79,9 +70,9 @@ class ApiTimelineTagAction extends ApiPrivateAuthAction
*
* @return void
*/
function handle($args)
protected function handle()
{
parent::handle($args);
parent::handle();
$this->showTimeline();
}
@@ -172,21 +163,12 @@ class ApiTimelineTagAction extends ApiPrivateAuthAction
*/
function getNotices()
{
$notices = array();
$notice = Notice_tag::getStream($this->tag)->getNotices(($this->page - 1) * $this->count,
$this->count + 1,
$this->since_id,
$this->max_id);
$notice = Notice_tag::getStream(
$this->tag,
($this->page - 1) * $this->count,
$this->count + 1,
$this->since_id,
$this->max_id
);
while ($notice->fetch()) {
$notices[] = clone($notice);
}
return $notices;
return $notice->fetchAll();
}
/**
+35 -170
Ver Arquivo
@@ -34,9 +34,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Returns the most recent notices (default 20) posted by the authenticating
@@ -79,6 +77,10 @@ class ApiTimelineUserAction extends ApiBareAuthAction
$this->clientError(_('No such user.'), 404);
}
if (!$this->target->isLocal()) {
$this->serverError(_('Remote user timelines are not available here yet.'), 501);
}
$this->notices = $this->getNotices();
return true;
@@ -111,11 +113,11 @@ class ApiTimelineUserAction extends ApiBareAuthAction
{
// We'll use the shared params from the Atom stub
// for other feed types.
$atom = new AtomUserNoticeFeed($this->target->getUser(), $this->auth_user);
$atom = new AtomUserNoticeFeed($this->target->getUser(), $this->scoped);
$link = common_local_url(
'showstream',
array('nickname' => $this->target->nickname)
array('nickname' => $this->target->getNickname())
);
$self = $this->getSelfUri();
@@ -123,7 +125,7 @@ class ApiTimelineUserAction extends ApiBareAuthAction
// FriendFeed's SUP protocol
// Also added RSS and Atom feeds
$suplink = common_local_url('sup', null, null, $this->target->id);
$suplink = common_local_url('sup', null, null, $this->target->getID());
header('X-SUP-ID: ' . $suplink);
@@ -131,7 +133,7 @@ class ApiTimelineUserAction extends ApiBareAuthAction
$nextUrl = !empty($this->next_id)
? common_local_url('ApiTimelineUser',
array('format' => $this->format,
'id' => $this->target->id),
'id' => $this->target->getID()),
array('max_id' => $this->next_id))
: null;
@@ -143,11 +145,11 @@ class ApiTimelineUserAction extends ApiBareAuthAction
$prevUrl = common_local_url('ApiTimelineUser',
array('format' => $this->format,
'id' => $this->target->id),
'id' => $this->target->getID()),
$prevExtra);
$firstUrl = common_local_url('ApiTimelineUser',
array('format' => $this->format,
'id' => $this->target->id));
'id' => $this->target->getID()));
switch($this->format) {
case 'xml':
@@ -202,7 +204,7 @@ class ApiTimelineUserAction extends ApiBareAuthAction
break;
case 'as':
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
$doc = new ActivityStreamJSONDocument($this->auth_user);
$doc = new ActivityStreamJSONDocument($this->scoped);
$doc->setTitle($atom->title);
$doc->addLink($link, 'alternate', 'text/html');
$doc->addItemsFromNotices($this->notices);
@@ -303,9 +305,9 @@ class ApiTimelineUserAction extends ApiBareAuthAction
return '"' . implode(
':',
array($this->arg('action'),
common_user_cache_hash($this->auth_user),
common_user_cache_hash($this->scoped),
common_language(),
$this->target->id,
$this->target->getID(),
strtotime($this->notices[0]->created),
strtotime($this->notices[$last]->created))
)
@@ -317,10 +319,10 @@ class ApiTimelineUserAction extends ApiBareAuthAction
function handlePost()
{
if (empty($this->auth_user) ||
$this->auth_user->id != $this->target->id) {
if (!$this->scoped instanceof Profile ||
!$this->target->sameAs($this->scoped)) {
// TRANS: Client error displayed trying to add a notice to another user's timeline.
$this->clientError(_('Only the user can add to their own timeline.'));
$this->clientError(_('Only the user can add to their own timeline.'), 403);
}
// Only handle posts for Atom
@@ -352,165 +354,28 @@ class ApiTimelineUserAction extends ApiBareAuthAction
$activity = new Activity($dom->documentElement);
$saved = null;
common_debug('AtomPub: Ignoring right now, but this POST was made to collection: '.$activity->id);
if (Event::handle('StartAtomPubNewActivity', array(&$activity, $this->target->getUser(), &$saved))) {
if ($activity->verb != ActivityVerb::POST) {
// TRANS: Client error displayed when not using the POST verb. Do not translate POST.
$this->clientError(_('Can only handle POST activities.'));
}
// Reset activity data so we can handle it in the same functions as with OStatus
// because we don't let clients set their own UUIDs... Not sure what AtomPub thinks
// about that though.
$activity->id = null;
$activity->actor = null; // not used anyway, we use $this->target
$activity->objects[0]->id = null;
$note = $activity->objects[0];
if (!in_array($note->type, array(ActivityObject::NOTE,
ActivityObject::BLOGENTRY,
ActivityObject::STATUS))) {
// TRANS: Client error displayed when using an unsupported activity object type.
// TRANS: %s is the unsupported activity object type.
$this->clientError(sprintf(_('Cannot handle activity object type "%s".'),
$note->type));
}
$saved = $this->postNote($activity);
Event::handle('EndAtomPubNewActivity', array($activity, $this->target->getUser(), $saved));
$stored = null;
if (Event::handle('StartAtomPubNewActivity', array($activity, $this->target, &$stored))) {
// TRANS: Client error displayed when not using the POST verb. Do not translate POST.
throw new ClientException(_('Could not handle this Atom Activity.'));
}
if (!empty($saved)) {
header('HTTP/1.1 201 Created');
header("Location: " . common_local_url('ApiStatusesShow', array('id' => $saved->id,
'format' => 'atom')));
$this->showSingleAtomStatus($saved);
if (!$stored instanceof Notice) {
throw new ServerException('Server did not create a Notice object from handled AtomPub activity.');
}
}
Event::handle('EndAtomPubNewActivity', array($activity, $this->target, $stored));
function postNote($activity)
{
$note = $activity->objects[0];
// Use summary as fallback for content
if (!empty($note->content)) {
$sourceContent = $note->content;
} else if (!empty($note->summary)) {
$sourceContent = $note->summary;
} else if (!empty($note->title)) {
$sourceContent = $note->title;
} else {
// @fixme fetch from $sourceUrl?
// TRANS: Client error displayed when posting a notice without content through the API.
// TRANS: %d is the notice ID (number).
$this->clientError(sprintf(_('No content for notice %d.'), $note->id));
}
// Get (safe!) HTML and text versions of the content
$rendered = $this->purify($sourceContent);
$content = common_strip_html($rendered);
$shortened = $this->auth_user->shortenLinks($content);
$options = array('is_local' => Notice::LOCAL_PUBLIC,
'rendered' => $rendered,
'replies' => array(),
'groups' => array(),
'tags' => array(),
'urls' => array());
// accept remote URI (not necessarily a good idea)
common_debug("Note ID is {$note->id}");
if (!empty($note->id)) {
$notice = Notice::getKV('uri', trim($note->id));
if (!empty($notice)) {
// TRANS: Client error displayed when using another format than AtomPub.
// TRANS: %s is the notice URI.
$this->clientError(sprintf(_('Notice with URI "%s" already exists.'), $note->id));
}
common_log(LOG_NOTICE, "Saving client-supplied notice URI '$note->id'");
$options['uri'] = $note->id;
}
// accept remote create time (also maybe not such a good idea)
if (!empty($activity->time)) {
common_log(LOG_NOTICE, "Saving client-supplied create time {$activity->time}");
$options['created'] = common_sql_date($activity->time);
}
// Check for optional attributes...
if ($activity->context instanceof ActivityContext) {
foreach ($activity->context->attention as $uri=>$type) {
try {
$profile = Profile::fromUri($uri);
if ($profile->isGroup()) {
$options['groups'][] = $profile->id;
} else {
$options['replies'][] = $uri;
}
} catch (UnknownUriException $e) {
common_log(LOG_WARNING, sprintf('AtomPub post with unknown attention URI %s', $uri));
}
}
// Maintain direct reply associations
// @fixme what about conversation ID?
if (!empty($activity->context->replyToID)) {
$orig = Notice::getKV('uri',
$activity->context->replyToID);
if (!empty($orig)) {
$options['reply_to'] = $orig->id;
}
}
$location = $activity->context->location;
if ($location) {
$options['lat'] = $location->lat;
$options['lon'] = $location->lon;
if ($location->location_id) {
$options['location_ns'] = $location->location_ns;
$options['location_id'] = $location->location_id;
}
}
}
// Atom categories <-> hashtags
foreach ($activity->categories as $cat) {
if ($cat->term) {
$term = common_canonical_tag($cat->term);
if ($term) {
$options['tags'][] = $term;
}
}
}
// Atom enclosures -> attachment URLs
foreach ($activity->enclosures as $href) {
// @fixme save these locally or....?
$options['urls'][] = $href;
}
$saved = Notice::saveNew($this->target->id,
$content,
'atompub', // TODO: deal with this
$options);
return $saved;
}
function purify($content)
{
require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
$config = array('safe' => 1,
'deny_attribute' => 'id,style,on*');
return htmLawed($content, $config);
header('HTTP/1.1 201 Created');
header("Location: " . common_local_url('ApiStatusesShow', array('id' => $stored->getID(),
'format' => 'atom')));
$this->showSingleAtomStatus($stored);
}
}
+4 -11
Ver Arquivo
@@ -230,18 +230,11 @@ class AtompubsubscriptionfeedAction extends AtompubAction
$this->clientError(sprintf(_('Unknown profile %s.'), $person->id));
}
if (Subscription::exists($this->_profile, $profile)) {
try {
$sub = Subscription::start($this->_profile, $profile);
} catch (AlreadyFulfilledException $e) {
// 409 Conflict
// TRANS: Client error displayed trying to subscribe to an already subscribed profile.
// TRANS: %s is the profile the user already has a subscription on.
$this->clientError(sprintf(_('Already subscribed to %s.'),
$person->id),
409);
}
if (Subscription::start($this->_profile, $profile)) {
$sub = Subscription::pkeyGet(array('subscriber' => $this->_profile->id,
'subscribed' => $profile->id));
$this->clientError($e->getMessage(), 409);
}
Event::handle('EndAtomPubNewActivity', array($activity, $sub));
+2 -2
Ver Arquivo
@@ -59,9 +59,9 @@ class Attachment_thumbnailAction extends AttachmentAction
try {
$thumbnail = $this->attachment->getThumbnail($this->thumb_w, $this->thumb_h, $this->thumb_c);
} catch (UseFileAsThumbnailException $e) {
common_redirect($e->file->getUrl());
common_redirect($e->file->getUrl(), 302);
}
common_redirect($thumbnail->getUrl());
common_redirect(File_thumbnail::url($thumbnail->filename), 302);
}
}
+45 -87
Ver Arquivo
@@ -28,13 +28,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
define('MAX_ORIGINAL', 480);
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Upload an avatar
@@ -82,11 +76,11 @@ class AvatarsettingsAction extends SettingsAction
/**
* Content area of the page
*
* Shows a form for uploading an avatar.
* Shows a form for uploading an avatar. Currently overrides FormAction's showContent
* since we haven't made classes out of AvatarCropForm and AvatarUploadForm.
*
* @return void
*/
function showContent()
{
if ($this->mode == 'crop') {
@@ -249,52 +243,19 @@ class AvatarsettingsAction extends SettingsAction
$this->elementEnd('form');
}
/**
* Handle a post
*
* We mux on the button name to figure out what the user actually wanted.
*
* @return void
*/
function handlePost()
protected function doPost()
{
// 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)
) {
// TRANS: Client error displayed when the number of bytes in a POST request exceeds a limit.
// TRANS: %s is the number of bytes of the CONTENT_LENGTH.
$msg = _m('The server was unable to handle that much POST data (%s byte) due to its current configuration.',
'The server was unable to handle that much POST data (%s bytes) due to its current configuration.',
intval($_SERVER['CONTENT_LENGTH']));
$this->showForm(sprintf($msg, $_SERVER['CONTENT_LENGTH']));
return;
}
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
// TRANS: Client error displayed when the session token does not match or is not given.
$this->showForm(_('There was a problem with your session token. '.
'Try again, please.'));
return;
}
if (Event::handle('StartAvatarSaveForm', array($this))) {
if ($this->arg('upload')) {
$this->uploadAvatar();
} else if ($this->arg('crop')) {
$this->cropAvatar();
} else if ($this->arg('delete')) {
$this->deleteAvatar();
} else {
// TRANS: Unexpected validation error on avatar upload form.
$this->showForm(_('Unexpected form submission.'));
}
if ($this->trimmed('upload')) {
return $this->uploadAvatar();
} else if ($this->trimmed('crop')) {
return $this->cropAvatar();
} else if ($this->trimmed('delete')) {
return $this->deleteAvatar();
} else {
// TRANS: Unexpected validation error on avatar upload form.
throw new ClientException(_('Unexpected form submission.'));
}
Event::handle('EndAvatarSaveForm', array($this));
}
}
@@ -309,21 +270,12 @@ class AvatarsettingsAction extends SettingsAction
*/
function uploadAvatar()
{
try {
$imagefile = ImageFile::fromUpload('avatarfile');
} catch (Exception $e) {
$this->showForm($e->getMessage());
return;
}
if ($imagefile === null) {
// TRANS: Validation error on avatar upload form when no file was uploaded.
$this->showForm(_('No file uploaded.'));
return;
}
// ImageFile throws exception if something goes wrong, which we'll
// pick up and show as an error message above the form.
$imagefile = ImageFile::fromUpload('avatarfile');
$cur = common_current_user();
$type = $imagefile->preferredType();
$filename = Avatar::filename($cur->id,
$filename = Avatar::filename($this->scoped->getID(),
image_type_to_extension($type),
null,
'tmp'.common_timestamp());
@@ -344,8 +296,7 @@ class AvatarsettingsAction extends SettingsAction
$this->mode = 'crop';
// TRANS: Avatar upload form instruction after uploading a file.
$this->showForm(_('Pick a square area of the image to be your avatar.'),
true);
return _('Pick a square area of the image to be your avatar.');
}
/**
@@ -357,36 +308,46 @@ class AvatarsettingsAction extends SettingsAction
{
$filedata = $_SESSION['FILEDATA'];
if (!$filedata) {
if (empty($filedata)) {
// TRANS: Server error displayed if an avatar upload went wrong somehow server side.
$this->serverError(_('Lost our file data.'));
throw new ServerException(_('Lost our file data.'));
}
$file_d = ($filedata['width'] > $filedata['height'])
? $filedata['height'] : $filedata['width'];
$file_d = min($filedata['width'], $filedata['height']);
$dest_x = $this->arg('avatar_crop_x') ? $this->arg('avatar_crop_x'):0;
$dest_y = $this->arg('avatar_crop_y') ? $this->arg('avatar_crop_y'):0;
$dest_w = $this->arg('avatar_crop_w') ? $this->arg('avatar_crop_w'):$file_d;
$dest_h = $this->arg('avatar_crop_h') ? $this->arg('avatar_crop_h'):$file_d;
$size = intval(min($dest_w, $dest_h, MAX_ORIGINAL));
$size = intval(min($dest_w, $dest_h, common_config('avatar', 'maxsize')));
$user = common_current_user();
$profile = $user->getProfile();
$box = array('width' => $size, 'height' => $size,
'x' => $dest_x, 'y' => $dest_y,
'w' => $dest_w, 'h' => $dest_h);
$imagefile = new ImageFile($user->id, $filedata['filepath']);
$filename = $imagefile->resize($size, $dest_x, $dest_y, $dest_w, $dest_h);
$imagefile = new ImageFile(null, $filedata['filepath']);
$filename = Avatar::filename($this->scoped->getID(), image_type_to_extension($imagefile->preferredType()),
$size, common_timestamp());
try {
$imagefile->resizeTo(Avatar::path($filename), $box);
} catch (UseFileAsThumbnailException $e) {
common_debug('Using uploaded avatar directly without resizing, copying it to: '.$filename);
if (!copy($filedata['filepath'], Avatar::path($filename))) {
common_debug('Tried to copy image file '.$filedata['filepath'].' to destination '.Avatar::path($filename));
throw new ServerException('Could not copy file to destination.');
}
}
if ($profile->setOriginal($filename)) {
if ($this->scoped->setOriginal($filename)) {
@unlink($filedata['filepath']);
unset($_SESSION['FILEDATA']);
$this->mode = 'upload';
// TRANS: Success message for having updated a user avatar.
$this->showForm(_('Avatar updated.'), true);
} else {
// TRANS: Error displayed on the avatar upload page if the avatar could not be updated for an unknown reason.
$this->showForm(_('Failed updating avatar.'));
return _('Avatar updated.');
}
// TRANS: Error displayed on the avatar upload page if the avatar could not be updated for an unknown reason.
throw new ServerException(_('Failed updating avatar.'));
}
/**
@@ -396,13 +357,10 @@ class AvatarsettingsAction extends SettingsAction
*/
function deleteAvatar()
{
$user = common_current_user();
$profile = $user->getProfile();
Avatar::deleteFromProfile($profile);
Avatar::deleteFromProfile($this->scoped);
// TRANS: Success message for deleting a user avatar.
$this->showForm(_('Avatar deleted.'), true);
return _('Avatar deleted.');
}
/**
+10 -172
Ver Arquivo
@@ -28,11 +28,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Download a backup of your own account to the browser
@@ -48,38 +44,19 @@ if (!defined('STATUSNET')) {
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class BackupaccountAction extends Action
class BackupaccountAction extends FormAction
{
/**
* Returns the title of the page
*
* @return string page title
*/
protected $form = 'BackupAccount';
function title()
{
// TRANS: Title for backup account page.
return _('Backup account');
}
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
protected function doPreparation()
{
parent::prepare($argarray);
$cur = common_current_user();
if (empty($cur)) {
// TRANS: Client exception thrown when trying to backup an account while not logged in.
throw new ClientException(_('Only logged-in users can backup their account.'), 403);
}
if (!$cur->hasRight(Right::BACKUPACCOUNT)) {
if (!$this->scoped->hasRight(Right::BACKUPACCOUNT)) {
// TRANS: Client exception thrown when trying to backup an account without having backup rights.
throw new ClientException(_('You may not backup your account.'), 403);
}
@@ -87,40 +64,11 @@ class BackupaccountAction extends Action
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return void
*/
function handle($argarray=null)
protected function doPost()
{
parent::handle($argarray);
$stream = new UserActivityStream($this->scoped->getUser(), true, UserActivityStream::OUTPUT_RAW);
if ($this->isPost()) {
$this->sendFeed();
} else {
$this->showPage();
}
return;
}
/**
* Send a feed of the user's activities to the browser
*
* Uses the UserActivityStream class; may take a long time!
*
* @return void
*/
function sendFeed()
{
$cur = common_current_user();
$stream = new UserActivityStream($cur, true, UserActivityStream::OUTPUT_RAW);
header('Content-Disposition: attachment; filename='.$cur->nickname.'.atom');
header('Content-Disposition: attachment; filename='.urlencode($this->scoped->getNickname()).'.atom');
header('Content-Type: application/atom+xml; charset=utf-8');
// @fixme atom feed logic is in getString...
@@ -128,39 +76,10 @@ class BackupaccountAction extends Action
$this->raw($stream->getString());
}
/**
* Show a little form so that the person can request a backup.
*
* @return void
*/
function showContent()
{
$form = new BackupAccountForm($this);
$form->show();
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
public function isReadOnly($args) {
return true;
}
/**
* Return last modified, if applicable.
*
* MAY override
*
* @return string last modified http header
*/
function lastModified()
{
// For comparison with If-Last-Modified
@@ -168,89 +87,8 @@ class BackupaccountAction extends Action
return null;
}
/**
* Return etag, if applicable.
*
* MAY override
*
* @return string etag http header
*/
function etag()
{
return null;
}
}
/**
* A form for backing up the account.
*
* @category Account
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class BackupAccountForm extends Form
{
/**
* Class of the form.
*
* @return string the form's class
*/
function formClass()
{
return 'form_profile_backup';
}
/**
* URL the form posts to
*
* @return string the form's action URL
*/
function action()
{
return common_local_url('backupaccount');
}
/**
* Output form data
*
* Really, just instructions for doing a backup.
*
* @return void
*/
function formData()
{
$msg =
// TRANS: Information displayed on the backup account page.
_('You can backup your account data in '.
'<a href="http://activitystrea.ms/">Activity Streams</a> '.
'format. This is an experimental feature and provides an '.
'incomplete backup; private account '.
'information like email and IM addresses is not backed up. '.
'Additionally, uploaded files and direct messages are not '.
'backed up.');
$this->out->elementStart('p');
$this->out->raw($msg);
$this->out->elementEnd('p');
}
/**
* Buttons for the form
*
* In this case, a single submit button
*
* @return void
*/
function formActions()
{
$this->out->submit('submit',
// TRANS: Submit button to backup an account on the backup account page.
_m('BUTTON', 'Backup'),
'submit',
null,
// TRANS: Title for submit button to backup an account on the backup account page.
_('Backup your account.'));
}
}
+4 -13
Ver Arquivo
@@ -43,23 +43,17 @@ class CancelsubscriptionAction extends FormAction
{
protected $needPost = true;
protected function prepare(array $args=array())
protected function doPreparation()
{
parent::prepare($args);
$profile_id = $this->int('unsubscribeto');
$this->target = Profile::getKV('id', $profile_id);
if (!$this->target instanceof Profile) {
throw new NoProfileException($profile_id);
}
return true;
}
protected function handlePost()
protected function doPost()
{
parent::handlePost();
try {
$request = Subscription_queue::pkeyGet(array('subscriber' => $this->scoped->id,
'subscribed' => $this->target->id));
@@ -70,7 +64,7 @@ class CancelsubscriptionAction extends FormAction
common_debug('Tried to cancel a non-existing pending subscription');
}
if (StatusNet::isAjax()) {
if (GNUsocial::isAjax()) {
$this->startHTML('text/xml;charset=utf-8');
$this->elementStart('head');
// TRANS: Title after unsubscribing from a group.
@@ -82,10 +76,7 @@ class CancelsubscriptionAction extends FormAction
$this->elementEnd('body');
$this->endHTML();
exit();
} else {
common_redirect(common_local_url('subscriptions',
array('nickname' => $this->scoped->nickname)),
303);
}
common_redirect(common_local_url('subscriptions', array('nickname' => $this->scoped->getNickname())), 303);
}
}
+8 -23
Ver Arquivo
@@ -49,24 +49,9 @@ class ConversationAction extends ManagedAction
var $page = null;
var $notices = null;
/**
* Initialization.
*
* @param array $args Web and URL arguments
*
* @return boolean false if id not passed in
*/
protected function prepare(array $args=array())
protected function doPreparation()
{
parent::prepare($args);
$convId = $this->int('id');
$this->conv = Conversation::getKV('id', $convId);
if (!$this->conv instanceof Conversation) {
throw new ClientException('Could not find specified conversation');
}
return true;
$this->conv = Conversation::getByID($this->int('id'));
}
/**
@@ -90,14 +75,14 @@ class ConversationAction extends ManagedAction
function showContent()
{
if (Event::handle('StartShowConversation', array($this, $this->conv, $this->scoped))) {
$notices = $this->conv->getNotices();
$notices = $this->conv->getNotices($this->scoped);
$nl = new FullThreadedNoticeList($notices, $this, $this->scoped);
$cnt = $nl->show();
}
Event::handle('EndShowConversation', array($this, $this->conv, $this->scoped));
}
function isReadOnly()
function isReadOnly($args)
{
return true;
}
@@ -108,7 +93,7 @@ class ConversationAction extends ManagedAction
return array(new Feed(Feed::JSON,
common_local_url('apiconversation',
array(
'id' => $this->conv->id,
'id' => $this->conv->getID(),
'format' => 'as')),
// TRANS: Title for link to notice feed.
// TRANS: %s is a user nickname.
@@ -116,7 +101,7 @@ class ConversationAction extends ManagedAction
new Feed(Feed::RSS2,
common_local_url('apiconversation',
array(
'id' => $this->conv->id,
'id' => $this->conv->getID(),
'format' => 'rss')),
// TRANS: Title for link to notice feed.
// TRANS: %s is a user nickname.
@@ -124,11 +109,11 @@ class ConversationAction extends ManagedAction
new Feed(Feed::ATOM,
common_local_url('apiconversation',
array(
'id' => $this->conv->id,
'id' => $this->conv->getID(),
'format' => 'atom')),
// TRANS: Title for link to notice feed.
// TRANS: %s is a user nickname.
_('Conversation feed (Activity Streams JSON)')));
_('Conversation feed (Atom)')));
}
}
+14 -139
Ver Arquivo
@@ -28,80 +28,24 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
// @todo FIXME: documentation needed.
class DeletenoticeAction extends Action
class DeletenoticeAction extends FormAction
{
var $error = null;
var $user = null;
var $notice = null;
var $profile = null;
var $user_profile = null;
protected $notice = null;
function prepare($args)
protected function doPreparation()
{
parent::prepare($args);
$this->notice = Notice::getByID($this->trimmed('notice'));
$this->user = common_current_user();
if (!$this->user) {
// TRANS: Error message displayed when trying to perform an action that requires a logged in user.
common_user_error(_('Not logged in.'));
exit;
}
$notice_id = $this->trimmed('notice');
$this->notice = Notice::getKV($notice_id);
if (!$this->notice) {
// TRANS: Error message displayed trying to delete a non-existing notice.
common_user_error(_('No such notice.'));
exit;
}
$this->profile = $this->notice->getProfile();
$this->user_profile = $this->user->getProfile();
return true;
}
function handle($args)
{
parent::handle($args);
if ($this->notice->profile_id != $this->user_profile->id &&
!$this->user->hasRight(Right::DELETEOTHERSNOTICE)) {
if (!$this->scoped->sameAs($this->notice->getProfile()) &&
!$this->scoped->hasRight(Right::DELETEOTHERSNOTICE)) {
// TRANS: Error message displayed trying to delete a notice that was not made by the current user.
common_user_error(_('Cannot delete this notice.'));
exit;
$this->clientError(_('Cannot delete this notice.'));
}
// XXX: Ajax!
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$this->deleteNotice();
} else if ($_SERVER['REQUEST_METHOD'] == 'GET') {
$this->showForm();
}
}
/**
* Show the page notice
*
* Shows instructions for the page
*
* @return void
*/
function showPageNotice()
{
$instr = $this->getInstructions();
$output = common_markup_to_html($instr);
$this->elementStart('div', 'instructions');
$this->raw($output);
$this->elementEnd('div');
$this->formOpts['notice'] = $this->notice;
}
function getInstructions()
@@ -117,84 +61,15 @@ class DeletenoticeAction extends Action
return _('Delete notice');
}
/**
* Wrapper for showing a page
*
* Stores an error and shows the page
*
* @param string $error Error, if any
*
* @return void
*/
function showForm($error = null)
protected function doPost()
{
$this->error = $error;
$this->showPage();
}
/**
* Insert delete notice form into the content
*
* @return void
*/
function showContent()
{
$this->elementStart('form', array('id' => 'form_notice_delete',
'class' => 'form_settings',
'method' => 'post',
'action' => common_local_url('deletenotice')));
$this->elementStart('fieldset');
// TRANS: Fieldset legend for the delete notice form.
$this->element('legend', null, _('Delete notice'));
$this->hidden('token', common_session_token());
$this->hidden('notice', $this->trimmed('notice'));
// TRANS: Message for the delete notice form.
$this->element('p', null, _('Are you sure you want to 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');
}
function deleteNotice()
{
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
// TRANS: Client error displayed when the session token does not match or is not given.
$this->showForm(_('There was a problem with your session token. ' .
'Try again, please.'));
return;
}
if ($this->arg('yes')) {
if (Event::handle('StartDeleteOwnNotice', array($this->user, $this->notice))) {
$this->notice->delete();
Event::handle('EndDeleteOwnNotice', array($this->user, $this->notice));
if (Event::handle('StartDeleteOwnNotice', array($this->scoped->getUser(), $this->notice))) {
$this->notice->deleteAs($this->scoped);
Event::handle('EndDeleteOwnNotice', array($this->scoped->getUser(), $this->notice));
}
}
$url = common_get_returnto();
if ($url) {
common_set_returnto(null);
} else {
$url = common_local_url('public');
}
common_redirect($url, 303);
common_redirect(common_get_returnto(), 303);
}
}
+15 -20
Ver Arquivo
@@ -27,9 +27,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Delete a user
@@ -44,33 +42,30 @@ class DeleteuserAction extends ProfileFormAction
{
var $user = null;
/**
* Take arguments for running
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*/
function prepare($args)
function prepare(array $args=array())
{
if (!parent::prepare($args)) {
return false;
}
$cur = common_current_user();
assert($this->scoped instanceof Profile);
assert(!empty($cur)); // checked by parent
if (!$cur->hasRight(Right::DELETEUSER)) {
if (!$this->scoped->hasRight(Right::DELETEUSER)) {
// TRANS: Client error displayed when trying to delete a user without having the right to delete users.
$this->clientError(_('You cannot delete users.'));
throw new AuthorizationException(_('You cannot delete users.'));
}
$this->user = User::getKV('id', $this->profile->id);
if (empty($this->user)) {
try {
$this->user = $this->profile->getUser();
} catch (NoSuchUserException $e) {
// TRANS: Client error displayed when trying to delete a non-local user.
$this->clientError(_('You can only delete local users.'));
throw new ClientException(_('You can only delete local users.'));
}
// Only administrators can delete other privileged users (such as others who have the right to silence).
if ($this->profile->isPrivileged() && !$this->scoped->hasRole(Profile_role::ADMINISTRATOR)) {
// TRANS: Client error displayed when trying to delete a user that has been granted moderation privileges
throw new AuthorizationException(_('You cannot delete other privileged users.'));
}
return true;
+15 -63
Ver Arquivo
@@ -28,9 +28,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Documentation class.
@@ -42,16 +40,14 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*/
class DocAction extends Action
class DocAction extends ManagedAction
{
var $output = null;
var $filename = null;
var $title = null;
function prepare($args)
protected function doPreparation()
{
parent::prepare($args);
$this->title = $this->trimmed('title');
if (!preg_match('/^[a-zA-Z0-9_-]*$/', $this->title)) {
$this->title = 'help';
@@ -59,52 +55,11 @@ class DocAction extends Action
$this->output = null;
$this->loadDoc();
return true;
}
/**
* Handle a request
*
* @param array $args array of arguments
*
* @return nothing
*/
function handle($args)
public function title()
{
parent::handle($args);
$this->showPage();
}
/**
* Page title
*
* Gives the page title of the document. Override default for hAtom entry.
*
* @return void
*/
function showPageTitle()
{
$this->element('h1', array('class' => 'entry-title'), $this->title());
}
/**
* Block for content.
*
* Overrides default from Action to wrap everything in an hAtom entry.
*
* @return void.
*/
function showContentBlock()
{
$this->elementStart('div', array('id' => 'content', 'class' => 'h-entry'));
$this->showPageTitle();
$this->showPageNoticeBlock();
$this->elementStart('div', array('id' => 'content_inner',
'class' => 'e-content'));
// show the actual content (forms, lists, whatever)
$this->showContent();
$this->elementEnd('div');
$this->elementEnd('div');
return ucfirst($this->title);
}
/**
@@ -119,16 +74,9 @@ class DocAction extends Action
$this->raw($this->output);
}
/**
* Page title.
*
* Uses the title of the document.
*
* @return page title
*/
function title()
function showNoticeForm()
{
return ucfirst($this->title);
// no notice form
}
/**
@@ -174,11 +122,15 @@ class DocNav extends Menu
{
function show()
{
$stub = new HomeStubNav($this->action);
$this->submenu(_m('MENU','Home'), $stub);
if (Event::handle('StartDocNav', array($this))) {
$stub = new HomeStubNav($this->action);
$this->submenu(_m('MENU','Home'), $stub);
$docs = new DocListNav($this->action);
$this->submenu(_m('MENU','Docs'), $docs);
$docs = new DocListNav($this->action);
$this->submenu(_m('MENU','Docs'), $docs);
Event::handle('EndDocNav', array($this));
}
}
}
+70 -125
Ver Arquivo
@@ -28,11 +28,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Settings for email
@@ -91,7 +87,7 @@ class EmailsettingsAction extends SettingsAction
*/
function showContent()
{
$user = common_current_user();
$user = $this->scoped->getUser();
$this->elementStart('form', array('method' => 'post',
'id' => 'form_settings_email',
@@ -112,8 +108,8 @@ class EmailsettingsAction extends SettingsAction
// TRANS: Button label to remove a confirmed e-mail address.
$this->submit('remove', _m('BUTTON','Remove'));
} else {
$confirm = $this->getConfirmation();
if ($confirm) {
try {
$confirm = $this->getConfirmation();
$this->element('p', array('id' => 'form_unconfirmed'), $confirm->address);
$this->element('p', array('class' => 'form_note'),
// TRANS: Form note in e-mail settings form.
@@ -123,12 +119,12 @@ class EmailsettingsAction extends SettingsAction
$this->hidden('email', $confirm->address);
// TRANS: Button label to cancel an e-mail address confirmation procedure.
$this->submit('cancel', _m('BUTTON','Cancel'));
} else {
} catch (NoResultException $e) {
$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,
$this->trimmed('email') ?: null,
// TRANS: Instructions for e-mail address input form. Do not translate
// TRANS: "example.org". It is one of the domain names reserved for
// TRANS: use in examples by http://www.rfc-editor.org/rfc/rfc2606.txt.
@@ -231,12 +227,6 @@ class EmailsettingsAction extends SettingsAction
_('Allow friends to nudge me and send me an email.'),
$user->emailnotifynudge);
$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');
Event::handle('EndEmailFormData', array($this, $this->scoped));
}
$this->elementEnd('ul');
@@ -254,56 +244,36 @@ class EmailsettingsAction extends SettingsAction
*/
function getConfirmation()
{
$user = common_current_user();
$confirm = new Confirm_address();
$confirm->user_id = $user->id;
$confirm->user_id = $this->scoped->getID();
$confirm->address_type = 'email';
if ($confirm->find(true)) {
return $confirm;
} else {
return null;
}
throw new NoResultException($confirm);
}
/**
* Handle posts
*
* Since there are a lot of different options on the page, we
* figure out what we're supposed to do based on which button was
* pushed
*
* @return void
*/
function handlePost()
protected function doPost()
{
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
// TRANS: Client error displayed when the session token does not match or is not given.
$this->show_form(_('There was a problem with your session token. '.
'Try again, please.'));
return;
if ($this->arg('save')) {
return $this->savePreferences();
} else if ($this->arg('add')) {
return $this->addAddress();
} else if ($this->arg('cancel')) {
return $this->cancelConfirmation();
} else if ($this->arg('remove')) {
return $this->removeAddress();
} else if ($this->arg('removeincoming')) {
return $this->removeIncoming();
} else if ($this->arg('newincoming')) {
return $this->newIncoming();
}
if ($this->arg('save')) {
$this->savePreferences();
} else if ($this->arg('add')) {
$this->addAddress();
} else if ($this->arg('cancel')) {
$this->cancelConfirmation();
} else if ($this->arg('remove')) {
$this->removeAddress();
} else if ($this->arg('removeincoming')) {
$this->removeIncoming();
} 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.'));
}
// TRANS: Message given submitting a form with an unknown action in e-mail settings.
throw new ClientException(_('Unexpected form submission.'));
}
/**
@@ -313,44 +283,38 @@ class EmailsettingsAction extends SettingsAction
*/
function savePreferences()
{
$user = common_current_user();
if (Event::handle('StartEmailSaveForm', array($this, $this->scoped))) {
$emailnotifysub = $this->boolean('emailnotifysub');
$emailnotifymsg = $this->boolean('emailnotifymsg');
$emailnotifynudge = $this->boolean('emailnotifynudge');
$emailnotifyattn = $this->boolean('emailnotifyattn');
$emailmicroid = $this->boolean('emailmicroid');
$emailpost = $this->boolean('emailpost');
assert(!is_null($user)); // should already be checked
$emailnotifysub = $this->booleanintstring('emailnotifysub');
$emailnotifymsg = $this->booleanintstring('emailnotifymsg');
$emailnotifynudge = $this->booleanintstring('emailnotifynudge');
$emailnotifyattn = $this->booleanintstring('emailnotifyattn');
$emailpost = $this->booleanintstring('emailpost');
$user = $this->scoped->getUser();
$user->query('BEGIN');
$original = clone($user);
$user->emailnotifysub = $emailnotifysub;
$user->emailnotifymsg = $emailnotifymsg;
$user->emailnotifynudge = $emailnotifynudge;
$user->emailnotifyattn = $emailnotifyattn;
$user->emailmicroid = $emailmicroid;
$user->emailpost = $emailpost;
$result = $user->update($original);
if ($result === false) {
common_log_db_error($user, 'UPDATE', __FILE__);
$user->query('ROLLBACK');
// TRANS: Server error thrown on database error updating e-mail preferences.
$this->serverError(_('Could not update user.'));
throw new ServerException(_('Could not update user.'));
}
$user->query('COMMIT');
Event::handle('EndEmailSaveForm', array($this, $this->scoped));
// TRANS: Confirmation message for successful e-mail preferences save.
$this->showForm(_('Email preferences saved.'), true);
}
// TRANS: Confirmation message for successful e-mail preferences save.
return _('Email preferences saved.');
}
/**
@@ -360,38 +324,32 @@ class EmailsettingsAction extends SettingsAction
*/
function addAddress()
{
$user = common_current_user();
$user = $this->scoped->getUser();
$email = $this->trimmed('email');
// Some validation
if (!$email) {
if (empty($email)) {
// TRANS: Message given saving e-mail address without having provided one.
$this->showForm(_('No email address.'));
return;
throw new ClientException(_('No email address.'));
}
$email = common_canonical_email($email);
if (!$email) {
if (empty($email)) {
// TRANS: Message given saving e-mail address that cannot be normalised.
$this->showForm(_('Cannot normalize that email address.'));
return;
throw new ClientException(_('Cannot normalize that email address.'));
}
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;
throw new ClientException(_('Not a valid email address.'));
} 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;
throw new ClientException(_('That is already your email address.'));
} 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;
throw new ClientException(_('That email address already belongs to another user.'));
}
if (Event::handle('StartAddEmailAddress', array($user, $email))) {
@@ -400,7 +358,7 @@ class EmailsettingsAction extends SettingsAction
$confirm->address = $email;
$confirm->address_type = 'email';
$confirm->user_id = $user->id;
$confirm->user_id = $user->getID();
$confirm->code = common_confirmation_code(64);
$result = $confirm->insert();
@@ -408,20 +366,19 @@ class EmailsettingsAction extends SettingsAction
if ($result === false) {
common_log_db_error($confirm, 'INSERT', __FILE__);
// TRANS: Server error thrown on database error adding e-mail confirmation code.
$this->serverError(_('Could not insert confirmation code.'));
throw new ServerException(_('Could not insert confirmation code.'));
}
mail_confirm_address($user, $confirm->code, $user->nickname, $email);
common_debug('Sending confirmation address for user '.$user->getID().' to email '.$email);
mail_confirm_address($user, $confirm->code, $user->getNickname(), $email);
Event::handle('EndAddEmailAddress', array($user, $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. '.
return _('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.');
$this->showForm($msg, true);
}
/**
@@ -431,31 +388,29 @@ class EmailsettingsAction extends SettingsAction
*/
function cancelConfirmation()
{
$email = $this->arg('email');
$email = $this->trimmed('email');
$confirm = $this->getConfirmation();
if (!$confirm) {
try {
$confirm = $this->getConfirmation();
if ($confirm->address !== $email) {
// TRANS: Message given canceling e-mail address confirmation for the wrong e-mail address.
throw new ClientException(_('That is the wrong email address.'));
}
} catch (NoResultException $e) {
// TRANS: Message given canceling e-mail address confirmation that is not pending.
$this->showForm(_('No pending confirmation to cancel.'));
return;
}
if ($confirm->address != $email) {
// TRANS: Message given canceling e-mail address confirmation for the wrong e-mail address.
$this->showForm(_('That is the wrong email address.'));
return;
throw new AlreadyFulfilledException(_('No pending confirmation to cancel.'));
}
$result = $confirm->delete();
if (!$result) {
if ($result === false) {
common_log_db_error($confirm, 'DELETE', __FILE__);
// TRANS: Server error thrown on database error canceling e-mail address confirmation.
$this->serverError(_('Could not delete email confirmation.'));
throw new ServerException(_('Could not delete email confirmation.'));
}
// TRANS: Message given after successfully canceling e-mail address confirmation.
$this->showForm(_('Email confirmation cancelled.'), true);
return _('Email confirmation cancelled.');
}
/**
@@ -467,26 +422,22 @@ class EmailsettingsAction extends SettingsAction
{
$user = common_current_user();
$email = $this->arg('email');
$email = $this->trimmed('email');
// Maybe an old tab open...?
if ($user->email != $email) {
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;
throw new ClientException(_('That is not your email address.'));
}
$original = clone($user);
$user->email = null;
// Throws exception on failure. Also performs it within a transaction.
$user->updateWithKeys($original);
// TRANS: Message given after successfully removing a registered e-mail address.
$this->showForm(_('The email address was removed.'), true);
return _('The email address was removed.');
}
/**
@@ -498,22 +449,19 @@ class EmailsettingsAction extends SettingsAction
{
$user = common_current_user();
if (!$user->incomingemail) {
if (empty($user->incomingemail)) {
// TRANS: Form validation error displayed when trying to remove an incoming e-mail address while no address has been set.
$this->showForm(_('No incoming email address.'));
return;
throw new AlreadyFulfilledException(_('No incoming email address.'));
}
$orig = clone($user);
$user->incomingemail = null;
$user->emailpost = 0;
// Throws exception on failure. Also performs it within a transaction.
$user->updateWithKeys($orig);
// TRANS: Message given after successfully removing an incoming e-mail address.
$this->showForm(_('Incoming email address removed.'), true);
return _('Incoming email address removed.');
}
/**
@@ -524,17 +472,14 @@ class EmailsettingsAction extends SettingsAction
function newIncoming()
{
$user = common_current_user();
$orig = clone($user);
$user->incomingemail = mail_new_incoming_address();
$user->emailpost = 1;
// Throws exception on failure. Also performs it within a transaction.
$user->updateWithKeys($orig);
// TRANS: Message given after successfully adding an incoming e-mail address.
$this->showForm(_('New incoming email address added.'), true);
return _('New incoming email address added.');
}
/**
@@ -553,10 +498,10 @@ class EmailsettingsAction extends SettingsAction
$other = User::getKV('email', $email);
if (!$other) {
if (!$other instanceof User) {
return false;
} else {
return $other->id != $user->id;
}
return $other->id != $user->id;
}
}
+5 -9
Ver Arquivo
@@ -17,24 +17,22 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
if (!defined('GNUSOCIAL')) { exit(1); }
define('LISTENER', 1);
define('LISTENEE', -1);
define('BOTH', 0);
// @todo XXX: Documentation missing.
class FoafAction extends Action
class FoafAction extends ManagedAction
{
function isReadOnly($args)
{
return true;
}
function prepare($args)
protected function doPreparation()
{
parent::prepare($args);
$nickname_arg = $this->arg('nickname');
if (empty($nickname_arg)) {
@@ -69,10 +67,8 @@ class FoafAction extends Action
return true;
}
function handle($args)
public function showPage()
{
parent::handle($args);
header('Content-Type: application/rdf+xml');
$this->startXML();
@@ -94,7 +90,7 @@ 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->getUri()));
if ($this->user->email) {
if (common_config('foaf', 'mbox_sha1sum') && $this->user->email) {
$this->element('mbox_sha1sum', null, sha1('mailto:' . $this->user->email));
}
if ($this->profile->fullname) {
+6 -42
Ver Arquivo
@@ -28,12 +28,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
require_once INSTALLDIR.'/lib/noticelist.php';
require_once INSTALLDIR.'/lib/feedlist.php';
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Permalink for a group
@@ -47,53 +42,22 @@ require_once INSTALLDIR.'/lib/feedlist.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class GroupbyidAction extends Action
class GroupbyidAction extends ManagedAction
{
/** group we're viewing. */
var $group = null;
protected $group = null;
/**
* Is this page read-only?
*
* @return boolean true
*/
function isReadOnly($args)
{
return true;
}
function prepare($args)
protected function doPreparation()
{
parent::prepare($args);
$id = $this->arg('id');
if (!$id) {
// TRANS: Client error displayed referring to a group's permalink without providing a group ID.
$this->clientError(_('No ID.'));
}
common_debug("Got ID $id");
$this->group = User_group::getKV('id', $id);
if (!$this->group) {
// TRANS: Client error displayed referring to a group's permalink for a non-existing group ID.
$this->clientError(_('No such group.'), 404);
}
return true;
$this->group = User_group::getByID($this->arg('id'));
}
/**
* Handle the request
*
* Shows a profile for the group, some controls, and a list of
* group notices.
*
* @return void
*/
function handle($args)
public function showPage()
{
common_redirect($this->group->homeUrl(), 303);
}
+13 -12
Ver Arquivo
@@ -28,13 +28,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
define('MAX_ORIGINAL', 480);
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Upload an avatar
@@ -390,13 +384,20 @@ class GrouplogoAction extends GroupAction
$dest_y = $this->arg('avatar_crop_y') ? $this->arg('avatar_crop_y'):0;
$dest_w = $this->arg('avatar_crop_w') ? $this->arg('avatar_crop_w'):$filedata['width'];
$dest_h = $this->arg('avatar_crop_h') ? $this->arg('avatar_crop_h'):$filedata['height'];
$size = min($dest_w, $dest_h);
$size = ($size > MAX_ORIGINAL) ? MAX_ORIGINAL:$size;
$size = min($dest_w, $dest_h, common_config('avatar', 'maxsize'));
$box = array('width' => $size, 'height' => $size,
'x' => $dest_x, 'y' => $dest_y,
'w' => $dest_w, 'h' => $dest_h);
$imagefile = new ImageFile($this->group->id, $filedata['filepath']);
$filename = $imagefile->resize($size, $dest_x, $dest_y, $dest_w, $dest_h);
$profile = $this->group->getProfile();
if ($this->group->setOriginal($filename)) {
$imagefile = new ImageFile(null, $filedata['filepath']);
$filename = Avatar::filename($profile->getID(), image_type_to_extension($imagefile->preferredType()),
$size, common_timestamp());
$imagefile->resizeTo(Avatar::path($filename), $box);
if ($profile->setOriginal($filename)) {
@unlink($filedata['filepath']);
unset($_SESSION['FILEDATA']);
$this->mode = 'upload';
+14 -48
Ver Arquivo
@@ -28,11 +28,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
require_once INSTALLDIR.'/lib/rssaction.php';
if (!defined('GNUSOCIAL')) { exit(1); }
define('MEMBERS_PER_SECTION', 27);
@@ -45,10 +41,10 @@ define('MEMBERS_PER_SECTION', 27);
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class groupRssAction extends Rss10Action
class GroupRssAction extends TargetedRss10Action
{
/** group we're viewing. */
var $group = null;
protected $group = null;
/**
* Is this page read-only?
@@ -60,18 +56,8 @@ class groupRssAction extends Rss10Action
return true;
}
/**
* Prepare the action
*
* Reads and validates arguments and instantiates the attributes.
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*/
function prepare($args)
protected function doStreamPreparation()
{
parent::prepare($args);
$nickname_arg = $this->arg('nickname');
$nickname = common_canonical_nickname($nickname_arg);
@@ -90,52 +76,32 @@ class groupRssAction extends Rss10Action
$local = Local_group::getKV('nickname', $nickname);
if (!$local) {
if (!$local instanceof Local_group) {
// TRANS: Client error displayed when requesting a group RSS feed for group that does not exist.
$this->clientError(_('No such group.'), 404);
}
$this->group = User_group::getKV('id', $local->group_id);
if (!$this->group) {
// TRANS: Client error displayed when requesting a group RSS feed for an object that is not a group.
$this->clientError(_('No such group.'), 404);
}
$this->notices = $this->getNotices($this->limit);
return true;
$this->group = $local->getGroup();
$this->target = $this->group->getProfile();
}
function getNotices($limit=0)
protected function getNotices()
{
$group = $this->group;
if (is_null($group)) {
return null;
}
$notices = array();
$notice = $group->getNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit);
while ($notice->fetch()) {
$notices[] = clone($notice);
}
return $notices;
$stream = $this->group->getNotices(0, $this->limit);
return $stream->fetchAll();
}
function getChannel()
{
$group = $this->group;
$c = array('url' => common_local_url('grouprss',
array('nickname' =>
$group->nickname)),
$this->target->getNickname())),
// 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)),
'title' => sprintf(_('%s timeline'), $this->target->getNickname()),
'link' => common_local_url('showgroup', array('nickname' => $this->target->getNickname())),
// TRANS: Message is used as link description. %1$s is a group name, %2$s is a site name.
'description' => sprintf(_('Updates from members of %1$s on %2$s!'),
$group->nickname, common_config('site', 'name')));
$this->target->getNickname(), common_config('site', 'name')));
return $c;
}
+51 -99
Ver Arquivo
@@ -27,9 +27,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Settings for Jabber/XMPP integration
@@ -118,8 +116,8 @@ class ImsettingsAction extends SettingsAction
// TRANS: Button label to remove a confirmed IM address.
$this->submit('remove', _m('BUTTON','Remove'));
} else {
$confirm = $this->getConfirmation($transport);
if ($confirm) {
try {
$confirm = $this->getConfirmation($transport);
$this->element('p', 'form_unconfirmed', $confirm->address);
// TRANS: Form note in IM settings form.
$this->element('p', 'form_note',
@@ -134,7 +132,7 @@ class ImsettingsAction extends SettingsAction
$this->hidden('screenname', $confirm->address);
// TRANS: Button label to cancel an IM address confirmation procedure.
$this->submit('cancel', _m('BUTTON','Cancel'));
} else {
} catch (NoResultException $e) {
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
// TRANS: Field label for IM address.
@@ -179,8 +177,6 @@ class ImsettingsAction extends SettingsAction
// TRANS: Checkbox label in IM preferences form.
array('name'=>'replies', 'description'=>_('Send me replies '.
'from people I\'m not subscribed to.')),
// TRANS: Checkbox label in IM preferences form.
array('name'=>'microid', 'description'=>_('Publish a MicroID'))
);
foreach($preferences as $preference)
{
@@ -211,57 +207,35 @@ class ImsettingsAction extends SettingsAction
*/
function getConfirmation($transport)
{
$user = common_current_user();
$confirm = new Confirm_address();
$confirm->user_id = $user->id;
$confirm->user_id = $this->scoped->getID();
$confirm->address_type = $transport;
if ($confirm->find(true)) {
return $confirm;
} else {
return null;
}
throw new NoResultException($confirm);
}
/**
* Handle posts to this form
*
* Based on the button that was pressed, muxes out to other functions
* to do the actual task requested.
*
* All sub-functions reload the form with a message -- success or failure.
*
* @return void
*/
function handlePost()
protected function doPost()
{
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
// TRANS: Client error displayed when the session token does not match or is not given.
$this->showForm(_('There was a problem with your session token. '.
'Try again, please.'));
return;
}
if ($this->arg('save')) {
$this->savePreferences();
return $this->savePreferences();
} else if ($this->arg('add')) {
$this->addAddress();
return $this->addAddress();
} else if ($this->arg('cancel')) {
$this->cancelConfirmation();
return $this->cancelConfirmation();
} else if ($this->arg('remove')) {
$this->removeAddress();
} else {
// TRANS: Message given submitting a form with an unknown action in Instant Messaging settings.
$this->showForm(_('Unexpected form submission.'));
return $this->removeAddress();
}
// TRANS: Message given submitting a form with an unknown action in Instant Messaging settings.
throw new ClientException(_('Unexpected form submission.'));
}
/**
* Save user's Jabber preferences
* Save user's XMPP preferences
*
* These are the checkboxes at the bottom of the page. They're used to
* set different settings
@@ -270,14 +244,12 @@ class ImsettingsAction extends SettingsAction
*/
function savePreferences()
{
$user = common_current_user();
$user_im_prefs = new User_im_prefs();
$user_im_prefs->query('BEGIN');
$user_im_prefs->user_id = $user->id;
$user_im_prefs->user_id = $this->scoped->getID();
if($user_im_prefs->find() && $user_im_prefs->fetch())
{
$preferences = array('notify', 'updatefrompresence', 'replies', 'microid');
$preferences = array('notify', 'updatefrompresence', 'replies');
do
{
$original = clone($user_im_prefs);
@@ -289,15 +261,15 @@ class ImsettingsAction extends SettingsAction
$result = $new->update($original);
if ($result === false) {
common_log_db_error($user, 'UPDATE', __FILE__);
common_log_db_error($user_im_prefs, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error updating IM preferences.
$this->serverError(_('Could not update IM preferences.'));
throw new ServerException(_('Could not update IM preferences.'));
}
}while($user_im_prefs->fetch());
}
$user_im_prefs->query('COMMIT');
// TRANS: Confirmation message for successful IM preferences save.
$this->showForm(_('Preferences saved.'), true);
return _('Preferences saved.');
}
/**
@@ -310,49 +282,42 @@ class ImsettingsAction extends SettingsAction
*/
function addAddress()
{
$user = common_current_user();
$screenname = $this->trimmed('screenname');
$transport = $this->trimmed('transport');
// Some validation
if (!$screenname) {
if (empty($screenname)) {
// TRANS: Message given saving IM address without having provided one.
$this->showForm(_('No screenname.'));
return;
throw new ClientException(_('No screenname.'));
}
if (!$transport) {
if (empty($transport)) {
// TRANS: Form validation error when no transport is available setting an IM address.
$this->showForm(_('No transport.'));
return;
throw new ClientException(_('No transport.'));
}
Event::handle('NormalizeImScreenname', array($transport, &$screenname));
if (!$screenname) {
if (empty($screenname)) {
// TRANS: Message given saving IM address that cannot be normalised.
$this->showForm(_('Cannot normalize that screenname.'));
return;
throw new ClientException(_('Cannot normalize that screenname.'));
}
$valid = false;
Event::handle('ValidateImScreenname', array($transport, $screenname, &$valid));
if (!$valid) {
// TRANS: Message given saving IM address that not valid.
$this->showForm(_('Not a valid screenname.'));
return;
throw new ClientException(_('Not a valid screenname.'));
} else if ($this->screennameExists($transport, $screenname)) {
// TRANS: Message given saving IM address that is already set for another user.
$this->showForm(_('Screenname already belongs to another user.'));
return;
throw new ClientException(_('Screenname already belongs to another user.'));
}
$confirm = new Confirm_address();
$confirm->address = $screenname;
$confirm->address_type = $transport;
$confirm->user_id = $user->id;
$confirm->user_id = $this->scoped->getID();
$confirm->code = common_confirmation_code(64);
$confirm->sent = common_sql_now();
$confirm->claimed = common_sql_now();
@@ -365,13 +330,10 @@ class ImsettingsAction extends SettingsAction
$this->serverError(_('Could not insert confirmation code.'));
}
Event::handle('SendImConfirmationCode', array($transport, $screenname, $confirm->code, $user));
Event::handle('SendImConfirmationCode', array($transport, $screenname, $confirm->code, $this->scoped));
// TRANS: Message given saving valid IM address that is to be confirmed.
$msg = _('A confirmation code was sent '.
'to the IM address you added.');
$this->showForm($msg, true);
return _('A confirmation code was sent to the IM address you added.');
}
/**
@@ -386,29 +348,27 @@ class ImsettingsAction extends SettingsAction
$screenname = $this->trimmed('screenname');
$transport = $this->trimmed('transport');
$confirm = $this->getConfirmation($transport);
if (!$confirm) {
try {
$confirm = $this->getConfirmation($transport);
if ($confirm->address != $screenname) {
// TRANS: Message given canceling IM address confirmation for the wrong IM address.
throw new ClientException(_('That is the wrong IM address.'));
}
} catch (NoResultException $e) {
// TRANS: Message given canceling Instant Messaging address confirmation that is not pending.
$this->showForm(_('No pending confirmation to cancel.'));
return;
}
if ($confirm->address != $screenname) {
// TRANS: Message given canceling IM address confirmation for the wrong IM address.
$this->showForm(_('That is the wrong IM address.'));
return;
throw new AlreadyFulfilledException(_('No pending confirmation to cancel.'));
}
$result = $confirm->delete();
if (!$result) {
if ($result === false) {
common_log_db_error($confirm, 'DELETE', __FILE__);
// TRANS: Server error thrown on database error canceling IM address confirmation.
$this->serverError(_('Could not delete confirmation.'));
throw new ServerException(_('Could not delete confirmation.'));
}
// TRANS: Message given after successfully canceling IM address confirmation.
$this->showForm(_('IM confirmation cancelled.'), true);
return _('IM confirmation cancelled.');
}
/**
@@ -420,34 +380,32 @@ class ImsettingsAction extends SettingsAction
*/
function removeAddress()
{
$user = common_current_user();
$screenname = $this->trimmed('screenname');
$transport = $this->trimmed('transport');
// Maybe an old tab open...?
$user_im_prefs = new User_im_prefs();
$user_im_prefs->user_id = $user->id;
if(! ($user_im_prefs->find() && $user_im_prefs->fetch())) {
$user_im_prefs->user_id = $this->scoped->getID();
$user_im_prefs->transport = $transport;
if (!$user_im_prefs->find(true)) {
// TRANS: Message given trying to remove an IM address that is not
// TRANS: registered for the active user.
$this->showForm(_('That is not your screenname.'));
return;
throw new AlreadyFulfilledException(_('There were no preferences stored for this transport.'));
}
$result = $user_im_prefs->delete();
if (!$result) {
common_log_db_error($user, 'UPDATE', __FILE__);
if ($result === false) {
common_log_db_error($user_im_prefs, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error removing a registered IM address.
$this->serverError(_('Could not update user IM preferences.'));
throw new ServerException(_('Could not update user IM preferences.'));
}
// XXX: unsubscribe to the old address
// TRANS: Message given after successfully removing a registered Instant Messaging address.
$this->showForm(_('The IM address was removed.'), true);
return _('The IM address was removed.');
}
/**
@@ -463,15 +421,9 @@ class ImsettingsAction extends SettingsAction
function screennameExists($transport, $screenname)
{
$user = common_current_user();
$user_im_prefs = new User_im_prefs();
$user_im_prefs->transport = $transport;
$user_im_prefs->screenname = $screenname;
if($user_im_prefs->find() && $user_im_prefs->fetch()){
return true;
}else{
return false;
}
return $user_im_prefs->find(true) ? true : false;
}
}
+1 -1
Ver Arquivo
@@ -118,7 +118,7 @@ class InviteAction extends Action
$this->already[] = $other;
} else {
try {
Subscription::start($profile, $other);
Subscription::ensureStart($profile, $other);
$this->subbed[] = $other;
} catch (Exception $e) {
// subscription failed, but keep working
+2 -38
Ver Arquivo
@@ -36,24 +36,6 @@ class LoginAction extends FormAction
{
protected $needLogin = false;
/**
* Prepare page to run
*
*
* @param $args
* @return string title
*/
protected function prepare(array $args=array())
{
// @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'));
}
return parent::prepare($args);
}
/**
* Handle input, produce output
*
@@ -79,10 +61,8 @@ class LoginAction extends FormAction
*
* @return void
*/
protected function handlePost()
protected function doPost()
{
parent::handlePost();
// XXX: login throttle
$nickname = $this->trimmed('nickname');
@@ -122,22 +102,6 @@ class LoginAction extends FormAction
common_redirect($url, 303);
}
/**
* Store an error and show the page
*
* This used to show the whole page; now, it's just a wrapper
* that stores the error in an attribute.
*
* @param string $error error, if any.
*
* @return void
*/
public function showForm($msg=null, $success=false)
{
common_ensure_session();
return parent::showForm($msg, $success);
}
function showScripts()
{
parent::showScripts();
@@ -208,7 +172,7 @@ class LoginAction extends FormAction
*
* @return void
*/
function getInstructions()
protected function getInstructions()
{
if (common_logged_in() && !common_is_real_login() &&
common_get_returnto()) {
+1 -1
Ver Arquivo
@@ -63,7 +63,7 @@ class LogoutAction extends ManagedAction
}
Event::handle('EndLogout', array($this));
common_redirect(common_local_url('startpage'));
common_redirect(common_local_url('top'));
}
// Accessed through the action on events
+1 -8
Ver Arquivo
@@ -2,7 +2,7 @@
if (!defined('GNUSOCIAL')) { exit(1); }
class NetworkpublicAction extends PublicAction
class NetworkpublicAction extends SitestreamAction
{
protected function streamPrepare()
{
@@ -28,13 +28,6 @@ class NetworkpublicAction extends PublicAction
}
}
function extraHead()
{
// the PublicAction has some XRDS stuff that might be unique to the non-network public feed
// FIXME: Solve this with a call that doesn't rely on parent:: and is unique for each class.
ManagedAction::extraHead();
}
function showSections()
{
// Show invite button, as long as site isn't closed, and
+13 -27
Ver Arquivo
@@ -28,9 +28,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Add a new application
@@ -43,7 +41,7 @@ if (!defined('STATUSNET')) {
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class NewApplicationAction extends FormAction
class NewApplicationAction extends SettingsAction
{
function title()
{
@@ -51,13 +49,12 @@ class NewApplicationAction extends FormAction
return _('New application');
}
protected function handlePost()
protected function doPost()
{
parent::handlePost();
if ($this->arg('cancel')) {
common_redirect(common_local_url('oauthappssettings'), 303);
} elseif ($this->arg('save')) {
//trySave will never return, just throw exception or redirect
$this->trySave();
}
@@ -65,30 +62,18 @@ class NewApplicationAction extends FormAction
$this->clientError(_('Unexpected form submission.'));
}
function showForm($msg=null)
protected function getForm()
{
$this->msg = $msg;
$this->showPage();
return new ApplicationEditForm($this);
}
function showContent()
protected function getInstructions()
{
$form = new ApplicationEditForm($this);
$form->show();
// TRANS: Form instructions for registering a new application.
return _('Use this form to register a new application.');
}
function showPageNotice()
{
if ($this->msg) {
$this->element('p', 'error', $this->msg);
} else {
$this->element('p', 'instructions',
// TRANS: Form instructions for registering a new application.
_('Use this form to register a new application.'));
}
}
private function trySave()
protected function trySave()
{
$name = $this->trimmed('name');
$description = $this->trimmed('description');
@@ -153,7 +138,7 @@ class NewApplicationAction extends FormAction
$app->query('BEGIN');
$app->name = $name;
$app->owner = $this->scoped->id;
$app->owner = $this->scoped->getID();
$app->description = $description;
$app->source_url = $source_url;
$app->organization = $organization;
@@ -181,6 +166,7 @@ class NewApplicationAction extends FormAction
if (!$result) {
common_log_db_error($consumer, 'INSERT', __FILE__);
$app->query('ROLLBACK');
// TRANS: Server error displayed when an application could not be registered in the database through the "New application" form.
$this->serverError(_('Could not create application.'));
}
@@ -191,9 +177,9 @@ class NewApplicationAction extends FormAction
if (!$this->app_id) {
common_log_db_error($app, 'INSERT', __FILE__);
$app->query('ROLLBACK');
// TRANS: Server error displayed when an application could not be registered in the database through the "New application" form.
$this->serverError(_('Could not create application.'));
$app->query('ROLLBACK');
}
try {
+8 -25
Ver Arquivo
@@ -29,9 +29,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Add a new group
@@ -48,6 +46,8 @@ class NewgroupAction extends FormAction
{
protected $group;
protected $form = 'GroupEdit';
function getGroup() {
return $this->group;
}
@@ -58,39 +58,23 @@ class NewgroupAction extends FormAction
return _('New group');
}
/**
* Prepare to run
*/
protected function prepare(array $args=array())
protected function doPreparation()
{
parent::prepare($args);
// $this->scoped is the current user profile
if (!$this->scoped->hasRight(Right::CREATEGROUP)) {
// TRANS: Client exception thrown when a user tries to create a group while banned.
$this->clientError(_('You are not allowed to create groups on this site.'), 403);
}
return true;
}
public function showContent()
protected function getInstructions()
{
$form = new GroupEditForm($this);
$form->show();
// TRANS: Form instructions for group create form.
return _('Use this form to create a new group.');
}
public function showInstructions()
protected function doPost()
{
$this->element('p', 'instructions',
// TRANS: Form instructions for group create form.
_('Use this form to create a new group.'));
}
protected function handlePost()
{
parent::handlePost();
if (Event::handle('StartGroupSaveForm', array($this))) {
$nickname = Nickname::normalize($this->trimmed('newnickname'), true);
@@ -133,7 +117,6 @@ class NewgroupAction extends FormAction
'Too many aliases! Maximum %d allowed.',
common_config('group', 'maxaliases')),
common_config('group', 'maxaliases')));
return;
}
if ($private) {
+71 -55
Ver Arquivo
@@ -30,9 +30,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Action for posting new notices
@@ -62,6 +60,9 @@ class NewnoticeAction extends FormAction
// TRANS: Page title after sending a notice.
return _('Notice posted');
}
if ($this->int('inreplyto')) {
return _m('TITLE', 'New reply');
}
// TRANS: Page title for sending a new notice.
return _m('TITLE','New notice');
}
@@ -80,7 +81,7 @@ class NewnoticeAction extends FormAction
}
/**
* This handlePost saves a new notice, based on arguments
* This doPost saves a new notice, based on arguments
*
* If successful, will show the notice, or return an Ajax-y result.
* If not, it will show an error message -- possibly Ajax-y.
@@ -90,19 +91,32 @@ class NewnoticeAction extends FormAction
*
* @return void
*/
protected function handlePost()
protected function doPost()
{
parent::handlePost();
assert($this->scoped); // XXX: maybe an error instead...
assert($this->scoped instanceof Profile); // XXX: maybe an error instead...
$user = $this->scoped->getUser();
$content = $this->trimmed('status_textarea');
$options = array();
$content = $this->formOpts['content'];
$options = array('source' => 'web');
Event::handle('StartSaveNewNoticeWeb', array($this, $user, &$content, &$options));
if (!$content) {
// TRANS: Client error displayed trying to send a notice without content.
$this->clientError(_('No content!'));
$upload = null;
try {
// throws exception on failure
$upload = MediaFile::fromUpload('attach', $this->scoped);
if (Event::handle('StartSaveNewNoticeAppendAttachment', array($this, $upload, &$content, &$options))) {
$content .= ($content==='' ? '' : ' ') . $upload->shortUrl();
}
Event::handle('EndSaveNewNoticeAppendAttachment', array($this, $upload, &$content, &$options));
// We could check content length here if the URL was added, but I'll just let it slide for now...
$act->enclosures[] = $upload->getEnclosure();
} catch (NoUploadedMediaException $e) {
// simply no attached media to the new notice
if (empty($content)) {
// TRANS: Client error displayed trying to send a notice without content.
$this->clientError(_('No content!'));
}
}
$inter = new CommandInterpreter();
@@ -110,7 +124,7 @@ class NewnoticeAction extends FormAction
$cmd = $inter->handle_command($user, $content);
if ($cmd) {
if (StatusNet::isAjax()) {
if (GNUsocial::isAjax()) {
$cmd->execute(new AjaxWebChannel($this));
} else {
$cmd->execute(new WebChannel($this));
@@ -118,44 +132,36 @@ class NewnoticeAction extends FormAction
return;
}
$content_shortened = $user->shortenLinks($content);
if (Notice::contentTooLong($content_shortened)) {
if ($this->int('inreplyto')) {
// Throws exception if the inreplyto Notice is given but not found.
$parent = Notice::getByID($this->int('inreplyto'));
} else {
$parent = null;
}
$act = new Activity();
$act->verb = ActivityVerb::POST;
$act->time = time();
$act->actor = $this->scoped->asActivityObject();
// Reject notice if it is too long (without the HTML)
// This is done after MediaFile::fromUpload etc. just to act the same as the ApiStatusesUpdateAction
if (Notice::contentTooLong($content)) {
// TRANS: Client error displayed when the parameter "status" is missing.
// TRANS: %d is the maximum number of character for a notice.
$this->clientError(sprintf(_m('That\'s too long. Maximum notice size is %d character.',
'That\'s too long. Maximum notice size is %d characters.',
Notice::maxContent()),
Notice::maxContent()));
throw new ClientException(sprintf(_m('That\'s too long. Maximum notice size is %d character.',
'That\'s too long. Maximum notice size is %d characters.',
Notice::maxContent()),
Notice::maxContent()));
}
$replyto = intval($this->trimmed('inreplyto'));
if ($replyto) {
$options['reply_to'] = $replyto;
$act->context = new ActivityContext();
if ($parent instanceof Notice) {
$act->context->replyToID = $parent->getUri();
$act->context->replyToUrl = $parent->getUrl(true); // maybe we don't have to send true here to force a URL?
}
$upload = null;
try {
// throws exception on failure
$upload = MediaFile::fromUpload('attach', $this->scoped);
if (Event::handle('StartSaveNewNoticeAppendAttachment', array($this, $upload, &$content_shortened, &$options))) {
$content_shortened .= ' ' . $upload->shortUrl();
}
Event::handle('EndSaveNewNoticeAppendAttachment', array($this, $upload, &$content_shortened, &$options));
if (Notice::contentTooLong($content_shortened)) {
$upload->delete();
// TRANS: Client error displayed exceeding the maximum notice length.
// TRANS: %d is the maximum length for a notice.
$this->clientError(sprintf(_m('Maximum notice size is %d character, including attachment URL.',
'Maximum notice size is %d characters, including attachment URL.',
Notice::maxContent()),
Notice::maxContent()));
}
} catch (NoUploadedMediaException $e) {
// simply no attached media to the new notice
}
if ($this->scoped->shareLocation()) {
// use browser data if checked; otherwise profile data
if ($this->arg('notice_data-geo')) {
@@ -172,19 +178,29 @@ class NewnoticeAction extends FormAction
$this->scoped);
}
$options = array_merge($options, $locOptions);
$act->context->location = Location::fromOptions($locOptions);
}
$author_id = $this->scoped->id;
$text = $content_shortened;
$content = $this->scoped->shortenLinks($content);
// Does the heavy-lifting for getting "To:" information
// FIXME: Make sure NoticeTitle plugin gets a change to add the title to our activityobject!
if (Event::handle('StartNoticeSaveWeb', array($this, $this->scoped, &$content, &$options))) {
ToSelector::fillOptions($this, $options);
// FIXME: We should be able to get the attentions from common_render_content!
// and maybe even directly save whether they're local or not!
$act->context->attention = common_get_attentions($content, $this->scoped, $parent);
if (Event::handle('StartNoticeSaveWeb', array($this, &$author_id, &$text, &$options))) {
// $options gets filled with possible scoping settings
ToSelector::fillActivity($this, $act, $options);
$this->stored = Notice::saveNew($this->scoped->id, $content_shortened, 'web', $options);
$actobj = new ActivityObject();
$actobj->type = ActivityObject::NOTE;
$actobj->content = common_render_content($content, $this->scoped, $parent);
// Finally add the activity object to our activity
$act->objects[] = $actobj;
$this->stored = Notice::saveActivity($act, $this->scoped, $options);
if ($upload instanceof MediaFile) {
$upload->attachToNotice($this->stored);
@@ -193,9 +209,9 @@ class NewnoticeAction extends FormAction
Event::handle('EndNoticeSaveWeb', array($this, $this->stored));
}
Event::handle('EndSaveNewNoticeWeb', array($this, $user, &$content_shortened, &$options));
Event::handle('EndSaveNewNoticeWeb', array($this, $user, &$content, &$options));
if (!StatusNet::isAjax()) {
if (!GNUsocial::isAjax()) {
$url = common_local_url('shownotice', array('notice' => $this->stored->id));
common_redirect($url, 303);
}
+1 -8
Ver Arquivo
@@ -203,14 +203,7 @@ class SearchNoticeListItem extends NoticeListItem {
{
// FIXME: URL, image, video, audio
$this->out->elementStart('p', array('class' => 'e-content'));
if ($this->notice->rendered) {
$this->out->raw($this->highlight($this->notice->rendered, $this->terms));
} else {
// XXX: may be some uncooked notices in the DB,
// we cook them right now. This should probably disappear in future
// versions (>> 0.4.x)
$this->out->raw($this->highlight(common_render_content($this->notice->content, $this->notice), $this->terms));
}
$this->out->raw($this->highlight($this->notice->getRendered(), $this->terms));
$this->out->elementEnd('p');
}
+3 -20
Ver Arquivo
@@ -28,11 +28,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
require_once INSTALLDIR.'/lib/rssaction.php';
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* RSS feed for notice search action class.
@@ -48,19 +44,7 @@ require_once INSTALLDIR.'/lib/rssaction.php';
*/
class NoticesearchrssAction extends Rss10Action
{
function init()
{
return true;
}
function prepare($args)
{
parent::prepare($args);
$this->notices = $this->getNotices();
return true;
}
function getNotices($limit=0)
protected function getNotices()
{
$q = $this->trimmed('q');
$notices = array();
@@ -70,8 +54,7 @@ class NoticesearchrssAction extends Rss10Action
$search_engine = $notice->getSearchEngine('notice');
$search_engine->set_sort_mode('chron');
if (!$limit) $limit = 20;
$search_engine->limit(0, $limit, true);
$search_engine->limit(0, $this->limit, true);
if (false === $search_engine->query($q)) {
$cnt = 0;
} else {
+7 -50
Ver Arquivo
@@ -27,11 +27,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
require_once INSTALLDIR . '/lib/applicationlist.php';
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Show a user's registered OAuth applications
@@ -47,19 +43,11 @@ require_once INSTALLDIR . '/lib/applicationlist.php';
class OauthappssettingsAction extends SettingsAction
{
var $page = 0;
protected $page = null;
function prepare($args)
protected function doPreparation()
{
parent::prepare($args);
$this->page = ($this->arg('page')) ? ($this->arg('page') + 0) : 1;
if (!common_logged_in()) {
// TRANS: Message displayed to an anonymous user trying to view OAuth application list.
$this->clientError(_('You must be logged in to list your applications.'));
}
return true;
$this->page = $this->int('page') ?: 1;
}
/**
@@ -86,21 +74,13 @@ class OauthappssettingsAction extends SettingsAction
return _('Applications you have registered');
}
/**
* Content area of the page
*
* @return void
*/
function showContent()
{
$user = common_current_user();
$offset = ($this->page - 1) * APPS_PER_PAGE;
$limit = APPS_PER_PAGE + 1;
$application = new Oauth_application();
$application->owner = $user->id;
$application->owner = $this->scoped->getID();
$application->whereAdd("name != 'anonymous'");
$application->limit($offset, $limit);
$application->orderBy('created DESC');
@@ -109,7 +89,7 @@ class OauthappssettingsAction extends SettingsAction
$cnt = 0;
if ($application) {
$al = new ApplicationList($application, $user, $this);
$al = new ApplicationList($application, $this->scoped, $this);
$cnt = $al->show();
if (0 == $cnt) {
$this->showEmptyListMessage();
@@ -135,34 +115,11 @@ class OauthappssettingsAction extends SettingsAction
function showEmptyListMessage()
{
// TRANS: Empty list message on page with OAuth applications.
// TRANS: Empty list message on page with OAuth applications. Markup allowed
$message = sprintf(_('You have not registered any applications yet.'));
$this->elementStart('div', 'guide');
$this->raw(common_markup_to_html($message));
$this->elementEnd('div');
}
/**
* Handle posts to this form
*
* Based on the button that was pressed, muxes out to other functions
* to do the actual task requested.
*
* All sub-functions reload the form with a message -- success or failure.
*
* @return void
*/
function handlePost()
{
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
$this->showForm(_('There was a problem with your session token. '.
'Try again, please.'));
return;
}
}
}
+14 -32
Ver Arquivo
@@ -27,11 +27,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
require_once INSTALLDIR . '/lib/applicationlist.php';
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Show connected OAuth applications
@@ -46,15 +42,14 @@ require_once INSTALLDIR . '/lib/applicationlist.php';
*/
class OauthconnectionssettingsAction extends SettingsAction
{
var $page = null;
var $oauth_token = null;
var $page = null;
function prepare($args)
protected $oauth_token = null;
protected function doPreparation()
{
parent::prepare($args);
$this->oauth_token = $this->arg('oauth_token');
$this->page = ($this->arg('page')) ? ($this->arg('page') + 0) : 1;
return true;
$this->page = $this->int('page') ?: 1;
}
/**
@@ -87,18 +82,15 @@ class OauthconnectionssettingsAction extends SettingsAction
function showContent()
{
$user = common_current_user();
$profile = $user->getProfile();
$offset = ($this->page - 1) * APPS_PER_PAGE;
$limit = APPS_PER_PAGE + 1;
$connection = $user->getConnectedApps($offset, $limit);
$connection = $this->scoped->getConnectedApps($offset, $limit);
$cnt = 0;
if (!empty($connection)) {
$cal = new ConnectedAppsList($connection, $user, $this);
$cal = new ConnectedAppsList($connection, $this->scoped, $this);
$cnt = $cal->show();
}
@@ -111,7 +103,7 @@ class OauthconnectionssettingsAction extends SettingsAction
$cnt > APPS_PER_PAGE,
$this->page,
'connectionssettings',
array('nickname' => $user->nickname)
array('nickname' => $this->scoped->getNickname())
);
}
@@ -125,24 +117,14 @@ class OauthconnectionssettingsAction extends SettingsAction
*
* @return void
*/
function handlePost()
protected function doPost()
{
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
// TRANS: Client error displayed when the session token does not match or is not given.
$this->showForm(_('There was a problem with your session token. '.
'Try again, please.'));
return;
}
if ($this->arg('revoke')) {
$this->revokeAccess($this->oauth_token);
} else {
// TRANS: Client error when submitting a form with unexpected information.
$this->clientError(_('Unexpected form submission.'), 401);
return $this->revokeAccess($this->oauth_token);
}
// TRANS: Client error when submitting a form with unexpected information.
throw new ClientException(_('Unexpected form submission.'), 401);
}
/**
+10 -35
Ver Arquivo
@@ -28,11 +28,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Old-school settings
@@ -77,35 +73,23 @@ class OldschoolsettingsAction extends SettingsAction
* @return boolean true
*/
function prepare($argarray)
protected function doPreparation()
{
if (!common_config('oldschool', 'enabled')) {
throw new ClientException("Old-school settings not enabled.");
}
parent::prepare($argarray);
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return void
*/
function handlePost()
function doPost()
{
$user = common_current_user();
$osp = Old_school_prefs::getKV('user_id', $user->id);
$osp = Old_school_prefs::getKV('user_id', $this->scoped->getID());
$orig = null;
if (!empty($osp)) {
$orig = clone($osp);
} else {
$osp = new Old_school_prefs();
$osp->user_id = $user->id;
$osp->user_id = $this->scoped->getID();
$osp->created = common_sql_now();
}
@@ -113,34 +97,25 @@ class OldschoolsettingsAction extends SettingsAction
$osp->stream_nicknames = $this->boolean('stream_nicknames');
$osp->modified = common_sql_now();
if (!empty($orig)) {
if ($orig instanceof Old_school_prefs) {
$osp->update($orig);
} else {
$osp->insert();
}
// TRANS: Confirmation shown when user profile settings are saved.
$this->showForm(_('Settings saved.'), true);
return;
}
function showContent()
{
$user = common_current_user();
$form = new OldSchoolForm($this, $user);
$form->show();
return _('Settings saved.');
}
}
class OldSchoolForm extends Form
class OldSchoolSettingsForm extends Form
{
var $user;
function __construct($out, $user)
function __construct(Action $out)
{
parent::__construct($out);
$this->user = $user;
$this->user = $out->getScoped()->getUser();
}
/**
+13 -67
Ver Arquivo
@@ -28,11 +28,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
if (!defined('STATUSNET')) { exit(1); }
/**
* Change password
@@ -77,18 +73,8 @@ class PasswordsettingsAction extends SettingsAction
$this->autofocus('oldpassword');
}
/**
* Content area of the page
*
* Shows a form for changing the password
*
* @return void
*/
function showContent()
{
$user = common_current_user();
$this->elementStart('form', array('method' => 'POST',
'id' => 'form_password',
'class' => 'form_settings',
@@ -102,7 +88,7 @@ class PasswordsettingsAction extends SettingsAction
$this->elementStart('ul', 'form_data');
// Users who logged in with OpenID won't have a pwd
if ($user->password) {
if ($this->scoped->hasPassword()) {
$this->elementStart('li');
// TRANS: Field label on page where to change password.
$this->password('oldpassword', _('Old password'));
@@ -129,29 +115,8 @@ class PasswordsettingsAction extends SettingsAction
$this->elementEnd('form');
}
/**
* Handle a post
*
* Validate input and save changes. Reload the form with a success
* or error message.
*
* @return void
*/
function handlePost()
protected function doPost()
{
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
// TRANS: Client error displayed when the session token does not match or is not given.
$this->showForm(_('There was a problem with your session token. '.
'Try again, please.'));
return;
}
$user = common_current_user();
assert(!is_null($user)); // should already be checked
// FIXME: scrub input
$newpassword = $this->arg('newpassword');
@@ -161,49 +126,30 @@ class PasswordsettingsAction extends SettingsAction
if (strlen($newpassword) < 6) {
// TRANS: Form validation error on page where to change password.
$this->showForm(_('Password must be 6 or more characters.'));
return;
throw new ClientException(_('Password must be 6 or more characters.'));
} else if (0 != strcmp($newpassword, $confirm)) {
// TRANS: Form validation error on password change when password confirmation does not match.
$this->showForm(_('Passwords do not match.'));
return;
throw new ClientException(_('Passwords do not match.'));
}
if ($user->password) {
$oldpassword = null;
if ($this->scoped->hasPassword()) {
$oldpassword = $this->arg('oldpassword');
if (!common_check_user($user->nickname, $oldpassword)) {
if (!common_check_user($this->scoped->getNickname(), $oldpassword)) {
// TRANS: Form validation error on page where to change password.
$this->showForm(_('Incorrect old password.'));
return;
throw new ClientException(_('Incorrect old password.'));
}
}else{
$oldpassword = null;
}
$success = false;
if(Event::handle('StartChangePassword', array($user, $oldpassword, $newpassword))){
if (Event::handle('StartChangePassword', array($this->scoped, $oldpassword, $newpassword))) {
//no handler changed the password, so change the password internally
$original = clone($user);
$user->setPassword($newpassword);
$user->password = common_munge_password($newpassword, $user->id);
$val = $user->validate();
if ($val !== true) {
// TRANS: Form validation error on page where to change password.
$this->showForm(_('Error saving user; invalid.'));
return;
}
if (!$user->update($original)) {
// TRANS: Server error displayed on page where to change password when password change
// TRANS: could not be made because of a server error.
$this->serverError(_('Cannot save new password.'));
}
Event::handle('EndChangePassword', array($user));
Event::handle('EndChangePassword', array($this->scoped));
}
// TRANS: Form validation notice on page where to change password.
$this->showForm(_('Password saved.'), true);
return _('Password saved.');
}
}
-2
Ver Arquivo
@@ -417,8 +417,6 @@ class PathsAdminPanelForm extends AdminForm
// TRANS: Drop down option in Paths admin panel (option for "When to use SSL").
$ssl = array('never' => _('Never'),
// TRANS: Drop down option in Paths admin panel (option for "When to use SSL").
'sometimes' => _('Sometimes'),
// TRANS: Drop down option in Paths admin panel (option for "When to use SSL").
'always' => _('Always'));
+1 -1
Ver Arquivo
@@ -68,7 +68,7 @@ class PeopletagautocompleteAction extends Action
}
$profile = $this->user->getProfile();
$tags = $profile->getLists(common_current_user());
$tags = $profile->getLists($this->scoped);
$this->tags = array();
while ($tags->fetch()) {
+2 -2
Ver Arquivo
@@ -116,7 +116,7 @@ class PeopletagsbyuserAction extends Action
$user = common_current_user();
if ($this->arg('public')) {
$this->tags = $this->tagger->getLists(false, $offset, $limit);
$this->tags = $this->tagger->getLists(null, $offset, $limit);
} else if ($this->arg('private')) {
if (empty($user)) {
// TRANS: Error message displayed when trying to perform an action that requires a logged in user.
@@ -130,7 +130,7 @@ class PeopletagsbyuserAction extends Action
$this->clientError(_('You cannot view others\' private lists'), 403);
}
} else {
$this->tags = $this->tagger->getLists(common_current_user(), $offset, $limit);
$this->tags = $this->tagger->getLists($this->scoped, $offset, $limit);
}
return true;
}
+1 -1
Ver Arquivo
@@ -126,7 +126,7 @@ class PeopletagsforuserAction extends Action
$offset = ($this->page-1) * PEOPLETAGS_PER_PAGE;
$limit = PEOPLETAGS_PER_PAGE + 1;
$ptags = $this->tagged->getOtherTags(common_current_user(), $offset, $limit);
$ptags = $this->tagged->getOtherTags($this->scoped, $offset, $limit);
$pl = new PeopletagList($ptags, $this);
$cnt = $pl->show();
+1 -1
Ver Arquivo
@@ -62,7 +62,7 @@ class PluginsadminpanelAction extends AdminPanelAction
{
// TRANS: Instructions at top of plugin admin page.
return _('Additional plugins can be enabled and configured manually. ' .
'See the <a href="http://status.net/wiki/Plugins">online plugin ' .
'See the <a href="https://git.gnu.io/gnu/gnu-social/blob/master/plugins/README.md">online plugin ' .
'documentation</a> for more details.');
}
+85 -95
Ver Arquivo
@@ -82,8 +82,7 @@ class ProfilesettingsAction extends SettingsAction
*/
function showContent()
{
$user = common_current_user();
$profile = $user->getProfile();
$user = $this->scoped->getUser();
$this->elementStart('form', array('method' => 'post',
'id' => 'form_settings_profile',
@@ -100,21 +99,26 @@ class ProfilesettingsAction extends SettingsAction
$this->elementStart('li');
// TRANS: Field label in form for profile settings.
$this->input('nickname', _('Nickname'),
$this->arg('nickname') ?: $profile->nickname,
$this->trimmed('nickname') ?: $this->scoped->getNickname(),
// TRANS: Tooltip for field label in form for profile settings.
_('1-64 lowercase letters or numbers, no punctuation or spaces.'),
null, false, // "name" (will be set to id), then "required"
!common_config('profile', 'changenick') ? array('disabled'=>'disabled') : array());
!common_config('profile', 'changenick')
? array('disabled' => 'disabled', 'placeholder' => null)
: array('placeholder' => null));
$this->elementEnd('li');
$this->elementStart('li');
// TRANS: Field label in form for profile settings.
$this->input('fullname', _('Full name'),
($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname);
$this->trimmed('fullname') ?: $this->scoped->getFullname(),
// TRANS: Instructions for full name text field on profile settings
_('A full name is required, if empty it will be set to your nickname.'),
null, true);
$this->elementEnd('li');
$this->elementStart('li');
// TRANS: Field label in form for profile settings.
$this->input('homepage', _('Homepage'),
($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage,
$this->trimmed('homepage') ?: $this->scoped->getHomepage(),
// TRANS: Tooltip for field label in form for profile settings.
_('URL of your homepage, blog, or profile on another site.'));
$this->elementEnd('li');
@@ -135,13 +139,13 @@ class ProfilesettingsAction extends SettingsAction
// TRANS: Text area label in form for profile settings where users can provide
// TRANS: their biography.
$this->textarea('bio', _('Bio'),
($this->arg('bio')) ? $this->arg('bio') : $profile->bio,
$this->trimmed('bio') ?: $this->scoped->getDescription(),
$bioInstr);
$this->elementEnd('li');
$this->elementStart('li');
// TRANS: Field label in form for profile settings.
$this->input('location', _('Location'),
($this->arg('location')) ? $this->arg('location') : $profile->location,
$this->trimmed('location') ?: $this->scoped->location,
// TRANS: Tooltip for field label in form for profile settings.
_('Where you are, like "City, State (or Region), Country".'));
$this->elementEnd('li');
@@ -150,14 +154,14 @@ class ProfilesettingsAction extends SettingsAction
// TRANS: Checkbox label in form for profile settings.
$this->checkbox('sharelocation', _('Share my current location when posting notices'),
($this->arg('sharelocation')) ?
$this->arg('sharelocation') : $this->scoped->shareLocation());
$this->boolean('sharelocation') : $this->scoped->shareLocation());
$this->elementEnd('li');
}
Event::handle('EndProfileFormData', array($this));
$this->elementStart('li');
// TRANS: Field label in form for profile settings.
$this->input('tags', _('Tags'),
($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()),
$this->trimmed('tags') ?: implode(' ', Profile_tag::getSelfTagsArray($this->scoped)),
// TRANS: Tooltip for field label in form for profile settings.
_('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated.'));
$this->elementEnd('li');
@@ -203,13 +207,15 @@ class ProfilesettingsAction extends SettingsAction
(empty($user->subscribe_policy)) ? User::SUBSCRIBE_POLICY_OPEN : $user->subscribe_policy);
$this->elementEnd('li');
}
$this->elementStart('li');
$this->checkbox('private_stream',
// TRANS: Checkbox label in profile settings.
_('Make updates visible only to my followers'),
($this->arg('private_stream')) ?
$this->boolean('private_stream') : $user->private_stream);
$this->elementEnd('li');
if (common_config('profile', 'allowprivate') || $user->private_stream) {
$this->elementStart('li');
$this->checkbox('private_stream',
// TRANS: Checkbox label in profile settings.
_('Make updates visible only to my followers'),
($this->arg('private_stream')) ?
$this->boolean('private_stream') : $user->private_stream);
$this->elementEnd('li');
}
$this->elementEnd('ul');
// TRANS: Button to save input in profile settings.
$this->submit('save', _m('BUTTON','Save'));
@@ -226,17 +232,8 @@ class ProfilesettingsAction extends SettingsAction
*
* @return void
*/
function handlePost()
protected function doPost()
{
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
// TRANS: Form validation error.
$this->showForm(_('There was a problem with your session token. '.
'Try again, please.'));
return;
}
if (Event::handle('StartProfileSaveForm', array($this))) {
// $nickname will only be set if this changenick value is true.
@@ -244,15 +241,13 @@ class ProfilesettingsAction extends SettingsAction
try {
$nickname = Nickname::normalize($this->trimmed('nickname'), true);
} catch (NicknameTakenException $e) {
// Abort only if the nickname is occupied by another local profile
if ($e->profile->id != $this->scoped->id) {
$this->showForm($e->getMessage());
return;
// Abort only if the nickname is occupied by _another_ local user profile
if (!$this->scoped->sameAs($e->profile)) {
throw $e;
}
$nickname = Nickname::normalize($this->trimmed('nickname')); // without in-use check this time
} catch (NicknameException $e) {
$this->showForm($e->getMessage());
return;
// Since the variable wasn't set before the exception was thrown, let's run
// the normalize sequence again, but without in-use check this time.
$nickname = Nickname::normalize($this->trimmed('nickname'));
}
}
@@ -260,9 +255,8 @@ class ProfilesettingsAction extends SettingsAction
$homepage = $this->trimmed('homepage');
$bio = $this->trimmed('bio');
$location = $this->trimmed('location');
$autosubscribe = $this->boolean('autosubscribe');
$autosubscribe = $this->booleanintstring('autosubscribe');
$subscribe_policy = $this->trimmed('subscribe_policy');
$private_stream = $this->boolean('private_stream');
$language = $this->trimmed('language');
$timezone = $this->trimmed('timezone');
$tagstring = $this->trimmed('tags');
@@ -271,33 +265,27 @@ class ProfilesettingsAction extends SettingsAction
if (!is_null($homepage) && (strlen($homepage) > 0) &&
!common_valid_http_url($homepage)) {
// TRANS: Validation error in form for profile settings.
$this->showForm(_('Homepage is not a valid URL.'));
return;
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
throw new ClientException(_('Homepage is not a valid URL.'));
} else if (!is_null($fullname) && mb_strlen($fullname) > 191) {
// TRANS: Validation error in form for profile settings.
$this->showForm(_('Full name is too long (maximum 255 characters).'));
return;
throw new ClientException(_('Full name is too long (maximum 191 characters).'));
} else if (Profile::bioTooLong($bio)) {
// TRANS: Validation error in form for profile settings.
// TRANS: Plural form is used based on the maximum number of allowed
// TRANS: characters for the biography (%d).
$this->showForm(sprintf(_m('Bio is too long (maximum %d character).',
throw new ClientException(sprintf(_m('Bio is too long (maximum %d character).',
'Bio is too long (maximum %d characters).',
Profile::maxBio()),
Profile::maxBio()));
return;
} else if (!is_null($location) && mb_strlen($location) > 255) {
} else if (!is_null($location) && mb_strlen($location) > 191) {
// TRANS: Validation error in form for profile settings.
$this->showForm(_('Location is too long (maximum 255 characters).'));
return;
throw new ClientException(_('Location is too long (maximum 191 characters).'));
} else if (is_null($timezone) || !in_array($timezone, DateTimeZone::listIdentifiers())) {
// TRANS: Validation error in form for profile settings.
$this->showForm(_('Timezone not selected.'));
return;
throw new ClientException(_('Timezone not selected.'));
} else if (!is_null($language) && strlen($language) > 50) {
// TRANS: Validation error in form for profile settings.
$this->showForm(_('Language is too long (maximum 50 characters).'));
return;
throw new ClientException(_('Language is too long (maximum 50 characters).'));
}
$tags = array();
@@ -313,17 +301,25 @@ class ProfilesettingsAction extends SettingsAction
if (!common_valid_profile_tag($tag)) {
// TRANS: Validation error in form for profile settings.
// TRANS: %s is an invalid tag.
$this->showForm(sprintf(_('Invalid tag: "%s".'), $tag));
return;
throw new ClientException(sprintf(_('Invalid tag: "%s".'), $tag));
}
$tag_priv[$tag] = $private;
}
}
$user = common_current_user();
$user = $this->scoped->getUser();
$user->query('BEGIN');
// Only allow setting private_stream if site policy allows it
// (or user already _has_ a private stream, then you can unset it)
if (common_config('profile', 'allowprivate') || $user->private_stream) {
$private_stream = $this->booleanintstring('private_stream');
} else {
// if not allowed, we set to the existing value
$private_stream = $user->private_stream;
}
// $user->nickname is updated through Profile->update();
// XXX: XOR
@@ -344,61 +340,60 @@ class ProfilesettingsAction extends SettingsAction
$result = $user->update($original);
if ($result === false) {
common_log_db_error($user, 'UPDATE', __FILE__);
$user->query('ROLLBACK');
// TRANS: Server error thrown when user profile settings could not be updated to
// TRANS: automatically subscribe to any subscriber.
$this->serverError(_('Could not update user for autosubscribe or subscribe_policy.'));
throw new ServerException(_('Could not update user for autosubscribe or subscribe_policy.'));
}
// Re-initialize language environment if it changed
common_init_language();
}
$profile = $user->getProfile();
$original = clone($this->scoped);
$orig_profile = clone($profile);
if (common_config('profile', 'changenick') == true && $profile->nickname !== $nickname) {
if (common_config('profile', 'changenick') == true && $this->scoped->getNickname() !== $nickname) {
assert(Nickname::normalize($nickname)===$nickname);
common_debug("Changing user nickname from '{$profile->nickname}' to '{$nickname}'.");
$profile->nickname = $nickname;
$profile->profileurl = common_profile_url($profile->nickname);
common_debug("Changing user nickname from '{$this->scoped->getNickname()}' to '{$nickname}'.");
$this->scoped->nickname = $nickname;
$this->scoped->profileurl = common_profile_url($this->scoped->getNickname());
}
$profile->fullname = $fullname;
$profile->homepage = $homepage;
$profile->bio = $bio;
$profile->location = $location;
$this->scoped->fullname = (mb_strlen($fullname)>0 ? $fullname : $this->scoped->nickname);
$this->scoped->homepage = $homepage;
$this->scoped->bio = $bio;
$this->scoped->location = $location;
$loc = Location::fromName($location);
if (empty($loc)) {
$profile->lat = null;
$profile->lon = null;
$profile->location_id = null;
$profile->location_ns = null;
$this->scoped->lat = null;
$this->scoped->lon = null;
$this->scoped->location_id = null;
$this->scoped->location_ns = null;
} else {
$profile->lat = $loc->lat;
$profile->lon = $loc->lon;
$profile->location_id = $loc->location_id;
$profile->location_ns = $loc->location_ns;
$this->scoped->lat = $loc->lat;
$this->scoped->lon = $loc->lon;
$this->scoped->location_id = $loc->location_id;
$this->scoped->location_ns = $loc->location_ns;
}
if (common_config('location', 'share') == 'user') {
$exists = false;
$prefs = User_location_prefs::getKV('user_id', $user->id);
$prefs = User_location_prefs::getKV('user_id', $this->scoped->getID());
if (empty($prefs)) {
$prefs = new User_location_prefs();
$prefs->user_id = $user->id;
$prefs->user_id = $this->scoped->getID();
$prefs->created = common_sql_now();
} else {
$exists = true;
$orig = clone($prefs);
}
$prefs->share_location = $this->boolean('sharelocation');
$prefs->share_location = $this->booleanintstring('sharelocation');
if ($exists) {
$result = $prefs->update($orig);
@@ -408,42 +403,37 @@ class ProfilesettingsAction extends SettingsAction
if ($result === false) {
common_log_db_error($prefs, ($exists) ? 'UPDATE' : 'INSERT', __FILE__);
$user->query('ROLLBACK');
// TRANS: Server error thrown when user profile location preference settings could not be updated.
$this->serverError(_('Could not save location prefs.'));
throw new ServerException(_('Could not save location prefs.'));
}
}
common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__);
common_debug('New profile: ' . common_log_objstring($profile), __FILE__);
common_debug('Old profile: ' . common_log_objstring($original), __FILE__);
common_debug('New profile: ' . common_log_objstring($this->scoped), __FILE__);
$result = $profile->update($orig_profile);
$result = $this->scoped->update($original);
if ($result === false) {
common_log_db_error($profile, 'UPDATE', __FILE__);
common_log_db_error($this->scoped, 'UPDATE', __FILE__);
$user->query('ROLLBACK');
// TRANS: Server error thrown when user profile settings could not be saved.
$this->serverError(_('Could not save profile.'));
throw new ServerException(_('Could not save profile.'));
}
// Set the user tags
$result = $user->setSelfTags($tags, $tag_priv);
if (!$result) {
// TRANS: Server error thrown when user profile settings tags could not be saved.
$this->serverError(_('Could not save tags.'));
}
$result = Profile_tag::setSelfTags($this->scoped, $tags, $tag_priv);
$user->query('COMMIT');
Event::handle('EndProfileSaveForm', array($this));
// TRANS: Confirmation shown when user profile settings are saved.
$this->showForm(_('Settings saved.'), true);
return _('Settings saved.');
}
}
function showAside() {
$user = common_current_user();
$this->elementStart('div', array('id' => 'aside_primary',
'class' => 'aside'));
@@ -451,7 +441,7 @@ class ProfilesettingsAction extends SettingsAction
'class' => 'section'));
$this->elementStart('ul');
if (Event::handle('StartProfileSettingsActions', array($this))) {
if ($user->hasRight(Right::BACKUPACCOUNT)) {
if ($this->scoped->hasRight(Right::BACKUPACCOUNT)) {
$this->elementStart('li');
$this->element('a',
array('href' => common_local_url('backupaccount')),
@@ -459,7 +449,7 @@ class ProfilesettingsAction extends SettingsAction
_('Backup account'));
$this->elementEnd('li');
}
if ($user->hasRight(Right::DELETEACCOUNT)) {
if ($this->scoped->hasRight(Right::DELETEACCOUNT)) {
$this->elementStart('li');
$this->element('a',
array('href' => common_local_url('deleteaccount')),
@@ -467,7 +457,7 @@ class ProfilesettingsAction extends SettingsAction
_('Delete account'));
$this->elementEnd('li');
}
if ($user->hasRight(Right::RESTOREACCOUNT)) {
if ($this->scoped->hasRight(Right::RESTOREACCOUNT)) {
$this->elementStart('li');
$this->element('a',
array('href' => common_local_url('restoreaccount')),
+25 -161
Ver Arquivo
@@ -29,10 +29,6 @@
if (!defined('GNUSOCIAL')) { exit(1); }
// Farther than any human will go
define('MAX_PUBLIC_PAGE', 100);
/**
* Action for displaying the public stream
*
@@ -43,54 +39,9 @@ define('MAX_PUBLIC_PAGE', 100);
* @link http://status.net/
*
* @see PublicrssAction
* @see PublicxrdsAction
*/
class PublicAction extends ManagedAction
class PublicAction extends SitestreamAction
{
/**
* page of the stream we're on; default = 1
*/
var $page = null;
var $notice;
protected $stream = null;
function isReadOnly($args)
{
return true;
}
protected function doPreparation()
{
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
if ($this->page > MAX_PUBLIC_PAGE) {
// TRANS: Client error displayed when requesting a public timeline page beyond the page limit.
// TRANS: %s is the page limit.
$this->clientError(sprintf(_('Beyond the page limit (%s).'), MAX_PUBLIC_PAGE));
}
common_set_returnto($this->selfUrl());
$this->streamPrepare();
$this->notice = $this->stream->getNotices(($this->page-1)*NOTICES_PER_PAGE,
NOTICES_PER_PAGE + 1);
if (!$this->notice) {
// TRANS: Server error displayed when a public timeline cannot be retrieved.
$this->serverError(_('Could not retrieve public timeline.'));
}
if ($this->page > 1 && $this->notice->N == 0){
// TRANS: Client error when page not found (404).
$this->clientError(_('No such page.'), 404);
}
return true;
}
protected function streamPrepare()
{
if ($this->scoped instanceof Profile && $this->scoped->isLocal() && $this->scoped->getUser()->streamModeOnly()) {
@@ -117,100 +68,6 @@ class PublicAction extends ManagedAction
}
}
function extraHead()
{
parent::extraHead();
$this->element('meta', array('http-equiv' => 'X-XRDS-Location',
'content' => common_local_url('publicxrds')));
$rsd = common_local_url('rsd');
// RSD, http://tales.phrasewise.com/rfc/rsd
$this->element('link', array('rel' => 'EditURI',
'type' => 'application/rsd+xml',
'href' => $rsd));
if ($this->page != 1) {
$this->element('link', array('rel' => 'canonical',
'href' => common_local_url('public')));
}
}
/**
* Output <head> elements for RSS and Atom feeds
*
* @return void
*/
function getFeeds()
{
return array(new Feed(Feed::JSON,
common_local_url('ApiTimelinePublic',
array('format' => 'as')),
// TRANS: Link description for public timeline feed.
_('Public Timeline Feed (Activity Streams JSON)')),
new Feed(Feed::RSS1, common_local_url('publicrss'),
// TRANS: Link description for public timeline feed.
_('Public Timeline Feed (RSS 1.0)')),
new Feed(Feed::RSS2,
common_local_url('ApiTimelinePublic',
array('format' => 'rss')),
// TRANS: Link description for public timeline feed.
_('Public Timeline Feed (RSS 2.0)')),
new Feed(Feed::ATOM,
common_local_url('ApiTimelinePublic',
array('format' => 'atom')),
// TRANS: Link description for public timeline feed.
_('Public Timeline Feed (Atom)')));
}
function showEmptyList()
{
// TRANS: Text displayed for public feed when there are no public notices.
$message = _('This is the public timeline for %%site.name%% but no one has posted anything yet.') . ' ';
if (common_logged_in()) {
// TRANS: Additional text displayed for public feed when there are no public notices for a logged in user.
$message .= _('Be the first to post!');
}
else {
if (! (common_config('site','closed') || common_config('site','inviteonly'))) {
// TRANS: Additional text displayed for public feed when there are no public notices for a not logged in user.
$message .= _('Why not [register an account](%%action.register%%) and be the first to post!');
}
}
$this->elementStart('div', 'guide');
$this->raw(common_markup_to_html($message));
$this->elementEnd('div');
}
/**
* Fill the content area
*
* Shows a list of the notices in the public stream, with some pagination
* controls.
*
* @return void
*/
function showContent()
{
if ($this->scoped instanceof Profile && $this->scoped->isLocal() && $this->scoped->getUser()->streamModeOnly()) {
$nl = new PrimaryNoticeList($this->notice, $this, array('show_n'=>NOTICES_PER_PAGE));
} else {
$nl = new ThreadedNoticeList($this->notice, $this, $this->scoped);
}
$cnt = $nl->show();
if ($cnt == 0) {
$this->showEmptyList();
}
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
$this->page, $this->action);
}
function showSections()
{
// Show invite button, as long as site isn't closed, and
@@ -239,23 +96,30 @@ class PublicAction extends ManagedAction
$feat->show();
}
function showAnonymousMessage()
/**
* Output <head> elements for RSS and Atom feeds
*
* @return void
*/
function getFeeds()
{
if (! (common_config('site','closed') || common_config('site','inviteonly'))) {
// TRANS: Message for not logged in users at an invite-only site trying to view the public feed of notices.
// TRANS: This message contains Markdown links. Please mind the formatting.
$m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [StatusNet](http://status.net/) tool. ' .
'[Join now](%%action.register%%) to share notices about yourself with friends, family, and colleagues! ' .
'([Read more](%%doc.help%%))');
} else {
// TRANS: Message for not logged in users at a closed site trying to view the public feed of notices.
// TRANS: This message contains Markdown links. Please mind the formatting.
$m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [StatusNet](http://status.net/) tool.');
}
$this->elementStart('div', array('id' => 'anon_notice'));
$this->raw(common_markup_to_html($m));
$this->elementEnd('div');
return array(new Feed(Feed::JSON,
common_local_url('ApiTimelinePublic',
array('format' => 'as')),
// TRANS: Link description for public timeline feed.
_('Public Timeline Feed (Activity Streams JSON)')),
new Feed(Feed::RSS1, common_local_url('publicrss'),
// TRANS: Link description for public timeline feed.
_('Public Timeline Feed (RSS 1.0)')),
new Feed(Feed::RSS2,
common_local_url('ApiTimelinePublic',
array('format' => 'rss')),
// TRANS: Link description for public timeline feed.
_('Public Timeline Feed (RSS 2.0)')),
new Feed(Feed::ATOM,
common_local_url('ApiTimelinePublic',
array('format' => 'atom')),
// TRANS: Link description for public timeline feed.
_('Public Timeline Feed (Atom)')));
}
}
+4 -36
Ver Arquivo
@@ -28,11 +28,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
require_once INSTALLDIR.'/lib/rssaction.php';
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* RSS feed for public timeline.
@@ -48,29 +44,6 @@ require_once INSTALLDIR.'/lib/rssaction.php';
*/
class PublicrssAction extends Rss10Action
{
/**
* Read arguments and initialize members
*
* @param array $args Arguments from $_REQUEST
* @return boolean success
*/
function prepare($args)
{
parent::prepare($args);
$this->notices = $this->getNotices($this->limit);
return true;
}
/**
* Initialization.
*
* @return boolean true
*/
function init()
{
return true;
}
/**
* Get notices
*
@@ -78,15 +51,10 @@ class PublicrssAction extends Rss10Action
*
* @return array notices
*/
function getNotices($limit=0)
protected function getNotices()
{
$notices = array();
$notice = Notice::publicStream(0, ($limit == 0) ? 48 : $limit);
while ($notice->fetch()) {
$notices[] = clone($notice);
}
return $notices;
$stream = Notice::publicStream(0, $this->limit);
return $stream->fetchAll();
}
/**
+11 -14
Ver Arquivo
@@ -272,10 +272,16 @@ class RecoverpasswordAction extends Action
try {
User::recoverPassword($nore);
$this->mode = 'sent';
// TRANS: User notification after an e-mail with instructions was sent from the password recovery form.
$this->msg = _('Instructions for recovering your password ' .
'have been sent to the email address registered to your ' .
'account.');
if (common_is_email($nore) && common_config('site', 'fakeaddressrecovery')) {
// TRANS: User notification when recovering password by giving email address,
// regardless if the mail was sent or not (to hide registered email status).
$this->msg = _('If the email address you provided was found in the database, a recovery mail with instructions has been sent there.');
} else {
// TRANS: User notification after an e-mail with instructions was sent from the password recovery form.
$this->msg = _('Instructions for recovering your password ' .
'have been sent to the email address registered to your ' .
'account.');
}
$this->success = true;
} catch (Exception $e) {
$this->success = false;
@@ -316,16 +322,7 @@ class RecoverpasswordAction extends Action
}
// OK, we're ready to go
$original = clone($user);
$user->password = common_munge_password($newpassword, $user->id);
if (!$user->update($original)) {
common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Reset password form validation error message.
$this->serverError(_('Cannot save new password.'));
}
$user->setPassword($newpassword);
$this->clearTempUser();
+8 -60
Ver Arquivo
@@ -28,11 +28,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Redirect to a given URL
@@ -47,75 +43,27 @@ if (!defined('STATUSNET')) {
* @link http://status.net/
*/
class RedirecturlAction extends Action
class RedirecturlAction extends ManagedAction
{
protected $id = null;
protected $file = null;
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
protected function doPreparation()
{
parent::prepare($argarray);
$this->id = $this->trimmed('id');
if (empty($this->id)) {
// TRANS: Client exception thrown when no ID parameter was provided.
throw new ClientException(_('No id parameter.'));
}
$this->file = File::getKV('id', $this->id);
if (empty($this->file)) {
// TRANS: Client exception thrown when an invalid ID parameter was provided for a file.
// TRANS: %d is the provided ID for which the file is not present (number).
throw new ClientException(sprintf(_('No such file "%d".'),
$this->id),
404);
}
$this->file = File::getByID($this->int('id'));
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return void
*/
function handle($argarray=null)
public function showPage()
{
common_redirect($this->file->url, 307);
common_redirect($this->file->getUrl(false), 301);
}
/**
* Return true if read only.
*
* MAY override
*
* @param array $args other arguments
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
return true;
}
/**
* Return last modified, if applicable.
*
* MAY override
*
* @return string last modified http header
*/
function lastModified()
{
// For comparison with If-Last-Modified
@@ -133,9 +81,9 @@ class RedirecturlAction extends Action
*/
function etag()
{
return 'W/"' . implode(':', array($this->arg('action'),
return 'W/"' . implode(':', array($this->getActionName(),
common_user_cache_hash(),
common_language(),
$this->file->id)) . '"';
$this->file->getID())) . '"';
}
}
+31 -36
Ver Arquivo
@@ -27,9 +27,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
if (!defined('GNUSOCIAL') && !defined('STATUSNET')) { exit(1); }
/**
* An action for registering a new user account
@@ -133,7 +131,11 @@ class RegisterAction extends Action
// TRANS: Client error displayed when trying to register while already logged in.
$this->clientError(_('Already logged in.'));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$this->tryRegister();
try {
$this->tryRegister();
} catch (ClientException $e) {
$this->showForm($e->getMessage());
}
} else {
$this->showForm();
}
@@ -210,9 +212,6 @@ class RegisterAction extends Action
!common_valid_http_url($homepage)) {
// TRANS: Form validation error displayed when trying to register with an invalid homepage URL.
$this->showForm(_('Homepage is not a valid URL.'));
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
// TRANS: Form validation error displayed when trying to register with a too long full name.
$this->showForm(_('Full name is too long (maximum 255 characters).'));
} else if (Profile::bioTooLong($bio)) {
// TRANS: Form validation error on registration page when providing too long a bio text.
// TRANS: %d is the maximum number of characters for bio; used for plural.
@@ -220,49 +219,44 @@ class RegisterAction extends Action
'Bio is too long (maximum %d characters).',
Profile::maxBio()),
Profile::maxBio()));
} else if (!is_null($location) && mb_strlen($location) > 255) {
// TRANS: Form validation error displayed when trying to register with a too long location.
$this->showForm(_('Location is too long (maximum 255 characters).'));
} else if (strlen($password) < 6) {
// TRANS: Form validation error displayed when trying to register with too short a password.
$this->showForm(_('Password must be 6 or more characters.'));
} else if ($password != $confirm) {
// TRANS: Form validation error displayed when trying to register with non-matching passwords.
$this->showForm(_('Passwords do not match.'));
} else if ($user = User::register(array('nickname' => $nickname,
} else {
try {
$user = User::register(array('nickname' => $nickname,
'password' => $password,
'email' => $email,
'fullname' => $fullname,
'homepage' => $homepage,
'bio' => $bio,
'location' => $location,
'code' => $code))) {
if (!($user instanceof User)) {
'code' => $code));
// success!
if (!common_set_user($user)) {
// TRANS: Server error displayed when saving fails during user registration.
$this->serverError(_('Error setting user.'));
}
// this is a real login
common_real_login(true);
if ($this->boolean('rememberme')) {
common_debug('Adding rememberme cookie for ' . $nickname);
common_rememberme($user);
}
// Re-init language env in case it changed (not yet, but soon)
common_init_language();
Event::handle('EndRegistrationTry', array($this));
$this->showSuccess();
} catch (Exception $e) {
// TRANS: Form validation error displayed when trying to register with an invalid username or password.
$this->showForm(_('Invalid username or password.'));
return;
$this->showForm($e->getMessage());
}
// success!
if (!common_set_user($user)) {
// TRANS: Server error displayed when saving fails during user registration.
$this->serverError(_('Error setting user.'));
}
// this is a real login
common_real_login(true);
if ($this->boolean('rememberme')) {
common_debug('Adding rememberme cookie for ' . $nickname);
common_rememberme($user);
}
// Re-init language env in case it changed (not yet, but soon)
common_init_language();
Event::handle('EndRegistrationTry', array($this));
$this->showSuccess();
} else {
// TRANS: Form validation error displayed when trying to register with an invalid username or password.
$this->showForm(_('Invalid username or password.'));
}
}
}
@@ -489,6 +483,7 @@ class RegisterAction extends Action
'id' => 'license',
'class' => 'checkbox',
'name' => 'license',
'required' => 'true',
'value' => 'true');
if ($this->boolean('license')) {
$attrs['checked'] = 'checked';
+24 -101
Ver Arquivo
@@ -27,13 +27,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
require_once INSTALLDIR.'/lib/personalgroupnav.php';
require_once INSTALLDIR.'/lib/noticelist.php';
require_once INSTALLDIR.'/lib/feedlist.php';
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* List of replies
@@ -44,72 +38,11 @@ require_once INSTALLDIR.'/lib/feedlist.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class RepliesAction extends Action
class RepliesAction extends ShowstreamAction
{
var $page = null;
var $notice;
/**
* Prepare the object
*
* Check the input values and initialize the object.
* Shows an error page on bad input.
*
* @param array $args $_REQUEST data
*
* @return boolean success flag
*/
function prepare($args)
public function getStream()
{
parent::prepare($args);
$nickname = common_canonical_nickname($this->arg('nickname'));
$this->user = User::getKV('nickname', $nickname);
if (!$this->user) {
// TRANS: Client error displayed when trying to reply to a non-exsting user.
$this->clientError(_('No such user.'));
}
$profile = $this->user->getProfile();
if (!$profile) {
// TRANS: Error message displayed when referring to a user without a profile.
$this->serverError(_('User has no profile.'));
}
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
common_set_returnto($this->selfUrl());
$stream = new ReplyNoticeStream($this->user->id,
Profile::current());
$this->notice = $stream->getNotices(($this->page-1) * NOTICES_PER_PAGE,
NOTICES_PER_PAGE + 1);
if($this->page > 1 && $this->notice->N == 0){
// TRANS: Client error when page not found (404)
$this->clientError(_('No such page.'), 404);
}
return true;
}
/**
* Handle a request
*
* Just show the page. All args already handled.
*
* @param array $args $_REQUEST data
*
* @return void
*/
function handle($args)
{
parent::handle($args);
$this->showPage();
return new ReplyNoticeStream($this->target->getID(), $this->scoped);
}
/**
@@ -124,12 +57,12 @@ class RepliesAction extends Action
if ($this->page == 1) {
// TRANS: Title for first page of replies for a user.
// TRANS: %s is a user nickname.
return sprintf(_("Replies to %s"), $this->user->nickname);
return sprintf(_("Replies to %s"), $this->target->getNickname());
} else {
// TRANS: Title for all but the first page of replies for a user.
// TRANS: %1$s is a user nickname, %2$d is a page number.
return sprintf(_('Replies to %1$s, page %2$d'),
$this->user->nickname,
$this->target->getNickname(),
$this->page);
}
}
@@ -144,46 +77,39 @@ class RepliesAction extends Action
return array(new Feed(Feed::JSON,
common_local_url('ApiTimelineMentions',
array(
'id' => $this->user->nickname,
'id' => $this->target->getNickname(),
'format' => 'as')),
// TRANS: Link for feed with replies for a user.
// TRANS: %s is a user nickname.
sprintf(_('Replies feed for %s (Activity Streams JSON)'),
$this->user->nickname)),
$this->target->getNickname())),
new Feed(Feed::RSS1,
common_local_url('repliesrss',
array('nickname' => $this->user->nickname)),
array('nickname' => $this->target->getNickname())),
// TRANS: Link for feed with replies for a user.
// TRANS: %s is a user nickname.
sprintf(_('Replies feed for %s (RSS 1.0)'),
$this->user->nickname)),
$this->target->getNickname())),
new Feed(Feed::RSS2,
common_local_url('ApiTimelineMentions',
array(
'id' => $this->user->nickname,
'id' => $this->target->getNickname(),
'format' => 'rss')),
// TRANS: Link for feed with replies for a user.
// TRANS: %s is a user nickname.
sprintf(_('Replies feed for %s (RSS 2.0)'),
$this->user->nickname)),
$this->target->getNickname())),
new Feed(Feed::ATOM,
common_local_url('ApiTimelineMentions',
array(
'id' => $this->user->nickname,
'id' => $this->target->getNickname(),
'format' => 'atom')),
// TRANS: Link for feed with replies for a user.
// TRANS: %s is a user nickname.
sprintf(_('Replies feed for %s (Atom)'),
$this->user->nickname)));
$this->target->getNickname())));
}
/**
* Show the content
*
* A list of notices that are replies to the user, plus pagination.
*
* @return void
*/
function showContent()
{
$nl = new PrimaryNoticeList($this->notice, $this, array('show_n'=>NOTICES_PER_PAGE));
@@ -195,33 +121,30 @@ class RepliesAction extends Action
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
$this->page, 'replies',
array('nickname' => $this->user->nickname));
array('nickname' => $this->target->getNickname()));
}
function showEmptyListMessage()
{
// TRANS: Empty list message for page with replies for a user.
// TRANS: %1$s and %s$s are the user nickname.
$message = sprintf(_('This is the timeline showing replies to %1$s but %2$s hasn\'t received a notice to them yet.'),
$this->user->nickname,
$this->user->nickname) . ' ';
// TRANS: %1$s is the user nickname.
$message = sprintf(_('This is the timeline showing replies to %1$s but no notices have arrived yet.'), $this->target->getNickname());
$message .= ' '; // Spacing between this sentence and the next.
if (common_logged_in()) {
$current_user = common_current_user();
if ($this->user->id === $current_user->id) {
if ($this->target->getID() === $this->scoped->getID()) {
// TRANS: Empty list message for page with replies for a user for the logged in user.
// TRANS: This message contains a Markdown link in the form [link text](link).
$message .= _('You can engage other users in a conversation, subscribe to more people or [join groups](%%action.groups%%).');
} else {
// TRANS: Empty list message for page with replies for a user for all logged in users but the user themselves.
// TRANS: %1$s, %2$s and %3$s are a user nickname. This message contains a Markdown link in the form [link text](link).
$message .= sprintf(_('You can try to [nudge %1$s](../%2$s) or [post something to them](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname);
// TRANS: %1$s is a user nickname and %2$s is the same but with a prepended '@' character. This message contains a Markdown link in the form [link text](link).
$message .= sprintf(_('You can try to [nudge %1$s](../%1$s) or [post something to them](%%%%action.newnotice%%%%?content=%2$s).'), $this->target->getNickname(), '@' . $this->target->getNickname());
}
}
else {
} else {
// TRANS: Empty list message for page with replies for a user for not logged in users.
// TRANS: %1$s is a user nickname. This message contains a Markdown link in the form [link text](link).
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->user->nickname);
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->target->getNickname());
}
$this->elementStart('div', 'guide');
@@ -229,7 +152,7 @@ class RepliesAction extends Action
$this->elementEnd('div');
}
function isReadOnly($args)
public function isReadOnly($args)
{
return true;
}
+9 -45
Ver Arquivo
@@ -17,70 +17,34 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once(INSTALLDIR.'/lib/rssaction.php');
if (!defined('GNUSOCIAL')) { exit(1); }
// Formatting of RSS handled by Rss10Action
class RepliesrssAction extends Rss10Action
class RepliesrssAction extends TargetedRss10Action
{
var $user = null;
function prepare($args)
protected function getNotices()
{
parent::prepare($args);
$nickname = $this->trimmed('nickname');
$this->user = User::getKV('nickname', $nickname);
if (!$this->user) {
// TRANS: Client error displayed when providing a non-existing nickname in a RSS 1.0 action.
$this->clientError(_('No such user.'));
} else {
$this->notices = $this->getNotices($this->limit);
return true;
}
}
function getNotices($limit=0)
{
$user = $this->user;
$notice = $user->getReplies(0, ($limit == 0) ? 48 : $limit);
$notices = array();
while ($notice->fetch()) {
$notices[] = clone($notice);
}
return $notices;
$stream = $this->target->getReplies(0, $this->limit);
return $stream->fetchAll();
}
function getChannel()
{
$user = $this->user;
$c = array('url' => common_local_url('repliesrss',
array('nickname' =>
$user->nickname)),
$this->target->getNickname())),
// TRANS: RSS reply feed title. %s is a user nickname.
'title' => sprintf(_("Replies to %s"), $user->nickname),
'title' => sprintf(_("Replies to %s"), $this->target->getNickname()),
'link' => common_local_url('replies',
array('nickname' =>
$user->nickname)),
array('nickname' => $this->target->getNickname())),
// TRANS: RSS reply feed description.
// TRANS: %1$s is a user nickname, %2$s is the StatusNet site name.
'description' => sprintf(_('Replies to %1$s on %2$s.'),
$user->nickname, common_config('site', 'name')));
$this->target->getNickname(), common_config('site', 'name')));
return $c;
}
function getImage()
{
$profile = $this->user->getProfile();
return $profile->avatarUrl(AVATAR_PROFILE_SIZE);
}
function isReadOnly($args)
{
return true;
+3 -15
Ver Arquivo
@@ -27,9 +27,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Prints out a static robots.txt
@@ -40,19 +38,9 @@ if (!defined('STATUSNET')) {
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*/
class RobotstxtAction extends Action
class RobotstxtAction extends ManagedAction
{
/**
* Handles requests
*
* Since this is a relatively static document, we
* don't do a prepare()
*
* @param array $args GET, POST, and URL params; unused.
*
* @return void
*/
function handle($args)
public function showPage()
{
if (Event::handle('StartRobotsTxt', array($this))) {
+1 -1
Ver Arquivo
@@ -151,7 +151,7 @@ class RsdAction extends Action
$this->elementStart('api', $apiAttrs);
$this->elementStart('settings');
$this->element('docs', null,
'http://status.net/wiki/TwitterCompatibleAPI');
common_local_url('doc', array('title' => 'api')));
$this->element('setting', array('name' => 'OAuth'),
'true');
$this->elementEnd('settings');
+33 -31
Ver Arquivo
@@ -70,10 +70,11 @@ class ShownoticeAction extends ManagedAction
{
parent::prepare($args);
if ($this->boolean('ajax')) {
StatusNet::setApi(true);
GNUsocial::setApi(true);
}
$this->notice = $this->getNotice();
$this->target = $this->notice;
if (!$this->notice->inScope($this->scoped)) {
// TRANS: Client exception thrown when trying a view a notice the user has no access to.
@@ -113,20 +114,22 @@ class ShownoticeAction extends ManagedAction
{
$id = $this->arg('notice');
$notice = Notice::getKV('id', $id);
if ($notice instanceof Notice) {
$notice = null;
try {
$notice = Notice::getByID($id);
// Alright, got it!
return $notice;
}
// Did we use to have it, and it got deleted?
$deleted = Deleted_notice::getKV('id', $id);
if ($deleted instanceof Deleted_notice) {
// TRANS: Client error displayed trying to show a deleted notice.
$this->clientError(_('Notice deleted.'), 410);
} catch (NoResultException $e) {
// Hm, not found.
$deleted = null;
Event::handle('IsNoticeDeleted', array($id, &$deleted));
if ($deleted === true) {
// TRANS: Client error displayed trying to show a deleted notice.
throw new ClientException(_('Notice deleted.'), 410);
}
}
// TRANS: Client error displayed trying to show a non-existing notice.
$this->clientError(_('No such notice.'), 404);
throw new ClientException(_('No such notice.'), 404);
}
/**
@@ -211,36 +214,35 @@ class ShownoticeAction extends ManagedAction
{
}
/**
* Don't show aside
*
* @return void
*/
function showAside() {
function getFeeds()
{
return array(new Feed(Feed::JSON,
common_local_url('ApiStatusesShow',
array(
'id' => $this->target->getID(),
'format' => 'json')),
// TRANS: Title for link to single notice representation.
// TRANS: %s is a user nickname.
sprintf(_('Single notice (JSON)'))),
new Feed(Feed::ATOM,
common_local_url('ApiStatusesShow',
array(
'id' => $this->target->getID(),
'format' => 'atom')),
// TRANS: Title for link to notice feed.
// TRANS: %s is a user nickname.
sprintf(_('Single notice (Atom)'))));
}
/**
* Extra <head> content
*
* We show the microid(s) for the author, if any.
* Facebook OpenGraph metadata.
*
* @return void
*/
function extraHead()
{
$user = User::getKV($this->profile->id);
if (!$user instanceof User) {
return;
}
if ($user->emailmicroid && $user->email && $this->notice->uri) {
$id = new Microid('mailto:'. $user->email,
$this->notice->uri);
$this->element('meta', array('name' => 'microid',
'content' => $id->toString()));
}
// Extras to aid in sharing notices to Facebook
$avatarUrl = $this->profile->avatarUrl(AVATAR_PROFILE_SIZE);
$this->element('meta', array('property' => 'og:image',
+29 -119
Ver Arquivo
@@ -22,97 +22,31 @@
* @link http://status.net
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
require_once INSTALLDIR.'/lib/profileminilist.php';
require_once INSTALLDIR.'/lib/peopletaglist.php';
require_once INSTALLDIR.'/lib/noticelist.php';
require_once INSTALLDIR.'/lib/feedlist.php';
class ShowprofiletagAction extends Action
class ShowprofiletagAction extends ShowstreamAction
{
var $notice, $tagger, $peopletag, $userProfile;
var $notice, $peopletag;
function isReadOnly($args)
protected function doStreamPreparation()
{
return true;
}
function prepare($args)
{
parent::prepare($args);
if (common_config('singleuser', 'enabled')) {
$tagger_arg = User::singleUserNickname();
} else {
$tagger_arg = $this->arg('tagger');
}
$tag_arg = $this->arg('tag');
$tagger = common_canonical_nickname($tagger_arg);
$tag = common_canonical_tag($tag_arg);
// Permanent redirect on non-canonical nickname
if ($tagger_arg != $tagger || $tag_arg != $tag) {
$args = array('tagger' => $nickname, 'tag' => $tag);
if ($this->page != 1) {
$args['page'] = $this->page;
}
common_redirect(common_local_url('showprofiletag', $args), 301);
}
if (!$tagger) {
// TRANS: Client error displayed when a tagger is expected but not provided.
$this->clientError(_('No tagger.'), 404);
}
$user = User::getKV('nickname', $tagger);
if (!$user) {
// TRANS: Client error displayed trying to perform an action related to a non-existing user.
$this->clientError(_('No such user.'), 404);
}
$this->tagger = $user->getProfile();
$this->peopletag = Profile_list::pkeyGet(array('tagger' => $user->id, 'tag' => $tag));
$current = common_current_user();
$can_see = !empty($this->peopletag) && (!$this->peopletag->private ||
($this->peopletag->private && $this->peopletag->tagger === $current->id));
if (!$can_see) {
$tag = common_canonical_tag($this->arg('tag'));
try {
$this->peopletag = Profile_list::getByPK(array('tagger' => $this->target->getID(), 'tag' => $tag));
} catch (NoResultException $e) {
// TRANS: Client error displayed trying to reference a non-existing list.
$this->clientError(_('No such list.'), 404);
throw new ClientException('No such list.');
}
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
$this->userProfile = Profile::current();
$stream = new PeopletagNoticeStream($this->peopletag, $this->userProfile);
$this->notice = $stream->getNotices(($this->page-1)*NOTICES_PER_PAGE,
NOTICES_PER_PAGE + 1);
if ($this->page > 1 && $this->notice->N == 0) {
// TRANS: Client error when page not found (404).
$this->clientError(_('No such page.'), 404);
if ($this->peopletag->private && !$this->peopletag->getTagger()->sameAs($this->scoped)) {
// TRANS: Client error displayed trying to reference a non-existing list.
throw new AuthorizationException('You do not have permission to see this list.');
}
return true;
}
function handle($args)
public function getStream()
{
parent::handle($args);
if (!$this->peopletag) {
// TRANS: Client error displayed trying to perform an action related to a non-existing user.
$this->clientError(_('No such user.'));
}
$this->showPage();
return new PeopletagNoticeStream($this->peopletag, $this->scoped);
}
function title()
@@ -137,7 +71,7 @@ class ShowprofiletagAction extends Action
// TRANS: %1$s is a list, %2$s is the tagger's nickname, %3$d is a page number.
return sprintf(_('Timeline for %1$s list by %2$s, page %3$d'),
$this->peopletag->tag,
$this->tagger->nickname,
$this->target->getNickname(),
$this->page
);
} else {
@@ -160,7 +94,7 @@ class ShowprofiletagAction extends Action
// TRANS: %1$s is a list, %2$s is the tagger's nickname.
return sprintf(_('Timeline for %1$s list by %2$s'),
$this->peopletag->tag,
$this->tagger->nickname
$this->target->getNickname()
);
}
}
@@ -171,29 +105,29 @@ class ShowprofiletagAction extends Action
return array(new Feed(Feed::JSON,
common_local_url(
'ApiTimelineList', array(
'user' => $this->tagger->id,
'user' => $this->target->id,
'id' => $this->peopletag->id,
'format' => 'as'
)
),
// TRANS: Feed title.
// TRANS: %s is tagger's nickname.
sprintf(_('Feed for friends of %s (Activity Streams JSON)'), $this->tagger->nickname)),
sprintf(_('Feed for friends of %s (Activity Streams JSON)'), $this->target->getNickname())),
new Feed(Feed::RSS2,
common_local_url(
'ApiTimelineList', array(
'user' => $this->tagger->id,
'user' => $this->target->id,
'id' => $this->peopletag->id,
'format' => 'rss'
)
),
// TRANS: Feed title.
// TRANS: %s is tagger's nickname.
sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->tagger->nickname)),
sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->target->getNickname())),
new Feed(Feed::ATOM,
common_local_url(
'ApiTimelineList', array(
'user' => $this->tagger->id,
'user' => $this->target->id,
'id' => $this->peopletag->id,
'format' => 'atom'
)
@@ -201,7 +135,7 @@ class ShowprofiletagAction extends Action
// TRANS: Feed title.
// TRANS: %1$s is a list, %2$s is tagger's nickname.
sprintf(_('Feed for %1$s list by %2$s (Atom)'),
$this->peopletag->tag, $this->tagger->nickname
$this->peopletag->tag, $this->target->getNickname()
)
)
);
@@ -219,11 +153,10 @@ class ShowprofiletagAction extends Action
// TRANS: %1$s is a list, %2$s is a tagger's nickname.
$message = sprintf(_('This is the timeline for %1$s list by %2$s but no one has posted anything yet.'),
$this->peopletag->tag,
$this->tagger->nickname) . ' ';
$this->target->getNickname()) . ' ';
if (common_logged_in()) {
$current_user = common_current_user();
if ($this->tagger->id == $current_user->id) {
if ($this->target->sameAs($this->scoped)) {
// TRANS: Additional empty list message for list timeline for currently logged in user tagged tags.
$message .= _('Try tagging more people.');
}
@@ -238,16 +171,15 @@ class ShowprofiletagAction extends Action
$this->elementEnd('div');
}
function showContent()
protected function showContent()
{
$this->showPeopletag();
$this->showNotices();
parent::showContent();
}
function showPeopletag()
{
$cur = common_current_user();
$tag = new Peopletag($this->peopletag, $cur, $this);
$tag = new Peopletag($this->peopletag, $this->scoped, $this);
$tag->show();
}
@@ -267,7 +199,7 @@ class ShowprofiletagAction extends Action
$this->page,
'showprofiletag',
array('tag' => $this->peopletag->tag,
'tagger' => $this->tagger->nickname)
'nickname' => $this->target->getNickname())
);
Event::handle('EndShowProfileTagContent', array($this));
@@ -283,11 +215,6 @@ class ShowprofiletagAction extends Action
# $this->showStatistics();
}
function showPageTitle()
{
$this->element('h1', null, $this->title());
}
function showTagged()
{
$profile = $this->peopletag->getTagged(0, PROFILES_PER_MINILIST + 1);
@@ -314,7 +241,7 @@ class ShowprofiletagAction extends Action
if ($cnt > PROFILES_PER_MINILIST) {
$this->elementStart('p');
$this->element('a', array('href' => common_local_url('taggedprofiles',
array('nickname' => $this->tagger->nickname,
array('nickname' => $this->target->getNickname(),
'profiletag' => $this->peopletag->tag)),
'class' => 'more'),
// TRANS: Link for more "People in list x by a user"
@@ -356,20 +283,3 @@ class ShowprofiletagAction extends Action
$this->elementEnd('div');
}
}
class Peopletag extends PeopletagListItem
{
protected $avatarSize = AVATAR_PROFILE_SIZE;
function showStart()
{
$mode = $this->peopletag->private ? 'private' : 'public';
$this->out->elementStart('div', array('class' => 'h-entry peopletag peopletag-profile mode-'.$mode,
'id' => 'peopletag-' . $this->peopletag->id));
}
function showEnd()
{
$this->out->elementEnd('div');
}
}
+39 -120
Ver Arquivo
@@ -28,15 +28,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
require_once INSTALLDIR.'/lib/personalgroupnav.php';
require_once INSTALLDIR.'/lib/noticelist.php';
require_once INSTALLDIR.'/lib/profileminilist.php';
require_once INSTALLDIR.'/lib/groupminilist.php';
require_once INSTALLDIR.'/lib/feedlist.php';
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* User profile page
@@ -53,29 +45,22 @@ require_once INSTALLDIR.'/lib/feedlist.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class ShowstreamAction extends ProfileAction
class ShowstreamAction extends NoticestreamAction
{
var $notice;
protected function prepare(array $args=array())
public function getStream()
{
parent::prepare($args);
if (empty($this->tag)) {
$stream = new ProfileNoticeStream($this->profile, $this->scoped);
$stream = new ProfileNoticeStream($this->target, $this->scoped);
} else {
$stream = new TaggedProfileNoticeStream($this->profile, $this->tag, $this->scoped);
$stream = new TaggedProfileNoticeStream($this->target, $this->tag, $this->scoped);
}
$this->notice = $stream->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
return true;
return $stream;
}
function title()
{
$base = $this->profile->getFancyName();
$base = $this->target->getFancyName();
if (!empty($this->tag)) {
if ($this->page == 1) {
// TRANS: Page title showing tagged notices in one user's timeline.
@@ -88,7 +73,7 @@ class ShowstreamAction extends ProfileAction
}
} else {
if ($this->page == 1) {
return $base;
return sprintf(_('Notices by %s'), $base);
} else {
// TRANS: Extended page title showing tagged notices in one user's timeline.
// TRANS: %1$s is the username, %2$d is the page number.
@@ -99,14 +84,14 @@ class ShowstreamAction extends ProfileAction
}
}
function showContent()
protected function showContent()
{
$this->showNotices();
}
function showProfileBlock()
{
$block = new AccountProfileBlock($this, $this->profile);
$block = new AccountProfileBlock($this, $this->target);
$block->show();
}
@@ -120,78 +105,71 @@ class ShowstreamAction extends ProfileAction
if (!empty($this->tag)) {
return array(new Feed(Feed::RSS1,
common_local_url('userrss',
array('nickname' => $this->target->nickname,
array('nickname' => $this->target->getNickname(),
'tag' => $this->tag)),
// TRANS: Title for link to notice feed.
// TRANS: %1$s is a user nickname, %2$s is a hashtag.
sprintf(_('Notice feed for %1$s tagged %2$s (RSS 1.0)'),
$this->target->nickname, $this->tag)));
$this->target->getNickname(), $this->tag)));
}
return array(new Feed(Feed::JSON,
common_local_url('ApiTimelineUser',
array(
'id' => $this->user->id,
'id' => $this->target->getID(),
'format' => 'as')),
// TRANS: Title for link to notice feed.
// TRANS: %s is a user nickname.
sprintf(_('Notice feed for %s (Activity Streams JSON)'),
$this->target->nickname)),
$this->target->getNickname())),
new Feed(Feed::RSS1,
common_local_url('userrss',
array('nickname' => $this->target->nickname)),
array('nickname' => $this->target->getNickname())),
// TRANS: Title for link to notice feed.
// TRANS: %s is a user nickname.
sprintf(_('Notice feed for %s (RSS 1.0)'),
$this->target->nickname)),
$this->target->getNickname())),
new Feed(Feed::RSS2,
common_local_url('ApiTimelineUser',
array(
'id' => $this->user->id,
'id' => $this->target->getID(),
'format' => 'rss')),
// TRANS: Title for link to notice feed.
// TRANS: %s is a user nickname.
sprintf(_('Notice feed for %s (RSS 2.0)'),
$this->target->nickname)),
$this->target->getNickname())),
new Feed(Feed::ATOM,
common_local_url('ApiTimelineUser',
array(
'id' => $this->user->id,
'id' => $this->target->getID(),
'format' => 'atom')),
// TRANS: Title for link to notice feed.
// TRANS: %s is a user nickname.
sprintf(_('Notice feed for %s (Atom)'),
$this->target->nickname)),
$this->target->getNickname())),
new Feed(Feed::FOAF,
common_local_url('foaf', array('nickname' =>
$this->target->nickname)),
$this->target->getNickname())),
// TRANS: Title for link to notice feed. FOAF stands for Friend of a Friend.
// TRANS: More information at http://www.foaf-project.org. %s is a user nickname.
sprintf(_('FOAF for %s'), $this->target->nickname)));
sprintf(_('FOAF for %s'), $this->target->getNickname())));
}
function extraHead()
{
if ($this->profile->bio) {
if ($this->target->bio) {
$this->element('meta', array('name' => 'description',
'content' => $this->profile->bio));
}
if ($this->user->emailmicroid && $this->user->email && $this->profile->profileurl) {
$id = new Microid('mailto:'.$this->user->email,
$this->selfUrl());
$this->element('meta', array('name' => 'microid',
'content' => $id->toString()));
'content' => $this->target->getDescription()));
}
// See https://wiki.mozilla.org/Microsummaries
$this->element('link', array('rel' => 'microsummary',
'href' => common_local_url('microsummary',
array('nickname' => $this->profile->nickname))));
array('nickname' => $this->target->getNickname()))));
$rsd = common_local_url('rsd',
array('nickname' => $this->profile->nickname));
array('nickname' => $this->target->getNickname()));
// RSD, http://tales.phrasewise.com/rfc/rsd
$this->element('link', array('rel' => 'EditURI',
@@ -200,30 +178,29 @@ class ShowstreamAction extends ProfileAction
if ($this->page != 1) {
$this->element('link', array('rel' => 'canonical',
'href' => $this->profile->profileurl));
'href' => $this->target->getUrl()));
}
}
function showEmptyListMessage()
{
// TRANS: First sentence of empty list message for a timeline. $1%s is a user nickname.
$message = sprintf(_('This is the timeline for %1$s, but %1$s hasn\'t posted anything yet.'), $this->target->nickname) . ' ';
$message = sprintf(_('This is the timeline for %1$s, but %1$s hasn\'t posted anything yet.'), $this->target->getNickname()) . ' ';
if (common_logged_in()) {
$current_user = common_current_user();
if ($this->user->id === $current_user->id) {
if ($this->scoped instanceof Profile) {
if ($this->target->getID() === $this->scoped->getID()) {
// TRANS: Second sentence of empty list message for a stream for the user themselves.
$message .= _('Seen anything interesting recently? You haven\'t posted any notices yet, now would be a good time to start :)');
} else {
// TRANS: Second sentence of empty list message for a non-self timeline. %1$s is a user nickname, %2$s is a part of a URL.
// TRANS: This message contains a Markdown link. Keep "](" together.
$message .= sprintf(_('You can try to nudge %1$s or [post something to them](%%%%action.newnotice%%%%?status_textarea=%2$s).'), $this->target->nickname, '@' . $this->target->nickname);
$message .= sprintf(_('You can try to nudge %1$s or [post something to them](%%%%action.newnotice%%%%?status_textarea=%2$s).'), $this->target->getNickname(), '@' . $this->target->getNickname());
}
}
else {
// TRANS: Second sentence of empty message for anonymous users. %s is a user nickname.
// TRANS: This message contains a Markdown link. Keep "](" together.
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->target->nickname);
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to them.'), $this->target->getNickname());
}
$this->elementStart('div', 'guide');
@@ -233,16 +210,13 @@ class ShowstreamAction extends ProfileAction
function showNotices()
{
$pnl = null;
if (Event::handle('ShowStreamNoticeList', array($this->notice, $this, &$pnl))) {
$pnl = new ProfileNoticeList($this->notice, $this);
}
$pnl = new NoticeList($this->notice, $this);
$cnt = $pnl->show();
if (0 == $cnt) {
$this->showEmptyListMessage();
}
$args = array('nickname' => $this->target->nickname);
$args = array('nickname' => $this->target->getNickname());
if (!empty($this->tag))
{
$args['tag'] = $this->tag;
@@ -259,13 +233,13 @@ class ShowstreamAction extends ProfileAction
$m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [StatusNet](http://status.net/) tool. ' .
'[Join now](%%%%action.register%%%%) to follow **%s**\'s notices and many more! ([Read more](%%%%doc.help%%%%))'),
$this->target->nickname, $this->target->nickname);
$this->target->getNickname(), $this->target->getNickname());
} else {
// TRANS: Announcement for anonymous users showing a timeline if site registrations are closed or invite only.
// TRANS: This message contains a Markdown link. Keep "](" together.
$m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [StatusNet](http://status.net/) tool.'),
$this->target->nickname, $this->target->nickname);
$this->target->getNickname(), $this->target->getNickname());
}
$this->elementStart('div', array('id' => 'anon_notice'));
$this->raw(common_markup_to_html($m));
@@ -276,7 +250,7 @@ class ShowstreamAction extends ProfileAction
{
parent::showSections();
if (!common_config('performance', 'high')) {
$cloud = new PersonalTagCloudSection($this, $this->user);
$cloud = new PersonalTagCloudSection($this->target, $this);
$cloud->show();
}
}
@@ -284,66 +258,11 @@ class ShowstreamAction extends ProfileAction
function noticeFormOptions()
{
$options = parent::noticeFormOptions();
$cur = common_current_user();
if (empty($cur) || $cur->id != $this->profile->id) {
$options['to_profile'] = $this->profile;
if (!$this->scoped instanceof Profile || !$this->scoped->sameAs($this->target)) {
$options['to_profile'] = $this->target;
}
return $options;
}
}
// We don't show the author for a profile, since we already know who it is!
/**
* Slightly modified from standard list; the author & avatar are hidden
* in CSS. We used to remove them here too, but as it turns out that
* confuses the inline reply code... and we hide them in CSS anyway
* since realtime updates come through in original form.
*
* Remaining customization right now is for the repeat marker, where
* it'll list who the original poster was instead of who did the repeat
* (since the repeater is you, and the repeatee isn't shown!)
* This will remain inconsistent if realtime updates come through,
* since those'll get rendered as a regular NoticeListItem.
*/
class ProfileNoticeList extends NoticeList
{
function newListItem($notice)
{
return new ProfileNoticeListItem($notice, $this->out);
}
}
class ProfileNoticeListItem extends DoFollowListItem
{
/**
* show a link to the author of repeat
*
* @return void
*/
function showRepeat()
{
if (!empty($this->repeat)) {
// FIXME: this code is almost identical to default; need to refactor
$attrs = array('href' => $this->profile->profileurl,
'class' => 'url');
if (!empty($this->profile->fullname)) {
$attrs['title'] = $this->profile->getFancyName();
}
$this->out->elementStart('span', 'repeat');
$text_link = XMLStringer::estring('a', $attrs, $this->profile->nickname);
// TRANS: Link to the author of a repeated notice. %s is a linked nickname.
$this->out->raw(sprintf(_('Repeat of %s'), $text_link));
$this->out->elementEnd('span');
}
}
}
+5 -41
Ver Arquivo
@@ -27,9 +27,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Silence a user.
@@ -42,45 +40,11 @@ if (!defined('STATUSNET')) {
*/
class SilenceAction 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;
}
$cur = common_current_user();
assert(!empty($cur)); // checked by parent
if (!$cur->hasRight(Right::SILENCEUSER)) {
// TRANS: Client error displayed trying to silence a user on a site where the feature is not enabled.
$this->clientError(_('You cannot silence users on this site.'));
}
assert(!empty($this->profile)); // checked by parent
if ($this->profile->isSilenced()) {
// TRANS: Client error displayed trying to silence an already silenced user.
$this->clientError(_('User is already silenced.'));
}
return true;
}
/**
* Silence a user.
*
* @return void
*/
function handlePost()
{
$this->profile->silence();
assert($this->scoped instanceof Profile);
assert($this->profile instanceof Profile);
$this->profile->silenceAs($this->scoped);
}
}
+4 -12
Ver Arquivo
@@ -27,11 +27,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Update the site-wide notice text
@@ -114,13 +110,9 @@ class SitenoticeadminpanelAction extends AdminPanelAction
}
// scrub HTML input
$config = array(
'safe' => 1,
'deny_attribute' => 'id,style,on*'
);
$siteNotice = htmLawed($siteNotice, $config);
require_once INSTALLDIR.'/extlib/HTMLPurifier/HTMLPurifier.auto.php';
$purifier = new HTMLPurifier();
$siteNotice = $purifier->purify($siteNotice);
}
}
+63 -105
Ver Arquivo
@@ -27,9 +27,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Settings for SMS
@@ -45,6 +43,14 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
class SmssettingsAction extends SettingsAction
{
protected function doPreparation()
{
if (!common_config('sms', 'enabled')) {
// TRANS: Message given in the SMS settings if SMS is not enabled on the site.
throw new ServerException(_('SMS is not available.'));
}
}
/**
* Title of the page
*
@@ -86,14 +92,7 @@ class SmssettingsAction extends SettingsAction
*/
function showContent()
{
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;
}
$user = common_current_user();
$user = $this->scoped->getUser();
$this->elementStart('form', array('method' => 'post',
'id' => 'form_settings_sms',
@@ -118,8 +117,8 @@ class SmssettingsAction extends SettingsAction
// TRANS: Button label to remove a confirmed SMS address.
$this->submit('remove', _m('BUTTON','Remove'));
} else {
$confirm = $this->getConfirmation();
if ($confirm) {
try {
$confirm = $this->getConfirmation();
$carrier = Sms_carrier::getKV($confirm->address_extra);
$this->element('p', 'form_unconfirmed',
$confirm->address . ' (' . $carrier->name . ')');
@@ -141,7 +140,7 @@ class SmssettingsAction extends SettingsAction
$this->elementEnd('ul');
// TRANS: Button label to confirm SMS confirmation code in SMS settings.
$this->submit('confirm', _m('BUTTON','Confirm'));
} else {
} catch (NoResultException $e) {
$this->elementStart('ul', 'form_data');
$this->elementStart('li');
// TRANS: Field label for SMS phone number input in SMS settings form.
@@ -216,60 +215,38 @@ class SmssettingsAction extends SettingsAction
*/
function getConfirmation()
{
$user = common_current_user();
$confirm = new Confirm_address();
$confirm->user_id = $user->id;
$confirm->user_id = $this->scoped->getID();
$confirm->address_type = 'sms';
if ($confirm->find(true)) {
return $confirm;
} else {
return null;
}
throw new NoResultException($confirm);
}
/**
* Handle posts to this form
*
* Based on the button that was pressed, muxes out to other functions
* to do the actual task requested.
*
* All sub-functions reload the form with a message -- success or failure.
*
* @return void
*/
function handlePost()
protected function doPost()
{
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
// TRANS: Client error displayed when the session token does not match or is not given.
$this->showForm(_('There was a problem with your session token. '.
'Try again, please.'));
return;
}
if ($this->arg('save')) {
$this->savePreferences();
return $this->savePreferences();
} else if ($this->arg('add')) {
$this->addAddress();
return $this->addAddress();
} else if ($this->arg('cancel')) {
$this->cancelConfirmation();
return $this->cancelConfirmation();
} else if ($this->arg('remove')) {
$this->removeAddress();
return $this->removeAddress();
} else if ($this->arg('removeincoming')) {
$this->removeIncoming();
return $this->removeIncoming();
} else if ($this->arg('newincoming')) {
$this->newIncoming();
return $this->newIncoming();
} 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.'));
return $this->confirmCode();
}
// TRANS: Message given submitting a form with an unknown action in SMS settings.
throw new ClientException(_('Unexpected form submission.'));
}
/**
@@ -281,30 +258,26 @@ class SmssettingsAction extends SettingsAction
*/
function savePreferences()
{
$smsnotify = $this->boolean('smsnotify');
$user = common_current_user();
assert(!is_null($user)); // should already be checked
$user = $this->scoped->getUser();
$user->query('BEGIN');
$original = clone($user);
$user->smsnotify = $smsnotify;
$user->smsnotify = $this->boolean('smsnotify');
$result = $user->update($original);
if ($result === false) {
common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error updating SMS preferences.
$this->serverError(_('Could not update user.'));
throw new ServerException(_('Could not update user.'));
}
$user->query('COMMIT');
// TRANS: Confirmation message for successful SMS preferences save.
$this->showForm(_('SMS preferences saved.'), true);
return _('SMS preferences saved.');
}
/**
@@ -324,28 +297,24 @@ class SmssettingsAction extends SettingsAction
// Some validation
if (!$sms) {
if (empty($sms)) {
// TRANS: Message given saving SMS phone number without having provided one.
$this->showForm(_('No phone number.'));
return;
throw new ClientException(_('No phone number.'));
}
if (!$carrier_id) {
if (empty($carrier_id)) {
// TRANS: Message given saving SMS phone number without having selected a carrier.
$this->showForm(_('No carrier selected.'));
return;
throw new ClientException(_('No carrier selected.'));
}
$sms = common_canonical_sms($sms);
if ($user->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;
throw new AlreadyFulfilledException(_('That is already your phone number.'));
} 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;
throw new ClientException(_('That phone number already belongs to another user.'));
}
$confirm = new Confirm_address();
@@ -353,7 +322,7 @@ class SmssettingsAction extends SettingsAction
$confirm->address = $sms;
$confirm->address_extra = $carrier_id;
$confirm->address_type = 'sms';
$confirm->user_id = $user->id;
$confirm->user_id = $this->scoped->getID();
$confirm->code = common_confirmation_code(40);
$result = $confirm->insert();
@@ -371,11 +340,9 @@ class SmssettingsAction extends SettingsAction
$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. '.
return _('A confirmation code was sent to the phone number you added. '.
'Check your phone for the code and instructions '.
'on how to use it.');
$this->showForm($msg, true);
}
/**
@@ -390,29 +357,27 @@ class SmssettingsAction extends SettingsAction
$sms = $this->trimmed('sms');
$carrier = $this->trimmed('carrier');
$confirm = $this->getConfirmation();
if (!$confirm) {
try {
$confirm = $this->getConfirmation();
if ($confirm->address != $sms) {
// TRANS: Message given canceling SMS phone number confirmation for the wrong phone number.
throw new ClientException(_('That is the wrong confirmation number.'));
}
} catch (NoResultException $e) {
// 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;
throw new AlreadyFulfilledException(_('No pending confirmation to cancel.'));
}
$result = $confirm->delete();
if (!$result) {
if ($result === false) {
common_log_db_error($confirm, 'DELETE', __FILE__);
// TRANS: Server error thrown on database error canceling SMS phone number confirmation.
$this->serverError(_('Could not delete SMS confirmation.'));
throw new ServerException(_('Could not delete SMS confirmation.'));
}
// TRANS: Message given after successfully canceling SMS phone number confirmation.
$this->showForm(_('SMS confirmation cancelled.'), true);
return _('SMS confirmation cancelled.');
}
/**
@@ -422,7 +387,7 @@ class SmssettingsAction extends SettingsAction
*/
function removeAddress()
{
$user = common_current_user();
$user = $this->scoped->getUser();
$sms = $this->arg('sms');
$carrier = $this->arg('carrier');
@@ -432,8 +397,7 @@ class SmssettingsAction extends SettingsAction
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;
throw new ClientException(_('That is not your phone number.'));
}
$original = clone($user);
@@ -446,7 +410,7 @@ class SmssettingsAction extends SettingsAction
$user->updateWithKeys($original);
// TRANS: Message given after successfully removing a registered SMS phone number.
$this->showForm(_('The SMS phone number was removed.'), true);
return _('The SMS phone number was removed.');
}
/**
@@ -460,15 +424,13 @@ class SmssettingsAction extends SettingsAction
*/
function smsExists($sms)
{
$user = common_current_user();
$other = User::getKV('sms', $sms);
if (!$other) {
if (!$other instanceof User) {
return false;
} else {
return $other->id != $user->id;
}
return !$this->scoped->sameAs($other->getProfile());
}
/**
@@ -519,15 +481,12 @@ class SmssettingsAction extends SettingsAction
{
$code = $this->trimmed('code');
if (!$code) {
if (empty($code)) {
// TRANS: Message given saving SMS phone number confirmation code without having provided one.
$this->showForm(_('No code entered.'));
return;
throw new ClientException(_('No code entered.'));
}
common_redirect(common_local_url('confirmaddress',
array('code' => $code)),
303);
common_redirect(common_local_url('confirmaddress', array('code' => $code)), 303);
}
/**
@@ -541,8 +500,7 @@ class SmssettingsAction extends SettingsAction
if (!$user->incomingemail) {
// TRANS: Form validation error displayed when trying to remove an incoming e-mail address while no address has been set.
$this->showForm(_('No incoming email address.'));
return;
throw new ClientException(_('No incoming email address.'));
}
$orig = clone($user);
@@ -553,7 +511,7 @@ class SmssettingsAction extends SettingsAction
$user->updateWithKeys($orig);
// TRANS: Confirmation text after updating SMS settings.
$this->showForm(_('Incoming email address removed.'), true);
return _('Incoming email address removed.');
}
/**
@@ -565,7 +523,7 @@ class SmssettingsAction extends SettingsAction
*/
function newIncoming()
{
$user = common_current_user();
$user = $this->scoped->getUser();
$orig = clone($user);
@@ -575,6 +533,6 @@ class SmssettingsAction extends SettingsAction
$user->updateWithKeys($orig);
// TRANS: Confirmation text after updating SMS settings.
$this->showForm(_('New incoming email address added.'), true);
return _('New incoming email address added.');
}
}
-26
Ver Arquivo
@@ -1,26 +0,0 @@
<?php
/**
* Startpage action. Decides what to show on the first page.
*/
if (!defined('GNUSOCIAL')) { exit(1); }
class StartpageAction extends ManagedAction
{
function isReadOnly($args)
{
return true;
}
function showPage()
{
if (common_config('singleuser', 'enabled')) {
$user = User::singleUser();
common_redirect(common_local_url('showstream', array('nickname' => $user->nickname)), 303);
} elseif (common_config('public', 'localonly')) {
common_redirect(common_local_url('public'), 303);
} else {
common_redirect(common_local_url('networkpublic'), 303);
}
}
}
+13 -43
Ver Arquivo
@@ -27,11 +27,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
require_once(INSTALLDIR.'/lib/profilelist.php');
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* List of group members
@@ -50,9 +46,9 @@ class SubqueueAction extends GalleryAction
{
parent::prepare($args);
if ($this->scoped->id != $this->target->id) {
if (!$this->target->sameAs($this->scoped)) {
// TRANS: Client error displayed when trying to approve group applicants without being a group administrator.
$this->clientError(_('You may only approve your own pending subscriptions.'));
throw new ClientException(_('You may only approve your own pending subscriptions.'));
}
return true;
}
@@ -88,47 +84,21 @@ class SubqueueAction extends GalleryAction
$cnt = 0;
$members = $this->target->getRequests($offset, $limit);
if ($members) {
// @fixme change!
$member_list = new SubQueueList($members, $this);
$cnt = $member_list->show();
try {
$subqueue = $this->target->getRequests($offset, $limit);
} catch (NoResultException $e) {
// TRANS: If no pending subscription requests are found
$this->element('div', null, _m('You have no pending subscription requests.'));
return;
}
$members->free();
$list = new SubQueueList($subqueue, $this);
$cnt = $list->show();
$subqueue->free();
$this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE,
$this->page, 'subqueue',
array('nickname' => $this->target->getNickname())); // urgh
}
}
class SubQueueList extends ProfileList
{
function newListItem($profile)
{
return new SubQueueListItem($profile, $this->action);
}
}
class SubQueueListItem extends ProfileListItem
{
function showActions()
{
$this->startActions();
if (Event::handle('StartProfileListItemActionElements', array($this))) {
$this->showApproveButtons();
Event::handle('EndProfileListItemActionElements', array($this));
}
$this->endActions();
}
function showApproveButtons()
{
$this->out->elementStart('li', 'entity_approval');
$form = new ApproveSubForm($this->out, $this->profile);
$form->show();
$this->out->elementEnd('li');
}
}
+1 -1
Ver Arquivo
@@ -122,7 +122,7 @@ class SubscribeAction extends Action
{
// Throws exception on error
$sub = Subscription::start($this->user->getProfile(),
$sub = Subscription::ensureStart($this->user->getProfile(),
$this->other);
if ($this->boolean('ajax')) {
-61
Ver Arquivo
@@ -132,64 +132,3 @@ class SubscribersAction extends GalleryAction
parent::showSections();
}
}
class SubscribersList extends SubscriptionList
{
function newListItem($profile)
{
return new SubscribersListItem($profile, $this->owner, $this->action);
}
}
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();
}
function showBlockForm()
{
$user = common_current_user();
if (!empty($user) && $this->owner->id == $user->id) {
$returnto = array('action' => 'subscribers',
'nickname' => $this->owner->getNickname());
$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;
}
}
+2 -72
Ver Arquivo
@@ -28,9 +28,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* A list of the user's subscriptions
@@ -60,7 +58,7 @@ class SubscriptionsAction extends GalleryAction
function showPageNotice()
{
if ($this->scoped instanceof Profile && $this->scoped->id === $this->target->id) {
if ($this->scoped instanceof Profile && $this->scoped->sameAs($this->getTarget())) {
$this->element('p', null,
// TRANS: Page notice for page with an overview of all subscriptions
// TRANS: of the logged in user's own profile.
@@ -156,71 +154,3 @@ class SubscriptionsAction extends GalleryAction
$this->target->getNickname())));
}
}
// XXX SubscriptionsList and SubscriptionList are dangerously close
class SubscriptionsList extends SubscriptionList
{
function newListItem($profile)
{
return new SubscriptionsListItem($profile, $this->owner, $this->action);
}
}
class SubscriptionsListItem extends SubscriptionListItem
{
function showOwnerControls()
{
$sub = Subscription::pkeyGet(array('subscriber' => $this->owner->id,
'subscribed' => $this->profile->id));
if (!$sub) {
return;
}
$transports = array();
Event::handle('GetImTransports', array(&$transports));
if (!$transports && !common_config('sms', 'enabled')) {
return;
}
$this->out->elementStart('form', array('id' => 'subedit-' . $this->profile->id,
'method' => 'post',
'class' => 'form_subscription_edit',
'action' => common_local_url('subedit')));
$this->out->hidden('token', common_session_token());
$this->out->hidden('profile', $this->profile->id);
if ($transports) {
$attrs = array('name' => 'jabber',
'type' => 'checkbox',
'class' => 'checkbox',
'id' => 'jabber-'.$this->profile->id);
if ($sub->jabber) {
$attrs['checked'] = 'checked';
}
$this->out->element('input', $attrs);
// TRANS: Checkbox label for enabling IM messages for a profile in a subscriptions list.
$this->out->element('label', array('for' => 'jabber-'.$this->profile->id), _m('LABEL','IM'));
} else {
$this->out->hidden('jabber', $sub->jabber);
}
if (common_config('sms', 'enabled')) {
$attrs = array('name' => 'sms',
'type' => 'checkbox',
'class' => 'checkbox',
'id' => 'sms-'.$this->profile->id);
if ($sub->sms) {
$attrs['checked'] = 'checked';
}
$this->out->element('input', $attrs);
// TRANS: Checkbox label for enabling SMS messages for a profile in a subscriptions list.
$this->out->element('label', array('for' => 'sms-'.$this->profile->id), _('SMS'));
} else {
$this->out->hidden('sms', $sub->sms);
}
// TRANS: Save button for settings for a profile in a subscriptions list.
$this->out->submit('save', _m('BUTTON','Save'));
$this->out->elementEnd('form');
}
}
+2 -1
Ver Arquivo
@@ -46,7 +46,8 @@ class TagAction extends ManagedAction
common_set_returnto($this->selfUrl());
$this->notice = Notice_tag::getStream($this->tag, (($this->page-1)*NOTICES_PER_PAGE), NOTICES_PER_PAGE + 1);
$this->notice = Notice_tag::getStream($this->tag)->getNotices(($this->page-1)*NOTICES_PER_PAGE,
NOTICES_PER_PAGE + 1);
if($this->page > 1 && $this->notice->N == 0){
// TRANS: Client error when page not found (404).
+25 -51
Ver Arquivo
@@ -19,9 +19,6 @@
if (!defined('GNUSOCIAL')) { exit(1); }
require_once INSTALLDIR . '/lib/settingsaction.php';
require_once INSTALLDIR . '/lib/peopletags.php';
class TagprofileAction extends FormAction
{
var $error = null;
@@ -29,36 +26,32 @@ class TagprofileAction extends FormAction
protected $target = null;
protected $form = 'TagProfile';
protected function prepare(array $args=array())
protected function doPreparation()
{
parent::prepare($args);
$id = $this->trimmed('id');
if (!$id) {
$this->target = null;
} else {
$uri = $this->trimmed('uri');
if (!empty($id)) {
$this->target = Profile::getKV('id', $id);
if (!$this->target instanceof Profile) {
// TRANS: Client error displayed when referring to non-existing profile ID.
$this->clientError(_('No profile with that ID.'));
}
} elseif (!empty($uri)) {
$this->target = Profile::fromUri($uri);
} else {
// TRANS: Client error displayed when trying to tag a user but no ID or profile is provided.
$this->clientError(_('No profile identifier provided.'));
}
if ($this->target instanceof Profile && !$this->scoped->canTag($this->target)) {
if (!$this->scoped->canTag($this->target)) {
// TRANS: Client error displayed when trying to tag a user that cannot be tagged.
$this->clientError(_('You cannot tag this user.'));
}
return true;
}
$this->formOpts = $this->target;
protected function handle()
{
if (Event::handle('StartTagProfileAction', array($this, $this->target))) {
parent::handle();
Event::handle('EndTagProfileAction', array($this, $this->target));
}
return true;
}
function title()
@@ -72,6 +65,15 @@ class TagprofileAction extends FormAction
return sprintf(_m('ADDTOLIST','List %s'), $this->target->getNickname());
}
function showPage()
{
// Only serve page content if we aren't POSTing via ajax
// otherwise, we serve XML content from doPost()
if (!$this->isPost() || !$this->boolean('ajax')) {
parent::showPage();
}
}
function showContent()
{
$this->elementStart('div', 'entity_profile h-card');
@@ -115,17 +117,8 @@ class TagprofileAction extends FormAction
}
}
protected function getForm()
protected function doPost()
{
$class = $this->form.'Form';
$form = new $class($this, $this->target);
return $form;
}
protected function handlePost()
{
parent::handlePost(); // Does nothing for now
$tagstring = $this->trimmed('tags');
$token = $this->trimmed('token');
@@ -144,22 +137,16 @@ class TagprofileAction extends FormAction
if (!common_valid_profile_tag($tag)) {
// TRANS: Form validation error displayed if a given tag is invalid.
// TRANS: %s is the invalid tag.
$this->showForm(sprintf(_('Invalid tag: "%s".'), $tag));
return;
throw new ClientException(sprintf(_('Invalid tag: "%s".'), $tag));
}
$tag_priv[$tag] = $private;
}
}
try {
$result = Profile_tag::setTags($this->scoped->id, $this->target->id, $tags, $tag_priv);
if (!$result) {
throw new Exception('The tags could not be saved.');
}
} catch (Exception $e) {
$this->showForm($e->getMessage());
return false;
$result = Profile_tag::setTags($this->scoped->getID(), $this->target->getID(), $tags, $tag_priv);
if (!$result) {
throw new ServerException('The tags could not be saved.');
}
if ($this->boolean('ajax')) {
@@ -188,17 +175,4 @@ class TagprofileAction extends FormAction
Event::handle('EndSavePeopletags', array($this, $tagstring));
}
}
function showPageNotice()
{
if ($this->error) {
$this->element('p', 'error', $this->error);
} else {
$this->elementStart('div', 'instructions');
$this->element('p', null,
// TRANS: Page notice.
_('Use this form to add your subscribers or subscriptions to lists.'));
$this->elementEnd('div');
}
}
}
+9 -23
Ver Arquivo
@@ -17,42 +17,28 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once(INSTALLDIR.'/lib/rssaction.php');
if (!defined('GNUSOCIAL')) { exit(1); }
// Formatting of RSS handled by Rss10Action
class TagrssAction extends Rss10Action
{
var $tag;
protected $tag;
function prepare($args) {
parent::prepare($args);
protected function doStreamPreparation()
{
$tag = common_canonical_tag($this->trimmed('tag'));
$this->tag = Notice_tag::getKV('tag', $tag);
if (!$this->tag) {
if (!$this->tag instanceof Notice_tag) {
// TRANS: Client error when requesting a tag feed for a non-existing tag.
$this->clientError(_('No such tag.'));
} else {
$this->notices = $this->getNotices($this->limit);
return true;
}
}
function getNotices($limit=0)
protected function getNotices()
{
$tag = $this->tag;
if (is_null($tag)) {
return null;
}
$notice = Notice_tag::getStream($tag->tag, 0, ($limit == 0) ? NOTICES_PER_PAGE : $limit);
while ($notice->fetch()) {
$notices[] = clone($notice);
}
return $notices;
$stream = Notice_tag::getStream($this->tag->tag)->getNotices(0, $this->limit);
return $stream->fetchAll();
}
function getChannel()
+14 -52
Ver Arquivo
@@ -20,67 +20,29 @@
* 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 Top
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
/**
* An action to redirect to the top of the site
*
* @category Action
* @package StatusNet
* @package GNUsocial
* @author Evan Prodromou <evan@status.net>
* @author Mikael Nordfeldth <mmn@hethane.se>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
* @copyright 2015 Free Software Foundation, Inc.
* @license https://www.gnu.org/licenses/agpl-3.0.html AGPL 3.0
* @link https://gnu.io/social
*/
class TopAction extends Action
if (!defined('GNUSOCIAL')) { exit(1); }
class TopAction extends ManagedAction
{
/**
* For initializing members of the class.
*
* @param array $argarray misc. arguments
*
* @return boolean true
*/
function prepare($argarray)
{
parent::prepare($argarray);
return true;
}
/**
* Handler method
*
* @param array $argarray is ignored since it's now passed in in prepare()
*
* @return void
*/
function handle($argarray=null)
public function showPage()
{
if (common_config('singleuser', 'enabled')) {
$url = common_local_url('showstream', array('nickname' => User::singleUserNickname()));
$user = User::singleUser();
common_redirect(common_local_url('showstream', array('nickname' => $user->getNickname())), 303);
} elseif (common_config('public', 'localonly')) {
common_redirect(common_local_url('public'), 303);
} else {
$url = common_local_url('public');
common_redirect(common_local_url('networkpublic'), 303);
}
// XXX: Permanent? I think so.
common_redirect($url, 301);
return;
}
}
+6 -42
Ver Arquivo
@@ -27,12 +27,10 @@
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Silence a user.
* Unsilence a user.
*
* @category Action
* @package StatusNet
@@ -42,45 +40,11 @@ if (!defined('STATUSNET')) {
*/
class UnsilenceAction 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;
}
$cur = common_current_user();
assert(!empty($cur)); // checked by parent
if (!$cur->hasRight(Right::SILENCEUSER)) {
// TRANS: Client error on page to unsilence a user when the feature is not enabled.
$this->clientError(_('You cannot silence users on this site.'));
}
assert(!empty($this->profile)); // checked by parent
if (!$this->profile->isSilenced()) {
// TRANS: Client error on page to unsilence a user when the to be unsilenced user has not been silenced.
$this->clientError(_('User is not silenced.'));
}
return true;
}
/**
* Silence a user.
*
* @return void
*/
function handlePost()
{
$this->profile->unsilence();
assert($this->scoped instanceof Profile);
assert($this->profile instanceof Profile);
$this->profile->unsilenceAs($this->scoped);
}
}
+12 -32
Ver Arquivo
@@ -28,9 +28,7 @@
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Miscellaneous settings actions
@@ -83,7 +81,7 @@ class UrlsettingsAction extends SettingsAction
*/
function showContent()
{
$user = common_current_user();
$user = $this->scoped->getUser();
$this->elementStart('form', array('method' => 'post',
'id' => 'form_settings_other',
@@ -154,31 +152,13 @@ class UrlsettingsAction extends SettingsAction
$this->elementEnd('form');
}
/**
* Handle a post
*
* Saves the changes to url-shortening prefs and shows a success or failure
* message.
*
* @return void
*/
function handlePost()
protected function doPost()
{
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
// TRANS: Client error displayed when the session token does not match or is not given.
$this->showForm(_('There was a problem with your session token. '.
'Try again, please.'));
return;
}
$urlshorteningservice = $this->trimmed('urlshorteningservice');
if (!is_null($urlshorteningservice) && strlen($urlshorteningservice) > 50) {
// TRANS: Form validation error for form "Other settings" in user profile.
$this->showForm(_('URL shortening service is too long (maximum 50 characters).'));
return;
throw new ClientException(_('URL shortening service is too long (maximum 50 characters).'));
}
$maxurllength = $this->trimmed('maxurllength');
@@ -195,9 +175,7 @@ class UrlsettingsAction extends SettingsAction
throw new ClientException(_('Invalid number for maximum notice length.'));
}
$user = common_current_user();
assert(!is_null($user)); // should already be checked
$user = $this->scoped->getUser();
$user->query('BEGIN');
@@ -209,14 +187,15 @@ class UrlsettingsAction extends SettingsAction
if ($result === false) {
common_log_db_error($user, 'UPDATE', __FILE__);
$user->query('ROLLBACK');
// TRANS: Server error displayed when "Other" settings in user profile could not be updated on the server.
$this->serverError(_('Could not update user.'));
throw new ServerException(_('Could not update user.'));
}
$prefs = User_urlshortener_prefs::getPrefs($user);
$orig = null;
if (empty($prefs)) {
if (!$prefs instanceof User_urlshortener_prefs) {
$prefs = new User_urlshortener_prefs();
$prefs->user_id = $user->id;
@@ -229,13 +208,14 @@ class UrlsettingsAction extends SettingsAction
$prefs->maxurllength = $maxurllength;
$prefs->maxnoticelength = $maxnoticelength;
if (!empty($orig)) {
if ($orig instanceof User_urlshortener_prefs) {
$result = $prefs->update($orig);
} else {
$result = $prefs->insert();
}
if (!$result) {
if ($result === null) {
$user->query('ROLLBACK');
// TRANS: Server exception thrown in profile URL settings when preferences could not be saved.
throw new ServerException(_('Error saving user URL shortening preferences.'));
}
@@ -243,6 +223,6 @@ class UrlsettingsAction extends SettingsAction
$user->query('COMMIT');
// TRANS: Confirmation message after saving preferences.
$this->showForm(_('Preferences saved.'), true);
return _('Preferences saved.');
}
}
+19 -44
Ver Arquivo
@@ -28,9 +28,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* User by ID action class.
@@ -42,50 +40,27 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*/
class UserbyidAction extends Action
class UserbyidAction extends ShowstreamAction
{
/**
* Is read only?
*
* @return boolean true
*/
function isReadOnly($args)
protected function doPreparation()
{
return true;
}
// accessing by ID just requires an ID, not a nickname
$this->target = Profile::getByID($this->trimmed('id'));
/**
* Class handler.
*
* @param array $args array of arguments
*
* @return nothing
*/
protected function handle()
{
parent::handle();
$id = $this->trimmed('id');
if (!$id) {
// TRANS: Client error displayed trying to find a user by ID without providing an ID.
$this->clientError(_('No ID.'));
// For local users when accessed by id number, redirect with
// the nickname as argument instead of id.
if ($this->target->isLocal()) {
// Support redirecting to FOAF rdf/xml if the agent prefers it...
// Internet Explorer doesn't specify "text/html" and does list "*/*"
// at least through version 8. We need to list text/html up front to
// ensure that only user-agents who specifically ask for RDF get it.
$page_prefs = 'text/html,application/xhtml+xml,application/rdf+xml,application/xml;q=0.3,text/xml;q=0.2';
$httpaccept = isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : null;
$type = common_negotiate_type(common_accept_to_prefs($httpaccept),
common_accept_to_prefs($page_prefs));
$page = $type === 'application/rdf+xml' ? 'foaf' : 'showstream';
$url = common_local_url($page, array('nickname' => $this->target->getNickname()));
common_redirect($url, 303);
}
$user = User::getKV($id);
if (!$user) {
// TRANS: Client error displayed trying to find a user by ID for a non-existing ID.
$this->clientError(_('No such user.'));
}
// Support redirecting to FOAF rdf/xml if the agent prefers it...
// Internet Explorer doesn't specify "text/html" and does list "*/*"
// at least through version 8. We need to list text/html up front to
// ensure that only user-agents who specifically ask for RDF get it.
$page_prefs = 'text/html,application/xhtml+xml,application/rdf+xml,application/xml;q=0.3,text/xml;q=0.2';
$httpaccept = isset($_SERVER['HTTP_ACCEPT'])
? $_SERVER['HTTP_ACCEPT'] : null;
$type = common_negotiate_type(common_accept_to_prefs($httpaccept),
common_accept_to_prefs($page_prefs));
$page = $type == 'application/rdf+xml' ? 'foaf' : 'showstream';
$url = common_local_url($page, array('nickname' => $user->nickname));
common_redirect($url, 303);
}
}
+54 -29
Ver Arquivo
@@ -52,46 +52,71 @@ class UsergroupsAction extends GalleryAction
if ($this->page == 1) {
// TRANS: Page title for first page of groups for a user.
// TRANS: %s is a nickname.
return sprintf(_('%s groups'), $this->user->nickname);
return sprintf(_('%s groups'), $this->getTarget()->getNickname());
} else {
// TRANS: Page title for all but the first page of groups for a user.
// TRANS: %1$s is a nickname, %2$d is a page number.
return sprintf(_('%1$s groups, page %2$d'),
$this->user->nickname,
$this->getTarget()->getNickname(),
$this->page);
}
}
function showPageNotice()
{
if ($this->scoped instanceof Profile && $this->scoped->sameAs($this->getTarget())) {
$this->element('p', 'instructions',
// TRANS: Page notice for page with an overview of all subscribed groups
// TRANS: of the logged in user's own profile.
_('These are the groups whose notices '.
'you listen to.'));
} else {
$this->element('p', 'instructions',
// TRANS: Page notice for page with an overview of all groups a user other
// TRANS: than the logged in user. %s is the user nickname.
sprintf(_('These are the groups whose '.
'notices %s listens to.'),
$this->target->getNickname()));
}
}
function showContent()
{
$this->elementStart('p', array('id' => 'new_group'));
$this->element('a', array('href' => common_local_url('newgroup'),
'class' => 'more'),
// TRANS: Link text on group page to create a new group.
_('Create a new group'));
$this->elementEnd('p');
$this->elementStart('p', array('id' => 'group_search'));
$this->element('a', array('href' => common_local_url('groupsearch'),
'class' => 'more'),
// TRANS: Link text on group page to search for groups.
_('Search for more groups'));
$this->elementEnd('p');
if ($this->scoped instanceof Profile && $this->scoped->sameAs($this->getTarget())) {
$notice =
// TRANS: Page notice of user's groups page.
// TRANS: %%%%action.groupsearch%%%% and %%%%action.newgroup%%%% are URLs. Do not change them.
// TRANS: This message contains Markdown links in the form [link text](link).
sprintf(_('Groups let you find and talk with ' .
'people of similar interests. ' .
'You can [search for groups](%%%%action.groups%%%%) in your instance or ' .
'[create a new group](%%%%action.newgroup%%%%). ' .
'You can also follow groups ' .
'from other GNU social instances: click on the remote button below ' .
'and copy the group\'s link. ' .
'You can find a list of GNU social groups [here](http://skilledtests.com/wiki/List_of_federated_GNU_social_groups)' .
''));
$this->elementStart('div', 'instructions');
$this->raw(common_markup_to_html($notice));
$this->elementEnd('div');
}
if (Event::handle('StartShowUserGroupsContent', array($this))) {
$offset = ($this->page-1) * GROUPS_PER_PAGE;
$limit = GROUPS_PER_PAGE + 1;
$groups = $this->user->getGroups($offset, $limit);
$groups = $this->getTarget()->getGroups($offset, $limit);
if ($groups instanceof User_group) {
$gl = new GroupList($groups, $this->user, $this);
$gl = new GroupList($groups, $this->getTarget(), $this);
$cnt = $gl->show();
$this->pagination($this->page > 1, $cnt > GROUPS_PER_PAGE,
$this->page, 'usergroups',
array('nickname' => $this->user->nickname));
} else {
$this->showEmptyListMessage();
if (0 == $cnt) {
$this->showEmptyListMessage();
} else {
$this->pagination($this->page > 1, $cnt > GROUPS_PER_PAGE,
$this->page, 'usergroups',
array('nickname' => $this->getTarget()->getNickname()));
}
}
Event::handle('EndShowUserGroupsContent', array($this));
@@ -102,16 +127,16 @@ class UsergroupsAction extends GalleryAction
{
// TRANS: Text on group page for a user that is not a member of any group.
// TRANS: %s is a user nickname.
$message = sprintf(_('%s is not a member of any group.'), $this->user->nickname) . ' ';
$message = sprintf(_('%s is not a member of any group.'), $this->getTarget()->getNickname()) . ' ';
if (common_logged_in()) {
$current_user = common_current_user();
if ($this->user->id === $current_user->id) {
if ($this->scoped->sameAs($this->getTarget())) {
// TRANS: Text on group page for a user that is not a member of any group. This message contains
// TRANS: a Markdown link in the form [link text](link) and a variable that should not be changed.
$message .= _('Try [searching for groups](%%action.groupsearch%%) and joining them.');
$message = _('You are not member of any group yet. After you join a group ' .
'you can send messages to its members using the ' .
'syntax "!groupname".');
}
}
}
$this->elementStart('div', 'guide');
$this->raw(common_markup_to_html($message));
$this->elementEnd('div');
@@ -119,7 +144,7 @@ class UsergroupsAction extends GalleryAction
function showProfileBlock()
{
$block = new AccountProfileBlock($this, $this->profile);
$block = new AccountProfileBlock($this, $this->getTarget());
$block->show();
}
}
+21 -67
Ver Arquivo
@@ -17,100 +17,54 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once(INSTALLDIR.'/lib/rssaction.php');
if (!defined('GNUSOCIAL')) { exit(1); }
// Formatting of RSS handled by Rss10Action
class UserrssAction extends Rss10Action
class UserrssAction extends TargetedRss10Action
{
var $tag = null;
protected $tag = null;
function prepare($args)
protected function doStreamPreparation()
{
parent::prepare($args);
$nickname = $this->trimmed('nickname');
$this->user = User::getKV('nickname', $nickname);
parent::doStreamPreparation();
$this->tag = $this->trimmed('tag');
}
if (!$this->user) {
// TRANS: Client error displayed when user not found for an action.
$this->clientError(_('No such user.'));
}
protected function getNotices()
{
if (!empty($this->tag)) {
$this->notices = $this->getTaggedNotices();
} else {
$this->notices = $this->getNotices();
$stream = $this->getTarget()->getTaggedNotices($this->tag, 0, $this->limit);
return $stream->fetchAll();
}
// otherwise we fetch a normal user stream
return true;
}
function getTaggedNotices()
{
$notice = $this->user->getTaggedNotices(
$this->tag,
0,
($this->limit == 0) ? NOTICES_PER_PAGE : $this->limit,
0,
0
);
$notices = array();
while ($notice->fetch()) {
$notices[] = clone($notice);
}
return $notices;
}
function getNotices()
{
$notice = $this->user->getNotices(
0,
($this->limit == 0) ? NOTICES_PER_PAGE : $this->limit
);
$notices = array();
while ($notice->fetch()) {
$notices[] = clone($notice);
}
return $notices;
$stream = $this->getTarget()->getNotices(0, $this->limit);
return $stream->fetchAll();
}
function getChannel()
{
$user = $this->user;
$profile = $user->getProfile();
$c = array('url' => common_local_url('userrss',
array('nickname' =>
$user->nickname)),
$this->target->getNickname())),
// TRANS: Message is used as link title. %s is a user nickname.
'title' => sprintf(_('%s timeline'), $user->nickname),
'link' => $profile->profileurl,
'title' => sprintf(_('%s timeline'), $this->target->getNickname()),
'link' => $this->target->getUrl(),
// TRANS: Message is used as link description. %1$s is a username, %2$s is a site name.
'description' => sprintf(_('Updates from %1$s on %2$s!'),
$user->nickname, common_config('site', 'name')));
$this->target->getNickname(), common_config('site', 'name')));
return $c;
}
function getImage()
{
$profile = $this->user->getProfile();
return $profile->avatarUrl(AVATAR_PROFILE_SIZE);
}
// override parent to add X-SUP-ID URL
function initRss($limit=0)
function initRss()
{
$url = common_local_url('sup', null, null, $this->user->id);
$url = common_local_url('sup', null, null, $this->target->getID());
header('X-SUP-ID: '.$url);
parent::initRss($limit);
parent::initRss();
}
function isReadOnly($args)
Ver Arquivo
Ver Arquivo
+16 -11
Ver Arquivo
@@ -22,7 +22,7 @@ class Attention extends Managed_DataObject
public $__table = 'attention'; // table name
public $notice_id; // int(4) primary_key not_null
public $profile_id; // int(4) primary_key not_null
public $reason; // varchar(255)
public $reason; // varchar(191) not 255 because utf8mb4 takes more space
public $created; // datetime() not_null
public $modified; // timestamp not_null default_CURRENT_TIMESTAMP
@@ -33,7 +33,7 @@ class Attention extends Managed_DataObject
'fields' => array(
'notice_id' => array('type' => 'int', 'not null' => true, 'description' => 'notice_id to give attention'),
'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'profile_id for feed receiver'),
'reason' => array('type' => 'varchar', 'length' => 255, 'description' => 'Optional reason why this was brought to the attention of profile_id'),
'reason' => array('type' => 'varchar', 'length' => 191, 'description' => 'Optional reason why this was brought to the attention of profile_id'),
'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
),
@@ -49,18 +49,23 @@ class Attention extends Managed_DataObject
);
}
public static function saveNew(Notice $notice, Profile $profile, $reason=null)
public static function saveNew(Notice $notice, Profile $target, $reason=null)
{
$att = new Attention();
try {
$att = Attention::getByKeys(['notice_id'=>$notice->getID(), 'profile_id'=>$target->getID()]);
throw new AlreadyFulfilledException('Attention already exists with reason: '.var_export($att->reason,true));
} catch (NoResultException $e) {
$att = new Attention();
$att->notice_id = $notice->getID();
$att->profile_id = $profile->getID();
$att->reason = $reason;
$att->created = common_sql_now();
$result = $att->insert();
$att->notice_id = $notice->getID();
$att->profile_id = $target->getID();
$att->reason = $reason;
$att->created = common_sql_now();
$result = $att->insert();
if ($result === false) {
throw new Exception('Could not saveNew in Attention');
if ($result === false) {
throw new Exception('Failed Attention::saveNew for notice id=='.$notice->getID().' target id=='.$target->getID().', reason=="'.$reason.'"');
}
}
return $att;
}
+16 -32
Ver Arquivo
@@ -1,27 +1,22 @@
<?php
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Table Definition for avatar
*/
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
class Avatar extends Managed_DataObject
{
###START_AUTOCODE
/* the code below is auto generated do not remove the above tag */
public $__table = 'avatar'; // table name
public $profile_id; // int(4) primary_key not_null
public $original; // tinyint(1)
public $width; // int(4) primary_key not_null
public $height; // int(4) primary_key not_null
public $mediatype; // varchar(32) not_null
public $filename; // varchar(255)
public $url; // varchar(255) unique_key
public $filename; // varchar(191) not 255 because utf8mb4 takes more space
public $created; // datetime() not_null
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
public static function schemaDef()
{
@@ -32,14 +27,13 @@ class Avatar extends Managed_DataObject
'width' => array('type' => 'int', 'not null' => true, 'description' => 'image width'),
'height' => array('type' => 'int', 'not null' => true, 'description' => 'image height'),
'mediatype' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'file type'),
'filename' => array('type' => 'varchar', 'length' => 255, 'description' => 'local filename, if local'),
'url' => array('type' => 'varchar', 'length' => 255, 'description' => 'avatar location'),
'filename' => array('type' => 'varchar', 'length' => 191, 'description' => 'local filename, if local'),
'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
),
'primary key' => array('profile_id', 'width', 'height'),
'unique keys' => array(
'avatar_url_key' => array('url'),
// 'avatar_filename_key' => array('filename'),
),
'foreign keys' => array(
'avatar_profile_id_fkey' => array('profile', array('profile_id' => 'id')),
@@ -193,16 +187,7 @@ class Avatar extends Managed_DataObject
$server = common_config('site', 'server');
}
$ssl = common_config('avatar', 'ssl');
if (is_null($ssl)) { // null -> guess
if (common_config('site', 'ssl') == 'always' &&
!common_config('avatar', 'server')) {
$ssl = true;
} else {
$ssl = false;
}
}
$ssl = (common_config('avatar', 'ssl') || GNUsocial::useHTTPS());
$protocol = ($ssl) ? 'https' : 'http';
@@ -211,12 +196,7 @@ class Avatar extends Managed_DataObject
function displayUrl()
{
$server = common_config('avatar', 'server');
if ($server && !empty($this->filename)) {
return Avatar::url($this->filename);
} else {
return $this->url;
}
return Avatar::url($this->filename);
}
static function urlByProfile(Profile $target, $width=null, $height=null) {
@@ -241,17 +221,21 @@ class Avatar extends Managed_DataObject
// TRANS: An error message when avatar size is unreasonable
throw new Exception(_m('Avatar size too large'));
}
// So far we only have square avatars and I don't have time to
// rewrite support for non-square ones right now ;)
$height = $width;
$original = Avatar::getUploaded($target);
$imagefile = new ImageFile($target->id, Avatar::path($original->filename));
$filename = $imagefile->resize($width);
$imagefile = new ImageFile(null, Avatar::path($original->filename));
$filename = Avatar::filename($target->getID(), image_type_to_extension($imagefile->preferredType()),
$width, common_timestamp());
$imagefile->resizeTo(Avatar::path($filename), array('width'=>$width, 'height'=>$height));
$scaled = clone($original);
$scaled->original = false;
$scaled->width = $width;
$scaled->height = $width;
$scaled->url = Avatar::url($filename);
$scaled->height = $height;
$scaled->filename = $filename;
$scaled->created = common_sql_now();
+3 -7
Ver Arquivo
@@ -17,16 +17,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET')) {
exit(1);
}
if (!defined('GNUSOCIAL')) { exit(1); }
/**
* Table Definition for config
*/
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
class Config extends Managed_DataObject
{
###START_AUTOCODE
@@ -35,7 +31,7 @@ class Config extends Managed_DataObject
public $__table = 'config'; // table name
public $section; // varchar(32) primary_key not_null
public $setting; // varchar(32) primary_key not_null
public $value; // varchar(255)
public $value; // text
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
@@ -46,7 +42,7 @@ class Config extends Managed_DataObject
'fields' => array(
'section' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'default' => '', 'description' => 'configuration section'),
'setting' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'default' => '', 'description' => 'configuration setting'),
'value' => array('type' => 'varchar', 'length' => 255, 'description' => 'configuration value'),
'value' => array('type' => 'text', 'description' => 'configuration value'),
),
'primary key' => array('section', 'setting'),
);
+4 -11
Ver Arquivo
@@ -2,34 +2,27 @@
/**
* Table Definition for confirm_address
*/
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
class Confirm_address extends Managed_DataObject
{
###START_AUTOCODE
/* the code below is auto generated do not remove the above tag */
public $__table = 'confirm_address'; // table name
public $code; // varchar(32) primary_key not_null
public $user_id; // int(4) not_null
public $address; // varchar(255) not_null
public $address_extra; // varchar(255) not_null
public $address; // varchar(191) not_null not 255 because utf8mb4 takes more space
public $address_extra; // varchar(191) not_null not 255 because utf8mb4 takes more space
public $address_type; // varchar(8) not_null
public $claimed; // datetime()
public $sent; // datetime()
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
public static function schemaDef()
{
return array(
'fields' => array(
'code' => array('type' => 'varchar', 'length' => 32, 'not null' => true, 'description' => 'good random code'),
'user_id' => array('type' => 'int', 'not null' => true, 'description' => 'user who requested confirmation'),
'address' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'address (email, xmpp, SMS, etc.)'),
'address_extra' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'carrier ID, for SMS'),
'address' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'address (email, xmpp, SMS, etc.)'),
'address_extra' => array('type' => 'varchar', 'length' => 191, 'description' => 'carrier ID, for SMS'),
'address_type' => array('type' => 'varchar', 'length' => 8, 'not null' => true, 'description' => 'address type ("email", "xmpp", "sms")'),
'claimed' => array('type' => 'datetime', 'description' => 'date this was claimed for queueing'),
'sent' => array('type' => 'datetime', 'description' => 'date this was sent for queueing'),
+4 -4
Ver Arquivo
@@ -10,8 +10,8 @@ class Consumer extends Managed_DataObject
/* the code below is auto generated do not remove the above tag */
public $__table = 'consumer'; // table name
public $consumer_key; // varchar(255) primary_key not_null
public $consumer_secret; // varchar(255) not_null
public $consumer_key; // varchar(191) primary_key not_null not 255 because utf8mb4 takes more space
public $consumer_secret; // varchar(191) not_null not 255 because utf8mb4 takes more space
public $seed; // char(32) not_null
public $created; // datetime not_null
public $modified; // timestamp not_null default_CURRENT_TIMESTAMP
@@ -24,8 +24,8 @@ class Consumer extends Managed_DataObject
return array(
'description' => 'OAuth consumer record',
'fields' => array(
'consumer_key' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'unique identifier, root URL'),
'consumer_secret' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'secret value'),
'consumer_key' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'unique identifier, root URL'),
'consumer_secret' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'description' => 'secret value'),
'seed' => array('type' => 'char', 'length' => 32, 'not null' => true, 'description' => 'seed for new tokens by this consumer'),
'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
+52 -27
Ver Arquivo
@@ -34,8 +34,8 @@ if (!defined('GNUSOCIAL')) { exit(1); }
class Conversation extends Managed_DataObject
{
public $__table = 'conversation'; // table name
public $id; // int(4) primary_key not_null
public $uri; // varchar(255) unique_key
public $id; // int(4) primary_key not_null auto_increment
public $uri; // varchar(191) unique_key not 255 because utf8mb4 takes more space
public $created; // datetime not_null
public $modified; // timestamp not_null default_CURRENT_TIMESTAMP
@@ -43,8 +43,8 @@ class Conversation extends Managed_DataObject
{
return array(
'fields' => array(
'id' => array('type' => 'int', 'not null' => true, 'description' => 'should be set from root notice id (since 2014-03-01 commit)'),
'uri' => array('type' => 'varchar', 'not null'=>true, 'length' => 255, 'description' => 'URI of the conversation'),
'id' => array('type' => 'serial', 'not null' => true, 'description' => 'Unique identifier, (again) unrelated to notice id since 2016-01-06'),
'uri' => array('type' => 'varchar', 'not null'=>true, 'length' => 191, 'description' => 'URI of the conversation'),
'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
),
@@ -55,6 +55,32 @@ class Conversation extends Managed_DataObject
);
}
static public function beforeSchemaUpdate()
{
$table = strtolower(get_called_class());
$schema = Schema::get();
$schemadef = $schema->getTableDef($table);
// 2016-01-06 We have to make sure there is no conversation with id==0 since it will screw up auto increment resequencing
if ($schemadef['fields']['id']['auto_increment']) {
// since we already have auto incrementing ('serial') we can continue
return;
}
// The conversation will be recreated in upgrade.php, which will
// generate a new URI, but that's collateral damage for you.
$conv = new Conversation();
$conv->id = 0;
if ($conv->find()) {
while ($conv->fetch()) {
// Since we have filtered on 0 this only deletes such entries
// which I have been afraid wouldn't work, but apparently does!
// (I thought it would act as null or something and find _all_ conversation entries)
$conv->delete();
}
}
}
/**
* Factory method for creating a new conversation.
*
@@ -63,25 +89,17 @@ class Conversation extends Managed_DataObject
*
* @return Conversation the new conversation DO
*/
static function create(Notice $notice, $uri=null)
static function create($uri=null, $created=null)
{
if (empty($notice->id)) {
throw new ServerException(_('Tried to create conversation for not yet inserted notice'));
}
// Be aware that the Notice does not have an id yet since it's not inserted!
$conv = new Conversation();
$conv->created = common_sql_now();
$conv->id = $notice->id;
$conv->uri = $uri ?: sprintf('%s%s=%d:%s=%s:%s=%x',
$conv->created = $created ?: common_sql_now();
$conv->uri = $uri ?: sprintf('%s%s=%s:%s=%s',
TagURI::mint(),
'noticeId', $notice->id,
'objectType', 'thread',
'crc32', crc32($notice->content));
$result = $conv->insert();
if ($result === false) {
common_log_db_error($conv, 'INSERT', __FILE__);
throw new ServerException(_('Failed to create conversation for notice'));
}
'nonce', common_random_hexstr(8));
// This insert throws exceptions on failure
$conv->insert();
return $conv;
}
@@ -108,8 +126,8 @@ class Conversation extends Managed_DataObject
static public function getUrlFromNotice(Notice $notice, $anchor=true)
{
$conv = self::getKV('id', $notice->conversation);
return $conv->getUrl($anchor ? $notice->id : null);
$conv = Conversation::getByID($notice->conversation);
return $conv->getUrl($anchor ? $notice->getID() : null);
}
public function getUri()
@@ -120,18 +138,25 @@ class Conversation extends Managed_DataObject
public function getUrl($noticeId=null)
{
// FIXME: the URL router should take notice-id as an argument...
return common_local_url('conversation', array('id' => $this->id)) .
return common_local_url('conversation', array('id' => $this->getID())) .
($noticeId===null ? '' : "#notice-{$noticeId}");
}
// FIXME: ...will 500 ever be too low? Taken from ConversationAction::MAX_NOTICES
public function getNotices($offset=0, $limit=500, Profile $scoped=null)
public function getNotices(Profile $scoped=null, $offset=0, $limit=500)
{
if ($scoped === null) {
$scoped = Profile::current();
}
$stream = new ConversationNoticeStream($this->id, $scoped);
$stream = new ConversationNoticeStream($this->getID(), $scoped);
$notices = $stream->getNotices($offset, $limit);
return $notices;
}
public function insert()
{
$result = parent::insert();
if ($result === false) {
common_log_db_error($this, 'INSERT', __FILE__);
throw new ServerException(_('Failed to insert Conversation into database'));
}
return $result;
}
}
-63
Ver Arquivo
@@ -1,63 +0,0 @@
<?php
/*
* Laconica - a distributed open-source microblogging tool
* Copyright (C) 2008, 2009, Control Yourself, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET')) {
exit(1);
}
/**
* Table Definition for notice
*/
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
class Deleted_notice extends Managed_DataObject
{
###START_AUTOCODE
/* the code below is auto generated do not remove the above tag */
public $__table = 'deleted_notice'; // table name
public $id; // int(4) primary_key not_null
public $profile_id; // int(4) not_null
public $uri; // varchar(255) unique_key
public $created; // datetime() not_null
public $deleted; // datetime() not_null
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
public static function schemaDef()
{
return array(
'fields' => array(
'id' => array('type' => 'int', 'not null' => true, 'description' => 'identity of notice'),
'profile_id' => array('type' => 'int', 'not null' => true, 'description' => 'author of the notice'),
'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universally unique identifier, usually a tag URI'),
'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date the notice record was created'),
'deleted' => array('type' => 'datetime', 'not null' => true, 'description' => 'date the notice record was created'),
),
'primary key' => array('id'),
'unique keys' => array(
'deleted_notice_uri_key' => array('uri'),
),
'indexes' => array(
'deleted_notice_profile_id_idx' => array('profile_id'),
),
);
}
}
+263 -170
Ver Arquivo
@@ -26,29 +26,36 @@ class File extends Managed_DataObject
{
public $__table = 'file'; // table name
public $id; // int(4) primary_key not_null
public $url; // varchar(255) unique_key
public $urlhash; // varchar(64) unique_key
public $url; // text
public $filehash; // varchar(64) indexed
public $mimetype; // varchar(50)
public $size; // int(4)
public $title; // varchar(255)
public $title; // text()
public $date; // int(4)
public $protected; // int(4)
public $filename; // varchar(255)
public $filename; // text()
public $width; // int(4)
public $height; // int(4)
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
const URLHASH_ALG = 'sha256';
const FILEHASH_ALG = 'sha256';
public static function schemaDef()
{
return array(
'fields' => array(
'id' => array('type' => 'serial', 'not null' => true),
'url' => array('type' => 'varchar', 'length' => 255, 'description' => 'destination URL after following redirections'),
'urlhash' => array('type' => 'varchar', 'length' => 64, 'not null' => true, 'description' => 'sha256 of destination URL (url field)'),
'url' => array('type' => 'text', 'description' => 'destination URL after following possible redirections'),
'filehash' => array('type' => 'varchar', 'length' => 64, 'not null' => false, 'description' => 'sha256 of the file contents, only for locally stored files of course'),
'mimetype' => array('type' => 'varchar', 'length' => 50, 'description' => 'mime type of resource'),
'size' => array('type' => 'int', 'description' => 'size of resource when available'),
'title' => array('type' => 'varchar', 'length' => 255, 'description' => 'title of resource when available'),
'title' => array('type' => 'text', 'description' => 'title of resource when available'),
'date' => array('type' => 'int', 'description' => 'date of resource according to http query'),
'protected' => array('type' => 'int', 'description' => 'true when URL is private (needs login)'),
'filename' => array('type' => 'varchar', 'length' => 255, 'description' => 'if a local file, name of the file'),
'filename' => array('type' => 'text', 'description' => 'if file is stored locally (too) this is the filename'),
'width' => array('type' => 'int', 'description' => 'width in pixels, if it can be described as such and data is available'),
'height' => array('type' => 'int', 'description' => 'height in pixels, if it can be described as such and data is available'),
@@ -56,13 +63,28 @@ class File extends Managed_DataObject
),
'primary key' => array('id'),
'unique keys' => array(
'file_url_key' => array('url'),
'file_urlhash_key' => array('urlhash'),
),
'indexes' => array(
'file_filehash_idx' => array('filehash'),
),
);
}
function isProtected($url) {
return 'http://www.facebook.com/login.php' === $url;
public static function isProtected($url) {
$protected_urls_exps = array(
'https://www.facebook.com/login.php',
common_path('main/login')
);
foreach ($protected_urls_exps as $protected_url_exp) {
if (preg_match('!^'.preg_quote($protected_url_exp).'(.*)$!i', $url) === 1) {
return true;
}
}
return false;
}
/**
@@ -72,29 +94,45 @@ class File extends Managed_DataObject
* @param string $given_url
* @return File
*/
public static function saveNew(array $redir_data, $given_url) {
// I don't know why we have to keep doing this but I'm adding this last check to avoid
// uniqueness bugs.
$file = File::getKV('url', $given_url);
if (!$file instanceof File) {
$file = new File;
$file->url = $given_url;
if (!empty($redir_data['protected'])) $file->protected = $redir_data['protected'];
if (!empty($redir_data['title'])) $file->title = $redir_data['title'];
if (!empty($redir_data['type'])) $file->mimetype = $redir_data['type'];
if (!empty($redir_data['size'])) $file->size = intval($redir_data['size']);
if (isset($redir_data['time']) && $redir_data['time'] > 0) $file->date = intval($redir_data['time']);
$file_id = $file->insert();
public static function saveNew(array $redir_data, $given_url)
{
$file = null;
try {
// I don't know why we have to keep doing this but we run a last check to avoid
// uniqueness bugs.
$file = File::getByUrl($given_url);
return $file;
} catch (NoResultException $e) {
// We don't have the file's URL since before, so let's continue.
}
Event::handle('EndFileSaveNew', array($file, $redir_data, $given_url));
assert ($file instanceof File);
$file = new File;
$file->url = $given_url;
if (!empty($redir_data['protected'])) $file->protected = $redir_data['protected'];
if (!empty($redir_data['title'])) $file->title = $redir_data['title'];
if (!empty($redir_data['type'])) $file->mimetype = $redir_data['type'];
if (!empty($redir_data['size'])) $file->size = intval($redir_data['size']);
if (isset($redir_data['time']) && $redir_data['time'] > 0) $file->date = intval($redir_data['time']);
$file->saveFile();
return $file;
}
public function saveFile() {
$this->urlhash = self::hashurl($this->url);
if (!Event::handle('StartFileSaveNew', array(&$this))) {
throw new ServerException('File not saved due to an aborted StartFileSaveNew event.');
}
$this->id = $this->insert();
if ($this->id === false) {
throw new ServerException('File/URL metadata could not be saved to the database.');
}
Event::handle('EndFileSaveNew', array($this));
}
/**
* Go look at a URL and possibly save data about it if it's new:
* - follow redirect chains and store them in file_redirection
@@ -103,16 +141,15 @@ class File extends Managed_DataObject
* - optionally save a file_to_post record
* - return the File object with the full reference
*
* @fixme refactor this mess, it's gotten pretty scary.
* @param string $given_url the URL we're looking at
* @param int $notice_id (optional)
* @param Notice $notice (optional)
* @param bool $followRedirects defaults to true
*
* @return mixed File on success, -1 on some errors
*
* @throws ServerException on failure
*/
public static function processNew($given_url, $notice_id=null, $followRedirects=true) {
public static function processNew($given_url, Notice $notice=null, $followRedirects=true) {
if (empty($given_url)) {
throw new ServerException('No given URL to process');
}
@@ -122,64 +159,18 @@ class File extends Managed_DataObject
throw new ServerException('No canonical URL from given URL to process');
}
$file = File::getKV('url', $given_url);
if (!$file instanceof File) {
// First check if we have a lookup trace for this URL already
$file_redir = File_redirection::getKV('url', $given_url);
if ($file_redir instanceof File_redirection) {
$file = File::getKV('id', $file_redir->file_id);
if (!$file instanceof File) {
// File did not exist, let's clean up the File_redirection entry
$file_redir->delete();
}
}
$redir = File_redirection::where($given_url);
$file = $redir->getFile();
// If we still don't have a File object, let's create one now!
if (!$file instanceof File) {
// @fixme for new URLs this also looks up non-redirect data
// such as target content type, size, etc, which we need
// for File::saveNew(); so we call it even if not following
// new redirects.
$redir_data = File_redirection::where($given_url);
if (is_array($redir_data)) {
$redir_url = $redir_data['url'];
} elseif (is_string($redir_data)) {
$redir_url = $redir_data;
$redir_data = array();
} else {
// TRANS: Server exception thrown when a URL cannot be processed.
throw new ServerException(sprintf(_("Cannot process URL '%s'"), $given_url));
}
// TODO: max field length
if ($redir_url === $given_url || strlen($redir_url) > 255 || !$followRedirects) {
// Save the File object based on our lookup trace
$file = File::saveNew($redir_data, $given_url);
} else {
// This seems kind of messed up... for now skipping this part
// if we're already under a redirect, so we don't go into
// horrible infinite loops if we've been given an unstable
// redirect (where the final destination of the first request
// doesn't match what we get when we ask for it again).
//
// Seen in the wild with clojure.org, which redirects through
// wikispaces for auth and appends session data in the URL params.
$file = self::processNew($redir_url, $notice_id, /*followRedirects*/false);
File_redirection::saveNew($redir_data, $file->id, $given_url);
}
}
if (!$file instanceof File) {
// This should only happen if File::saveNew somehow did not return a File object,
// though we have an assert for that in case the event there might've gone wrong.
// If anything else goes wrong, there should've been an exception thrown.
throw new ServerException('URL processing failed without new File object');
}
if (!$file instanceof File || empty($file->id)) {
// This should not happen
throw new ServerException('URL processing failed without new File object');
}
if (!empty($notice_id)) {
File_to_post::processNew($file->id, $notice_id);
if ($notice instanceof Notice) {
File_to_post::processNew($file, $notice);
}
return $file;
}
@@ -233,16 +224,20 @@ class File extends Managed_DataObject
return true;
}
public function getFilename()
{
if (!self::validFilename($this->filename)) {
// TRANS: Client exception thrown if a file upload does not have a valid name.
throw new ClientException(_("Invalid filename."));
}
return $this->filename;
}
// where should the file go?
static function filename(Profile $profile, $origname, $mimetype)
{
try {
$ext = common_supported_mime_to_ext($mimetype);
} catch (Exception $e) {
// We don't support this mimetype, but let's guess the extension
$ext = substr(strrchr($mimetype, '/'), 1);
}
$ext = self::guessMimeExtension($mimetype);
// Normalize and make the original filename more URL friendly.
$origname = basename($origname, ".$ext");
@@ -263,6 +258,21 @@ class File extends Managed_DataObject
return $filename;
}
static function guessMimeExtension($mimetype)
{
try {
$ext = common_supported_mime_to_ext($mimetype);
} catch (Exception $e) {
// We don't support this mimetype, but let's guess the extension
$matches = array();
if (!preg_match('/\/([a-z0-9]+)/', mb_strtolower($mimetype), $matches)) {
throw new Exception('Malformed mimetype: '.$mimetype);
}
$ext = $matches[1];
}
return mb_strtolower($ext);
}
/**
* Validation for as-saved base filenames
*/
@@ -303,7 +313,7 @@ class File extends Managed_DataObject
}
if (StatusNet::useHTTPS()) {
if (GNUsocial::useHTTPS()) {
$sslserver = common_config('attachments', 'sslserver');
@@ -350,28 +360,48 @@ class File extends Managed_DataObject
return $protocol.'://'.$server.$path.$filename;
}
static $_enclosures = array();
function getEnclosure(){
$enclosure = (object) array();
foreach (array('title', 'url', 'date', 'modified', 'size', 'mimetype') as $key) {
$enclosure->$key = $this->$key;
if (isset(self::$_enclosures[$this->getID()])) {
return self::$_enclosures[$this->getID()];
}
$needMoreMetadataMimetypes = array(null, 'application/xhtml+xml');
$enclosure = (object) array();
foreach (array('title', 'url', 'date', 'modified', 'size', 'mimetype', 'width', 'height') as $key) {
if ($this->$key !== '') {
$enclosure->$key = $this->$key;
}
}
$needMoreMetadataMimetypes = array(null, 'application/xhtml+xml', 'text/html');
if (!isset($this->filename) && in_array(common_bare_mime($enclosure->mimetype), $needMoreMetadataMimetypes)) {
// This fetches enclosure metadata for non-local links with unset/HTML mimetypes,
// which may be enriched through oEmbed or similar (implemented as plugins)
Event::handle('FileEnclosureMetadata', array($this, &$enclosure));
}
if (empty($enclosure->mimetype) || in_array(common_bare_mime($enclosure->mimetype), $needMoreMetadataMimetypes)) {
if (empty($enclosure->mimetype)) {
// This means we either don't know what it is, so it can't
// be shown as an enclosure, or it is an HTML link which
// does not link to a resource with further metadata.
throw new ServerException('Unknown enclosure mimetype, not enough metadata');
}
self::$_enclosures[$this->getID()] = $enclosure;
return $enclosure;
}
public function hasThumbnail()
{
try {
$this->getThumbnail();
} catch (Exception $e) {
return false;
}
return true;
}
/**
* Get the attachment's thumbnail record, if any.
* Make sure you supply proper 'int' typed variables (or null).
@@ -381,8 +411,12 @@ class File extends Managed_DataObject
* @param $crop bool Crop to the max-values' aspect ratio
*
* @return File_thumbnail
*
* @throws UseFileAsThumbnailException if the file is considered an image itself and should be itself as thumbnail
* @throws UnsupportedMediaException if, despite trying, we can't understand how to make a thumbnail for this format
* @throws ServerException on various other errors
*/
public function getThumbnail($width=null, $height=null, $crop=false, $force_still=true)
public function getThumbnail($width=null, $height=null, $crop=false, $force_still=true, $upscale=null)
{
// Get some more information about this file through our ImageFile class
$image = ImageFile::fromFileObject($this);
@@ -394,99 +428,67 @@ class File extends Managed_DataObject
}
}
if ($width === null) {
$width = common_config('thumbnail', 'width');
$height = common_config('thumbnail', 'height');
$crop = common_config('thumbnail', 'crop');
}
if ($height === null) {
$height = $width;
$crop = true;
}
// Get proper aspect ratio width and height before lookup
// We have to do it through an ImageFile object because of orientation etc.
// Only other solution would've been to rotate + rewrite uploaded files.
list($width, $height, $x, $y, $w, $h) =
$image->scaleToFit($width, $height, $crop);
$params = array('file_id'=> $this->id,
'width' => $width,
'height' => $height);
$thumb = File_thumbnail::pkeyGet($params);
if ($thumb instanceof File_thumbnail) {
return $thumb;
}
// throws exception on failure to generate thumbnail
$outname = "thumb-{$width}x{$height}-" . $image->filename;
$outpath = self::path($outname);
// The boundary box for our resizing
$box = array('width'=>$width, 'height'=>$height,
'x'=>$x, 'y'=>$y,
'w'=>$w, 'h'=>$h);
// Doublecheck that parameters are sane and integers.
if ($box['width'] < 1 || $box['width'] > common_config('thumbnail', 'maxsize')
|| $box['height'] < 1 || $box['height'] > common_config('thumbnail', 'maxsize')
|| $box['w'] < 1 || $box['x'] >= $image->width
|| $box['h'] < 1 || $box['y'] >= $image->height) {
// Fail on bad width parameter. If this occurs, it's due to algorithm in ImageFile->scaleToFit
common_debug("Boundary box parameters for resize of {$image->filepath} : ".var_export($box,true));
throw new ServerException('Bad thumbnail size parameters.');
}
common_debug(sprintf('Generating a thumbnail of File id==%u of size %ux%u', $this->id, $width, $height));
// Perform resize and store into file
$image->resizeTo($outpath, $box);
// Avoid deleting the original
if ($image->getPath() != self::path($image->filename)) {
$image->unlink();
}
return File_thumbnail::saveThumbnail($this->id,
self::url($outname),
$width, $height,
$outname);
return $image->getFileThumbnail($width, $height, $crop,
!is_null($upscale) ? $upscale : common_config('thumbnail', 'upscale'));
}
public function getPath()
{
return self::path($this->filename);
$filepath = self::path($this->filename);
if (!file_exists($filepath)) {
throw new FileNotFoundException($filepath);
}
return $filepath;
}
public function getUrl()
public function getUrl($prefer_local=true)
{
if (!empty($this->filename)) {
if ($prefer_local && !empty($this->filename)) {
// A locally stored file, so let's generate a URL for our instance.
$url = self::url($this->filename);
if ($url != $this->url) {
// For indexing purposes, in case we do a lookup on the 'url' field.
// also we're fixing possible changes from http to https, or paths
$this->updateUrl($url);
}
return $url;
return self::url($this->filename);
}
// No local filename available, return the URL we have stored
return $this->url;
}
static public function getByUrl($url)
{
$file = new File();
$file->urlhash = self::hashurl($url);
if (!$file->find(true)) {
throw new NoResultException($file);
}
return $file;
}
/**
* @param string $hashstr String of (preferrably lower case) hexadecimal characters, same as result of 'hash_file(...)'
*/
static public function getByHash($hashstr)
{
$file = new File();
$file->filehash = strtolower($hashstr);
if (!$file->find(true)) {
throw new NoResultException($file);
}
return $file;
}
public function updateUrl($url)
{
$file = File::getKV('url', $url);
$file = File::getKV('urlhash', self::hashurl($url));
if ($file instanceof File) {
throw new ServerException('URL already exists in DB');
}
$sql = 'UPDATE %1$s SET url=%2$s WHERE url=%3$s;';
$result = $this->query(sprintf($sql, $this->__table,
$sql = 'UPDATE %1$s SET urlhash=%2$s, url=%3$s WHERE urlhash=%4$s;';
$result = $this->query(sprintf($sql, $this->tableName(),
$this->_quote((string)self::hashurl($url)),
$this->_quote((string)$url),
$this->_quote((string)$this->url)));
$this->_quote((string)$this->urlhash)));
if ($result === false) {
common_log_db_error($this, 'UPDATE', __FILE__);
throw new ServerException("Could not UPDATE {$this->__table}.url");
throw new ServerException("Could not UPDATE {$this->tableName()}.url");
}
return $result;
@@ -502,9 +504,9 @@ class File extends Managed_DataObject
function blowCache($last=false)
{
self::blow('file:notice-ids:%s', $this->url);
self::blow('file:notice-ids:%s', $this->id);
if ($last) {
self::blow('file:notice-ids:%s;last', $this->url);
self::blow('file:notice-ids:%s;last', $this->id);
}
self::blow('file:notice-count:%d', $this->id);
}
@@ -570,6 +572,14 @@ class File extends Managed_DataObject
$thumbs->delete();
}
}
$f2p = new File_to_post();
$f2p->file_id = $this->id;
if ($f2p->find()) {
while ($f2p->fetch()) {
$f2p->delete();
}
}
}
// And finally remove the entry from the database
@@ -582,4 +592,87 @@ class File extends Managed_DataObject
return $title ?: null;
}
static public function hashurl($url)
{
if (empty($url)) {
throw new Exception('No URL provided to hash algorithm.');
}
return hash(self::URLHASH_ALG, $url);
}
static public function beforeSchemaUpdate()
{
$table = strtolower(get_called_class());
$schema = Schema::get();
$schemadef = $schema->getTableDef($table);
// 2015-02-19 We have to upgrade our table definitions to have the urlhash field populated
if (isset($schemadef['fields']['urlhash']) && isset($schemadef['unique keys']['file_urlhash_key'])) {
// We already have the urlhash field, so no need to migrate it.
return;
}
echo "\nFound old $table table, upgrading it to contain 'urlhash' field...";
$file = new File();
$file->query(sprintf('SELECT id, LEFT(url, 191) AS shortenedurl, COUNT(*) AS c FROM %1$s WHERE LENGTH(url)>191 GROUP BY shortenedurl HAVING c > 1', $schema->quoteIdentifier($table)));
print "\nFound {$file->N} URLs with too long entries in file table\n";
while ($file->fetch()) {
// We've got a URL that is too long for our future file table
// so we'll cut it. We could save the original URL, but there is
// no guarantee it is complete anyway since the previous max was 255 chars.
$dupfile = new File();
// First we find file entries that would be duplicates of this when shortened
// ... and we'll just throw the dupes out the window for now! It's already so borken.
$dupfile->query(sprintf('SELECT * FROM file WHERE LEFT(url, 191) = "%1$s"', $file->shortenedurl));
// Leave one of the URLs in the database by using ->find(true) (fetches first entry)
if ($dupfile->find(true)) {
print "\nShortening url entry for $table id: {$file->id} [";
$orig = clone($dupfile);
$dupfile->url = $file->shortenedurl; // make sure it's only 191 chars from now on
$dupfile->update($orig);
print "\nDeleting duplicate entries of too long URL on $table id: {$file->id} [";
// only start deleting with this fetch.
while($dupfile->fetch()) {
print ".";
$dupfile->delete();
}
print "]\n";
} else {
print "\nWarning! URL suddenly disappeared from database: {$file->url}\n";
}
}
echo "...and now all the non-duplicates which are longer than 191 characters...\n";
$file->query('UPDATE file SET url=LEFT(url, 191) WHERE LENGTH(url)>191');
echo "\n...now running hacky pre-schemaupdate change for $table:";
// We have to create a urlhash that is _not_ the primary key,
// transfer data and THEN run checkSchema
$schemadef['fields']['urlhash'] = array (
'type' => 'varchar',
'length' => 64,
'not null' => false, // this is because when adding column, all entries will _be_ NULL!
'description' => 'sha256 of destination URL (url field)',
);
$schemadef['fields']['url'] = array (
'type' => 'text',
'description' => 'destination URL after following possible redirections',
);
unset($schemadef['unique keys']);
$schema->ensureTable($table, $schemadef);
echo "DONE.\n";
$classname = ucfirst($table);
$tablefix = new $classname;
// urlhash is hash('sha256', $url) in the File table
echo "Updating urlhash fields in $table table...";
// Maybe very MySQL specific :(
$tablefix->query(sprintf('UPDATE %1$s SET %2$s=%3$s;',
$schema->quoteIdentifier($table),
'urlhash',
// The line below is "result of sha256 on column `url`"
'SHA2(url, 256)'));
echo "DONE.\n";
echo "Resuming core schema upgrade...";
}
}
+165 -80
Ver Arquivo
@@ -29,7 +29,8 @@ class File_redirection extends Managed_DataObject
/* the code below is auto generated do not remove the above tag */
public $__table = 'file_redirection'; // table name
public $url; // varchar(255) primary_key not_null
public $urlhash; // varchar(64) primary_key not_null
public $url; // text
public $file_id; // int(4)
public $redirections; // int(4)
public $httpcode; // int(4)
@@ -38,29 +39,37 @@ class File_redirection extends Managed_DataObject
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
protected $file; /* Cache the associated file sometimes */
public static function schemaDef()
{
return array(
'fields' => array(
'url' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'description' => 'short URL (or any other kind of redirect) for file (id)'),
'urlhash' => array('type' => 'varchar', 'length' => 64, 'not null' => true, 'description' => 'sha256 hash of the URL'),
'url' => array('type' => 'text', 'description' => 'short URL (or any other kind of redirect) for file (id)'),
'file_id' => array('type' => 'int', 'description' => 'short URL for what URL/file'),
'redirections' => array('type' => 'int', 'description' => 'redirect count'),
'httpcode' => array('type' => 'int', 'description' => 'HTTP status code (20x, 30x, etc.)'),
'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
),
'primary key' => array('url'),
'primary key' => array('urlhash'),
'foreign keys' => array(
'file_redirection_file_id_fkey' => array('file' => array('file_id' => 'id')),
),
);
}
static public function getByUrl($url)
{
return self::getByPK(array('urlhash' => File::hashurl($url)));
}
static function _commonHttp($url, $redirs) {
$request = new HTTPClient($url);
$request->setConfig(array(
'connect_timeout' => 10, // # seconds to wait
'max_redirs' => $redirs, // # max number of http redirections to follow
'follow_redirects' => true, // Follow redirects
'follow_redirects' => false, // We follow redirects ourselves in lib/httpclient.php
'store_body' => false, // We won't need body content here.
));
return $request;
@@ -87,7 +96,7 @@ class File_redirection extends Managed_DataObject
* size (optional): byte size from Content-Length header
* time (optional): timestamp from Last-Modified header
*/
public function lookupWhere($short_url, $redirs = 10, $protected = false) {
static function lookupWhere($short_url, $redirs = 10, $protected = false) {
if ($redirs < 0) return false;
if(strpos($short_url,'://') === false){
@@ -111,21 +120,26 @@ class File_redirection extends Managed_DataObject
// no content it'll be cheap. :)
$request = self::_commonHttp($short_url, $redirs);
$response = $request->send();
} elseif (400 == $response->getStatus()) {
throw new Exception('Got error 400 on HEAD request, will not go further.');
}
} catch (Exception $e) {
// Invalid URL or failure to reach server
common_log(LOG_ERR, "Error while following redirects for $short_url: " . $e->getMessage());
return $short_url;
}
if ($response->getRedirectCount() && File::isProtected($response->getUrl())) {
// Bump back up the redirect chain until we find a non-protected URL
return self::lookupWhere($short_url, $response->getRedirectCount() - 1, true);
// if last url after all redirections is protected,
// use the url before it in the redirection chain
if ($response->getRedirectCount() && File::isProtected($response->getEffectiveUrl())) {
$return_url = $response->redirUrls[$response->getRedirectCount()-1];
} else {
$return_url = $response->getEffectiveUrl();
}
$ret = array('code' => $response->getStatus()
, 'redirects' => $response->getRedirectCount()
, 'url' => $response->getUrl());
, 'url' => $return_url);
$type = $response->getHeader('Content-Type');
if ($type) $ret['type'] = $type;
@@ -148,40 +162,70 @@ class File_redirection extends Managed_DataObject
*
* @param string $in_url
* @param boolean $discover true to attempt dereferencing the redirect if we don't know it already
* @return mixed one of:
* string - target URL, if this is a direct link or a known redirect
* array - redirect info if this is an *unknown* redirect:
* associative array with the following elements:
* code: HTTP status code
* redirects: count of redirects followed
* url: URL string of final target
* type (optional): MIME type from Content-Type header
* size (optional): byte size from Content-Length header
* time (optional): timestamp from Last-Modified header
* @return File_redirection
*/
public function where($in_url, $discover=true) {
// let's see if we know this...
$a = File::getKV('url', $in_url);
static function where($in_url, $discover=true) {
$redir = new File_redirection();
$redir->url = $in_url;
$redir->urlhash = File::hashurl($redir->url);
$redir->redirections = 0;
if (!empty($a)) {
// this is a direct link to $a->url
return $a->url;
} else {
$b = File_redirection::getKV('url', $in_url);
if (!empty($b)) {
// this is a redirect to $b->file_id
$a = File::getKV('id', $b->file_id);
return $a->url;
try {
$r = File_redirection::getByUrl($in_url);
if($r instanceof File_redirection) {
try {
$f = File::getKV('id',$r->file_id);
$r->file = $f;
$r->redir_url = $f->url;
} catch (NoResultException $e) {
// Invalid entry, delete and run again
common_log(LOG_ERR, "Could not find File with id=".$r->file_id." referenced in File_redirection, deleting File redirection entry and creating new File and File_redirection entries.");
$r->delete();
return self::where($in_url);
}
return $r;
}
} catch (NoResultException $e) {
try {
$f = File::getByUrl($in_url);
$redir->file_id = $f->id;
$redir->file = $f;
return $redir;
} catch (NoResultException $e) {
// Oh well, let's keep going
}
}
if ($discover) {
$ret = File_redirection::lookupWhere($in_url);
return $ret;
} else {
// No manual dereferencing; leave the unknown URL as is.
return $in_url;
if ($discover) {
$redir_info = File_redirection::lookupWhere($in_url);
if(is_string($redir_info)) {
$redir_info = array('url' => $redir_info);
}
// Save the file if we don't have it already
$redir->file = File::saveNew($redir_info,$redir_info['url']);
// If this is a redirection, save it
// (if it hasn't been saved yet by some other process while we we
// were running lookupWhere())
if($redir_info['url'] != $in_url) {
try {
$file_redir = File_redirection::getByUrl($in_url);
} catch (NoResultException $e) {
$file_redir = new File_redirection();
$file_redir->urlhash = File::hashurl($in_url);
$file_redir->url = $in_url;
$file_redir->file_id = $redir->file->getID();
$file_redir->insert();
$file_redir->redir_url = $redir->file->url;
}
$file_redir->file = $redir->file;
return $file_redir;
}
}
return $redir;
}
/**
@@ -198,7 +242,7 @@ class File_redirection extends Managed_DataObject
* @param User $user whose shortening options to use; defaults to the current web session user
* @return string
*/
function makeShort($long_url, $user=null)
static function makeShort($long_url, $user=null)
{
$canon = File_redirection::_canonUrl($long_url);
@@ -206,11 +250,7 @@ class File_redirection extends Managed_DataObject
// Did we get one? Is it shorter?
if (!empty($short_url)) {
return $short_url;
} else {
return $long_url;
}
return !empty($short_url) ? $short_url : $long_url;
}
/**
@@ -227,55 +267,37 @@ class File_redirection extends Managed_DataObject
* @return string
*/
function forceShort($long_url, $user)
static function forceShort($long_url, $user)
{
$canon = File_redirection::_canonUrl($long_url);
$short_url = File_redirection::_userMakeShort($canon, $user, true);
// Did we get one? Is it shorter?
if (!empty($short_url)) {
return $short_url;
} else {
return $long_url;
}
return !empty($short_url) ? $short_url : $long_url;
}
function _userMakeShort($long_url, User $user=null, $force = false) {
static function _userMakeShort($long_url, User $user=null, $force = false) {
$short_url = common_shorten_url($long_url, $user, $force);
if (!empty($short_url) && $short_url != $long_url) {
$short_url = (string)$short_url;
// store it
$file = File::getKV('url', $long_url);
if ($file instanceof File) {
$file_id = $file->id;
} else {
try {
$file = File::getByUrl($long_url);
} catch (NoResultException $e) {
// Check if the target URL is itself a redirect...
$redir_data = File_redirection::where($long_url);
if (is_array($redir_data)) {
// We haven't seen the target URL before.
// Save file and embedding data about it!
$file = File::saveNew($redir_data, $long_url);
$file_id = $file->id;
} else if (is_string($redir_data)) {
// The file is a known redirect target.
$file = File::getKV('url', $redir_data);
if (empty($file)) {
// @fixme should we save a new one?
// this case was triggering sometimes for redirects
// with unresolvable targets; found while fixing
// "can't linkify" bugs with shortened links to
// SSL sites with cert issues.
return null;
}
$file_id = $file->id;
}
// This should already have happened in processNew in common_shorten_url()
$redir = File_redirection::where($long_url);
$file = $redir->file;
}
$file_redir = File_redirection::getKV('url', $short_url);
if (!$file_redir instanceof File_redirection) {
$file_redir = new File_redirection;
// Now we definitely have a File object in $file
try {
$file_redir = File_redirection::getByUrl($short_url);
} catch (NoResultException $e) {
$file_redir = new File_redirection();
$file_redir->urlhash = File::hashurl($short_url);
$file_redir->url = $short_url;
$file_redir->file_id = $file_id;
$file_redir->file_id = $file->getID();
$file_redir->insert();
}
return $short_url;
@@ -295,7 +317,7 @@ class File_redirection extends Managed_DataObject
* @param string $default_scheme if given a bare link; defaults to 'http://'
* @return string
*/
function _canonUrl($in_url, $default_scheme = 'http://') {
static function _canonUrl($in_url, $default_scheme = 'http://') {
if (empty($in_url)) return false;
$out_url = $in_url;
$p = parse_url($out_url);
@@ -307,6 +329,8 @@ class File_redirection extends Managed_DataObject
$out_url = str_replace('.-()', '', $out_url);
break;
// non-HTTP schemes, so no redirects
case 'bitcoin':
case 'mailto':
case 'aim':
case 'jabber':
@@ -314,6 +338,16 @@ class File_redirection extends Managed_DataObject
// don't touch anything
break;
// URLs without domain name, so no redirects
case 'magnet':
// don't touch anything
break;
// URLs with coordinates, not browsable domain names
case 'geo':
// don't touch anything
break;
default:
$out_url = $default_scheme . ltrim($out_url, '/');
$p = parse_url($out_url);
@@ -332,12 +366,63 @@ class File_redirection extends Managed_DataObject
return $out_url;
}
function saveNew($data, $file_id, $url) {
static function saveNew($data, $file_id, $url) {
$file_redir = new File_redirection;
$file_redir->urlhash = File::hashurl($url);
$file_redir->url = $url;
$file_redir->file_id = $file_id;
$file_redir->redirections = intval($data['redirects']);
$file_redir->httpcode = intval($data['code']);
$file_redir->insert();
}
static public function beforeSchemaUpdate()
{
$table = strtolower(get_called_class());
$schema = Schema::get();
$schemadef = $schema->getTableDef($table);
// 2015-02-19 We have to upgrade our table definitions to have the urlhash field populated
if (isset($schemadef['fields']['urlhash']) && in_array('urlhash', $schemadef['primary key'])) {
// We already have the urlhash field, so no need to migrate it.
return;
}
echo "\nFound old $table table, upgrading it to contain 'urlhash' field...";
// We have to create a urlhash that is _not_ the primary key,
// transfer data and THEN run checkSchema
$schemadef['fields']['urlhash'] = array (
'type' => 'varchar',
'length' => 64,
'not null' => true,
'description' => 'sha256 hash of the URL',
);
$schemadef['fields']['url'] = array (
'type' => 'text',
'description' => 'short URL (or any other kind of redirect) for file (id)',
);
unset($schemadef['primary key']);
$schema->ensureTable($table, $schemadef);
echo "DONE.\n";
$classname = ucfirst($table);
$tablefix = new $classname;
// urlhash is hash('sha256', $url) in the File table
echo "Updating urlhash fields in $table table...";
// Maybe very MySQL specific :(
$tablefix->query(sprintf('UPDATE %1$s SET %2$s=%3$s;',
$schema->quoteIdentifier($table),
'urlhash',
// The line below is "result of sha256 on column `url`"
'SHA2(url, 256)'));
echo "DONE.\n";
echo "Resuming core schema upgrade...";
}
public function getFile() {
if(empty($this->file) && $this->file_id) {
$this->file = File::getKV('id', $this->file_id);
}
return $this->file;
}
}

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais